290 likes | 429 Views
Sudipta Kundu Zachary Tatlock Sorin Lerner. Proving Optimizations Correct using Parameterized Program Equivalence. University of California, San Diego. Compiler Correctness. Difficult to develop reliable compilers: large, complex programs take a long time to mature
E N D
SudiptaKundu Zachary Tatlock Sorin Lerner Proving Optimizations Correctusing Parameterized Program Equivalence University of California, San Diego
Compiler Correctness • Difficult to develop reliable compilers: • large, complex programs • take a long time to mature • Consequence: buggy compilers, but also … • hinders development of new languages, architectures • discourages user from extending compiler • Focus on correctness of compiler optimizations • many intricate opts, unexpected interactions • turning off optimizations often no longer an option
Focus on Automated Techniques Existing Techniques • a prioriCorrectness • prove correctness • before compiler runs • once and for all [Necula 00] Compcert [Leroy et al.] Verified TV [Tristan et al.] TVOC [Zuck et al.] [Pnueli et al.] Rhodium [Lerner et al.] • Translation Validation • prove equivalence • for each transformation • every compiler execution
Focus on Automated Techniques Our Approach: Expressive Power Complex Loop Opts [Necula 00] Key Insight: Adapt Translation Validation to once-and-for-all setting TVOC [Zuck et al.] Rhodium [Lerner et al.] One-to-one Rewrites complex loop opts + once-and-for-all correctness Scope of Guarantee Verify Compiler Run Verify Compiler
Generalize to Parameterized Progs Translation Validation Input PProg Equivalence Checking Output PProg k := 0 while(k<100){ a[k] += k k++ } Generalize to Parameterized Programs Input Prog Output Prog
Generalize to Parameterized Progs Input PProg Equivalence Checking Output PProg I := 0 while(I<100){ a[k] += I I++ } Generalize to Parameterized Programs Input Prog Output Prog
Generalize to Parameterized Progs Input PProg Equivalence Checking Output PProg I := 0 while(I<E){ a[k] += I I++ } Generalize to Parameterized Programs Input Prog Output Prog
Generalize to Parameterized Progs Input PProg Equivalence Checking Optimization Output PProg I := 0 while(I<E){ S I++ } I := 0 while(I<E){ S I++ } Generalize to Parameterized Programs Input Prog Optimization Instance Output Prog
Generalize to Parameterized Progs Input PProg Equivalence Checking Parameterized Equivalence Checking Optimization Output PProg Generalize to Parameterized Programs Input Prog Optimization Instance Output Prog
Contributions 1 Input PProg Parameterized Equivalence Checking Optimization Output PProg 2 3 • Parameterized Equivalence Checking (PEC) • proves opts correct statically and automatically • can reason about many-to-many opts • Expressed and proved a variety of opts correct • which Rhodium could not have proven correct • software pipelining and other complex loop opts
Parameterized Rewrite Rules I := 0 while(I < E){ S I++ } I := 0 while(I<E-1){ S I++ } S I++ • where: • E > 0 • S does not modify I, E • Loop Peeling • move iter out of loop • ids range over: • I: variable • E: expression • S: statement • Shift final iteration after loop • Side conditions indicate when rewrite safe
Applying Rewrite Rules I := 0 while(I < E){ S I++ } I := 0 while(I<E-1){ S I++ } S I++ • where: • E > 0 • S does not modify I, E • Divisible by 3 • Directly unroll by 3 k := 0 while(k<99){ a[k] += k k++ } a[k] += k k++ k := 0 while(k<100){ a[k] += k k++ } • where: • 100 > 0 • a[k] += k • does not modify k,100 • Not divisible by 3 • Hard to unroll by 3 • Enable loop unrolling • Apply Rewrite • Match parameters • Check side conds • Rewrite
Checking Correctness Parameterized Equivalence Checking OPT
Checking Correctness Generalization of [ Necula 00 ] Relate Relate OPT OR Permute Generalization of [ Zuck et al. 04]
Checking Rewrite Rules • σ1=σ2 • Programs equivalent: • Consider CFGs • Start in equal states • End in equal states I := 0 while(I < E){ S I++ } I := 0 while(I<E-1){ S I++ } S I++ I:=0 I:=0 I<E I≥E I<E-1 I≥E-1 S S • where: • E> 0 • Sdoes not modifyI, E I++ I++ S I++ • σ1=σ2
Checking Rewrite Rules • σ1=σ2 I:=0 I:=0 • Relate Executions: • Find synchronization points • Generateinvariants • Check invariants preserved I<E I≥E I<E-1 I≥E-1 A S S B I++ I++ S • Use auto theorem prover • Each invariant must imply successor invariants • Strengthen if inv too weak I++ • σ1=σ2
1. Find Synchronization Points • Traverse in lockstep • Stop at stmt params • Prune infeasible paths I:=0 I:=0 I<E I≥E I<E-1 I≥E-1 S S • From Path: E≤0 • Side Conds: E>0 • Path never executes I++ I++ S I++
2. Generate Invariants • σ1=σ2 I:=0 I:=0 • Invariants: • predicates over σ1,σ2 • Gen initial invariant: • σ1 =σ2 AND • strongest post cond I<E I<E I<E-1 I≥E I<E-1 I≥E-1 I≥E-1 A A S S B B I++ I++ S I++ • σ1=σ2
3. Check Invariants • σ1=σ2 • Each invariant must imply successor invariants • Query Theorem Prover I:=0 I:=0 A I<E I<E I≥E I≥E-1 I<E-1 I≥E-1 S S A A I++ I++ S S S S B B I<E I≥E-1 I++ I++ I++ I++ S B I++ • σ1=σ2
3. Check Invariants ATP Query: • σ1σ2 . • A(σ1,σ2) ∧ • σ1’ = step(σ1, S;I++;I<E)∧ • σ2’ = step(σ2, S;I++;I≥E-1) • B(σ1’,σ2’) • σ1σ2 . σ1 A σ2 • A(σ1,σ2) ∧ S S • σ1’ = step(σ1, S;I++;I<E) ∧ I++ I++ • σ2’ = step(σ2, S;I++;I≥E-1) I<E I≥E-1 • B(σ1’,σ2’) σ1’ B σ2’ ATP
3. Check Invariants ATP Query: • σ1=σ2 ∧ eval(σ1, I < E) • ∧ eval(σ2, I < E-1) • σ1σ2 . • A(σ1,σ2) ∧ • σ1’ = step(σ1, S;I++;I<E)∧ • σ2’ = step(σ2, S;I++;I≥E-1) • B(σ1’,σ2’) σ1 A σ2 S S I++ I++ I<E I≥E-1 • σ1’=σ2’∧ eval(σ1’, I < E) • ∧ eval(σ2’, I ≥ E-1) σ1’ B σ2’ ATP
3. Check Invariants ATP Query: • σ1=σ2 ∧ eval(σ1, I < E) • ∧ eval(σ2, I < E-1) • σ1σ2 . • A(σ1,σ2) ∧ • σ1’ = step(σ1, S;I++;I<E)∧ • σ2’ = step(σ2, S;I++;I≥E-1) • B(σ1’,σ2’) σ1 σ2 A A ∧ B(σ1’,σ2’) S S • σ1’ = step(σ1, S;I++;I<E) I++ I++ • σ2’ = step(σ2, S;I++;I≥E-1) I<E I≥E-1 • σ1’=σ2’∧ eval(σ1’, I < E) • ∧ eval(σ2’, I ≥ E-1) σ1’ σ2’ B ATP • Strengthen A if the theorem prover fails
3. Check Invariants • σ1=σ2 • Each invariant must imply successor invariants • Query Auto Theorem Prover I:=0 I:=0 I<E I≥E I<E-1 I≥E-1 A S S B I++ I++ S I++ • σ1=σ2
Checking Correctness Works well for structure-preserving optimizations Generalization of [ Necula 00 ] Relate Relate OPT OR Permute Permute Generalization of [ Zuck et al. 04] Works well for non structure-preserving optimizations
Permute Module Loop Interchange • for (I in R1){ • for (J in R2){ • S[I, J]; • } • } • for (N in R2){ • for (M in R1){ • S[M, N]; • } • } where:⟨side condition⟩ • Generate correspondence between loop indices • Ask ATP to show that ⟨side condition⟩ implies: • correspondence is one-to-one • For all I, I’ ∊ R1 and J, J’ ∊ R2 • S[I, J] commutes with S[I’, J’]
Contributions 1 Input PProg Parameterized Equivalence Checking Optimization Output PProg 2 3 • Parameterized Equivalence Checking (PEC) • proves opts correct statically and automatically • can reason about many-to-many opts • Expressed and proved a variety of opts correct • which Rhodium could not have proven correct • software pipelining and other complex loop opts
Conclusion Input PProg Parameterized Equivalence Checking Optimization Output PProg • Parameterized Equivalence Checking (PEC) • proves opts correct statically and automatically • can reason about many-to-many opts • Expressed and proved a variety of opts correct • which Rhodium could not have proven correct • software pipelining and other complex loop opts