aspects of compilation for reversible programming
play

Aspects of Compilation for Reversible Programming Languages Holger - PowerPoint PPT Presentation

Aspects of Compilation for Reversible Programming Languages Holger Bock Axelsen DIKU, Dept. of Computer Science, University of Copenhagen www.diku.dk/~funkstar QPCW @ IQC, U Waterloo, June 11, 2015 Overview Setup Quick language primers


  1. Aspects of Compilation for Reversible Programming Languages Holger Bock Axelsen DIKU, Dept. of Computer Science, University of Copenhagen www.diku.dk/~funkstar QPCW @ IQC, U Waterloo, June 11, 2015

  2. Overview Setup Quick language primers Janus PISA Complications for compilation Assorted techniques Assignment statements Control flow operators Procedure (un)calls Structured heap data Conclusion 2

  3. Danger! 3

  4. The view from Olympus [CF’08] procedure update_a if a < b then a += b Algorithms call update_b else a −= b * 2 + c uncall update_b High−level fi a > b languages BRA 6 SWBR $1 Machine code NEG $3 XORI $3 42 ADD $2 $3 XORI $3 42 Computer BRA −6 architecture [CSR’07] Gate level Physical Implementation (Cl-)aim: reversibility everywhere . 4

  5. Close-up ... n x1 x2 BRA fib bot SUBI $1 1 procedure fib EXCH $2 $1 if n=0 fib: SWAPBR $2 then x1 += 1 NEG $2 x2 += 1 EXCH $2 $1 else n -= 1 ADDI $1 1 call fib XORI $5 n x1 += x2 EXCH $6 $5 x1 <=> x2 XOR $4 $6 fi x1=x2 EXCH $6 $5 XORI $5 n procedure main ADDI $6 0 x1 += 5 SLTX $3 $4 $6 x2 += 8 if5: BEQ $3 $0 if6 uncall fib ... 5

  6. Source primer: Janus (dev@Caltech, early 80s) Janus : C-style reversible programming on arrays Program d ∗ ( procedure id s ) + ::= p ::= x | x [ c ] d Statements s ::= x ⊕ = e | x [ e ] ⊕ = e | call id | uncall id | if e then s else s fi e | from e do s loop s until e | skip | s s Expressions, operators, constants e ::= c | x | x [ e ] | e ⊗ e ⊗ ::= ⊕ | * | && | <= | · · · ⊕ ::= + | - | ^ c ::= · · · | -1 | 0 | 1 | · · · 6

  7. Janus sticky points n x1 x2 Key points: procedure fib if n=0 then x1 += 1 Structured: translate by x2 += 1 recursive descent else n -= 1 Every assignment call fib reversibly updates array x1 += x2 cells x1 <=> x2 Assertions enforce fi x1=x2 reversibility at run-time Uncalls provide direct procedure main access to inverse x1 += 5 semantics x2 += 8 uncall fib 7

  8. Target primer: PISA (dev@MIT, late 90s) RISC-style Von Neuman architecture (think MIPS) 32 GPRs of 32 bits each Reversible data and control instructions 8

  9. PISA examples: data ops Inv ( i ) Effect ( i ) i reg d ← reg d + reg s ADD reg d reg s SUB SUB reg d reg s ADD reg d ← reg d − reg s reg d ← reg d ⊕ ( reg s ∧ reg t ) ANDX reg d reg s reg t ANDX XOR reg d reg s XOR reg d ← reg d ⊕ reg s reg d ← reg d < RL reg d reg s RR < rotate reg s EXCH reg d reg p reg d ↔ M ( reg p ) EXCH 9

  10. PISA examples: control ops i Inv ( i ) Effect ( i ) BRA n BRA br ← br + n br ← br + ( reg s = reg t ? n : 0) BEQ reg s reg t n BEQ BGTZ reg s n BGTZ br ← br + ( reg s > 0 ? n : 0) reg d ↔ br SWAPBR reg d SWAPBR RBRA n RBRA like BRA but changes direction 10

  11. Paired branches for jumps PC update routine if br=0 then pc += 1 else pc += br fi br=0 11

  12. Complications for compilation How does source & target reversibility make our task harder? Correctness: The translation must be strictly semantics-preserving, so no (final) garbage. Usual transformations for reversible embeddings - tracing, compute-copy-uncompute - are not clean. (But still useful!) Efficiency: The translation should preserve complexities. Bennett’s simulation (for injective functions) is neither time nor space-preserving Granularity: Different atomic levels of reversibility: Janus is ‘coarser’ than PISA, and relies on irreversible expression evaluation. This must be simulated reversibly in PISA, using ancillary space, garbage, etc. 12

  13. A common RC/QC goal: clean ancillae Ancillary space (unbounded) start halt (a) . . . . . . . . . Time e − 1 e − 1 e − 1 e 1 e 4 e 2 2 4 1 Ancillary space max( | e 1 | , | e 2 | , . . . , | e k | ) start (bounded) halt (b) . . . . . . Time e − 1 e − 1 e − 1 e − 1 e 1 e 4 e 2 e 7 1 4 2 7 13

  14. Translation of x += exp Most expression operators can be simulated, but... Evaluating exp alone is irreversible: evaluating expressions reversibly generates garbage. Uncomputation (removing the garbage) is easy: Inversion of the PISA code for evaluating exp (w/ garbage.) Translate by a clean compute-“copy”-uncompute. (1) < code for r e ← [ [ exp ] ] g > ; Generates garbage G (2) ADD r x r e ; Update variable (3) ; Removes garbage G < inverse code of 1 > No garbage generated: the variables in exp are supposed to be conserved, and we didn’t consume an ancilla for the result! 14

  15. Control flow operators ✲ s 1 ✲ s 1 ✗ ✔ ✗ ✔ ❄ ❄ t t � ❅ � ❅ ✲� ❅ ✲ ✲ � ❅ ✲ t t e 1 e 2 e 1 e 2 ❅ ❅ � ✖ ✕ ✖ ✕ ❅ ❅ � � � f ✻ ✻ f f f ✲ s 2 ✛ s 2 if e 1 then s 1 else s 2 fi e 2 from e 1 do s 1 loop s 2 until e 2 15

  16. Compiling if-then-else-fi : decompose ✲ B 1 ✗ ✔ ❄ t t � ❅ ✲� ❅ ✲ e 1 e 2 ❅ ❅ � ✖ ✕ � ✻ f f ✲ B 2 = = = ⇒ ⇒ ⇒ ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t � ❅ ✲� ❅ ✲ e 1 e 2 ❅ ❅ � ✖ ✕ � ✻ f f ✲ ✲ B 2 ✲ 16

  17. Compiling if-then-else-fi : branches and test < code for r e 1 ← [ [ e 1 ] ] c > ; Evaluate e 1 ; Jump if [ [ e 1 ] ] = 0 test : BEQ r e 1 r 0 test false XORI r e 1 1 ; Clear r e 1 < code for B 1 branch > . . . ; Receive jump test false : BRA test < code for B 2 branch > . . . ⇒ ⇒ ⇒ = = = ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t � ❅ ✲� ❅ ✲ e 1 e 2 ❅ ❅ � ✖ ✕ � ✻ f f ✲ ✲ B 2 ✲ 17

  18. Compiling if-then-else-fi : assertion < code for r e 1 ← [ [ e 1 ] ] c > ; Evaluate e 1 ; Jump if [ [ e 1 ] ] = 0 test : BEQ r e 1 r 0 test false XORI r e 1 1 ; Clear r e 1 < code for B 1 branch > . . . ; Receive jump test false : BRA test < code for B 2 branch > . . . ⇒ ⇒ ⇒ = = = ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t (inversion) � ❅ ✲� ❅ ✲ ⇐ ⇒ e 1 e 2 ❅ ❅ � ✖ ✕ � ✻ f f ✲ ✲ B 2 ✲ 18

  19. Compiling if-then-else-fi : assertion . . . < code for B 1 branch > XORI r e 2 1 ; Set r e 2 = 1 ; Jump assert true : BRA assert . . . < code for B 2 branch > assert : BNE r e 2 r 0 assert true ; Receive jump < code for r e 2 → [ [ e 2 ] ] c > ; Unevaluate e 2 ⇒ ⇒ ⇒ = = = ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t (inversion) � ❅ ✲� ❅ ✲ ⇐ ⇒ e 1 e 2 ❅ ❅ � ✖ ✕ � ✻ f f ✲ ✲ B 2 ✲ 18

  20. Compiling if-then-else-fi : compose < code for r e 1 ← [ [ e 1 ] ] c > ; Evaluate e 1 test : BEQ r e 1 r 0 test false ; Jump if [ [ e 1 ] ] = 0 ; Clear r e 1 XORI r e 1 1 < code for B 1 branch > ; Set r e 2 = 1 XORI r e 2 1 assert true : BRA assert ; Jump ; Receive jump test false : BRA test < code for B 2 branch > assert BNE r e 2 r 0 assert true ; Receive jump : < code for r e 2 → [ [ e 2 ] ] c > ; Unevaluate e 2 ⇒ ⇒ ⇒ = = = ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t � ❅ ✲� ❅ ✲ e 1 e 2 ❅ ❅ � ✖ ✕ � f ✻ f ✲ B 2 ✲ ✲ 19

  21. Compiling if-then-else-fi : error check BNE r e 1 r 0 error ; Error check < code for r e 1 ← [ [ e 1 ] ] c > ; Evaluate e 1 test : BEQ r e 1 r 0 test false ; Jump if [ [ e 1 ] ] = 0 ; Clear r e 1 XORI r e 1 1 < code for B 1 branch > ; Set r e 2 = 1 XORI r e 2 1 assert true : BRA assert ; Jump ; Receive jump test false : BRA test < code for B 2 branch > ; Receive jump assert : BNE r e 2 r 0 assert true < code for r e 2 → [ [ e 2 ] ] c > ; Unevaluate e 2 ; Error check BNE r e 2 r 0 error ⇒ ⇒ ⇒ = = = ✲ ✲ B 1 ✲ ✗ ✔ ❄ t t � ❅ ✲� ❅ ✲ e 1 e 2 ❅ ❅ � ✖ ✕ � f ✻ f ✲ ✲ B 2 ✲ 20

  22. Procedure (un)calls Recursion: Add call stack to subroutine convention [Frank99] Code sharing for uncalls: Just one definition of f in the target 21

  23. Other language paradigms work, too: RFUN mirror t � case t of Cons ( a , b ) let c = mirror a in → let d = mirror b in Cons ( d , c ) Nil Nil → Mirror function applied to Cons ( Nil , Cons ( Nil , Nil )): Cons Cons Nil Cons Cons Nil Nil Nil Nil Nil So the result is Cons ( Cons ( Nil , Nil ) , Nil ). Key problem: How can constructor terms be represented in a reversible machine? How can they be manipulated? Requires a heap. (As in ‘heap memory management’, not the ‘heap data structure.’) 22

  24. Static heap representation — pointer trees bottom of heap x : Nil y : Nil environment Nil x �→ Nil Cons y �→ Cons free list pointer Cons Nil Cons Nil Nil Nil heap pointer free space The dynamics are a bit harder, but RFUN compiles to PISA. (In fact, a clever way using “hash-consing” is possible.) 23

  25. Conclusion Translation between reversible languages: Extensionally clean - no garbage output at program level Intensionally clean - no garbage across statements Efficient - complexities of source program preserved Generic - reversible updates and general CFOs can be translated, richer data types possible Surprises: General register allocation is difficult Even simple control flow is somewhat involved to translate Hidden irreversibilities are costly, rely on general reversibilizations Check www.diku.dk/~funkstar for references, and topps.diku.dk/pirc for interpreters. Thanks! 24

Recommend


More recommend