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

aspects of compilation for reversible programming
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 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

slide-2
SLIDE 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

slide-3
SLIDE 3

Danger!

3

slide-4
SLIDE 4

The view from Olympus

a += b NEG $3 XORI $3 42 BRA −6 XORI $3 42 BRA 6 ADD $2 $3 SWBR $1 if a < b then update_a else a −= b * 2 + c call fi uncall update_b a > b update_b procedure

Algorithms High−level languages Computer Machine code

[CSR’07] [CF’08]

Implementation Physical Gate level architecture

(Cl-)aim: reversibility everywhere.

4

slide-5
SLIDE 5

Close-up

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

5

slide-6
SLIDE 6

Source primer: Janus (dev@Caltech, early 80s)

Janus: C-style reversible programming on arrays

Program p ::= d∗ (procedure id s)+ d ::= x | x[c] 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

slide-7
SLIDE 7

Janus sticky points

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

7

slide-8
SLIDE 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

slide-9
SLIDE 9

PISA examples: data ops

i Inv(i) Effect(i) ADD regd regs SUB regd ← regd + regs SUB regd regs ADD regd ← regd − regs ANDX regd regs regt ANDX regd ← regd ⊕ (regs ∧ regt) XOR regd regs XOR regd ← regd ⊕ regs RL regd regs RR regd ← regd < <rotate regs EXCH regd regp EXCH regd ↔ M(regp)

9

slide-10
SLIDE 10

PISA examples: control ops

i Inv(i) Effect(i) BRA n BRA br ← br + n BEQ regs regt n BEQ br ← br + (regs = regt ? n : 0) BGTZ regs n BGTZ br ← br + (regs > 0 ? n : 0) SWAPBR regd SWAPBR regd ↔ br RBRA n RBRA like BRA but changes direction

10

slide-11
SLIDE 11

Paired branches for jumps

PC update routine if br=0 then pc += 1 else pc += br fi br=0

11

slide-12
SLIDE 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

slide-13
SLIDE 13

A common RC/QC goal: clean ancillae

Ancillary space Time e2 start Time e1 e4 e2 e−1

2

e−1

1

e−1

4

e−1

7

e1 e−1

2

e−1

4

e−1

1

e4 e7 . . . . . . . . . . . . . . . (a) (b) halt start halt (unbounded) (bounded) max(|e1|, |e2|, . . . , |ek |) Ancillary space 13

slide-14
SLIDE 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 re ← [ [exp] ]g > ; Generates garbage G (2) ADD rx re ; Update variable (3) <inverse code of 1> ; Removes garbage G No garbage generated: the variables in exp are supposed to be conserved, and we didn’t consume an ancilla for the result!

14

slide-15
SLIDE 15

Control flow operators

e1

t f

✲ s1 ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✲ s2 ✻ ✲ ✗ ✖ ✔ ✕

e1

t f

✲ s1 ❄

e2

t f

s2

✻ ✲

if e1 then s1 else s2 fi e2 from e1 do s1 loop s2 until e2

15

slide-16
SLIDE 16

Compiling if-then-else-fi: decompose

e1

t f

✲ B1 ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✲ B2 ✻

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲ ✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

16

slide-17
SLIDE 17

Compiling if-then-else-fi: branches and test

<code for re1 ← [ [e1] ]c > ; Evaluate e1 test : BEQ re1 r0 testfalse ; Jump if [ [e1] ] = 0 XORI re1 1 ; Clear re1 <code for B1 branch> . . . testfalse : BRA test ; Receive jump <code for B2 branch> . . .

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲ ✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

17

slide-18
SLIDE 18

Compiling if-then-else-fi: assertion

<code for re1 ← [ [e1] ]c > ; Evaluate e1 test : BEQ re1 r0 testfalse ; Jump if [ [e1] ] = 0 XORI re1 1 ; Clear re1 <code for B1 branch> . . . testfalse : BRA test ; Receive jump <code for B2 branch> . . .

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲

(inversion)

⇐ ⇒

✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

18

slide-19
SLIDE 19

Compiling if-then-else-fi: assertion

. . . <code for B1 branch> XORI re2 1 ; Set re2 = 1 asserttrue : BRA assert ; Jump . . . <code for B2 branch> assert : BNE re2 r0 asserttrue ; Receive jump <code for re2 → [ [e2] ]c > ; Unevaluate e2

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲

(inversion)

⇐ ⇒

✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

18

slide-20
SLIDE 20

Compiling if-then-else-fi: compose

<code for re1 ← [ [e1] ]c > ; Evaluate e1 test : BEQ re1 r0 testfalse ; Jump if [ [e1] ] = 0 XORI re1 1 ; Clear re1 <code for B1 branch> XORI re2 1 ; Set re2 = 1 asserttrue : BRA assert ; Jump testfalse : BRA test ; Receive jump <code for B2 branch> assert : BNE re2 r0 asserttrue ; Receive jump <code for re2 → [ [e2] ]c > ; Unevaluate e2

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲ ✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

19

slide-21
SLIDE 21

Compiling if-then-else-fi: error check

BNE re1 r0 error ; Error check <code for re1 ← [ [e1] ]c > ; Evaluate e1 test : BEQ re1 r0 testfalse ; Jump if [ [e1] ] = 0 XORI re1 1 ; Clear re1 <code for B1 branch> XORI re2 1 ; Set re2 = 1 asserttrue : BRA assert ; Jump testfalse : BRA test ; Receive jump <code for B2 branch> assert : BNE re2 r0 asserttrue ; Receive jump <code for re2 → [ [e2] ]c > ; Unevaluate e2 BNE re2 r0 error ; Error check

= ⇒ = ⇒ = ⇒

e1

t f

✲ ✲ ✲ B1 ✲ ✲ B2 ✲ ❄ ✗ ✖ ✔ ✕

e2

t f

✲ ✻

20

slide-22
SLIDE 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

slide-23
SLIDE 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)):

Nil Cons Cons Nil Nil Cons Cons 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

slide-24
SLIDE 24

Static heap representation — pointer trees

x → Nil y →

Nil Cons Cons Nil Nil Cons Cons Nil Nil Nil Nil bottom of heap heap pointer free space x : y : environment free list pointer

The dynamics are a bit harder, but RFUN compiles to PISA. (In fact, a clever way using “hash-consing” is possible.)

23

slide-25
SLIDE 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