Automatically Proving the Correctness of Compiler Optimizations

42
Automatically Proving the Correctness of Compiler Optimizations Sorin Lerner Todd Millstein Craig Chambers University of Washington

description

Automatically Proving the Correctness of Compiler Optimizations. Sorin Lerner Todd Millstein Craig Chambers University of Washington. Goal: correct compilers. The compiler is usually part of the trusted computing base. “But I use gcc, and it works great!”. gcc-bugs mailing list. - PowerPoint PPT Presentation

Transcript of Automatically Proving the Correctness of Compiler Optimizations

Page 1: Automatically Proving the Correctness of Compiler Optimizations

Automatically Proving the Correctness of Compiler

OptimizationsSorin Lerner Todd Millstein Craig

ChambersUniversity of Washington

Page 2: Automatically Proving the Correctness of Compiler Optimizations

Goal: correct compilers

• The compiler is usually part of the trusted computing base.

• “But I use gcc, and it works great!”

Page 3: Automatically Proving the Correctness of Compiler Optimizations

gcc-bugs mailing list

• c/9525: incorrect code generation on SSE2 intrinsics• target/7336: [ARM] With -Os option, gcc incorrectly computes the

elimination offset• optimization/9325: wrong conversion of constants: (int)(float)(int)

(INT_MAX)• optimization/6537: For -O (but not -O2 or -O0) incorrect assembly is

generated• optimization/6891: G++ generates incorrect code when -Os is used• optimization/8613: [3.2/3.3/3.4 regression] -O2 optimization generates

wrong code • target/9732: PPC32: Wrong code with -O2 –fPIC• c/8224: Incorrect joining of signed and unsigned division • …

Searched for “incorrect” and “wrong” in the gcc-bugs mailing list.Some of the results:

And this is only for February 2003!On a mature compiler!

Page 4: Automatically Proving the Correctness of Compiler Optimizations

compilerSource CompiledProg

run!

inputexp-ectedoutput

Testing

• No correctness guarantees:• neither for the compiled

prog• nor for the compiler

DIFF

• To get benefits, must:• run over many inputs• compile many test cases

output

Page 5: Automatically Proving the Correctness of Compiler Optimizations

Verify each compilation

compilerSource CompiledProg

SemanticDIFF

• Translation validation [Pnueli et al 98, Necula 00]

• Credible compilation[Rinard 99]

• Compiler can still have bugs.

• Compile time increases.• “Semantic Diff” is hard.

Page 6: Automatically Proving the Correctness of Compiler Optimizations

Proving the whole compiler correct

compilerSource CompiledProg

Correctnesschecker

Page 7: Automatically Proving the Correctness of Compiler Optimizations

Proving the whole compiler correct

compiler

Correctnesschecker

Correctness checker

• Option 1: Prove compiler correct by hand.

• Proofs are long…

• And hard.• Compilers are

proven correct as written on paper. What about the implementation?

ProofProofProof«¬

$ \ rt l / .

Link?

Page 8: Automatically Proving the Correctness of Compiler Optimizations

Correctness checker

Our Approach

• Our approach: prove compiler correct automatically.

AutomaticTheoremProver

compiler

Page 9: Automatically Proving the Correctness of Compiler Optimizations

This seems really hard!

AutomaticTheoremProver

Task of provingcompiler correct

Complexity that an automatic theorem prover can handle.

Complexity of proving a compiler correct.

Page 10: Automatically Proving the Correctness of Compiler Optimizations

Making the problem easier

AutomaticTheoremProver

Task of provingcompiler correct

Page 11: Automatically Proving the Correctness of Compiler Optimizations

Making the problem easier

AutomaticTheoremProver

Task of provingoptimizer correct • Only prove optimizer correct.

• Trust front-end and code-generator.

Page 12: Automatically Proving the Correctness of Compiler Optimizations

Making the problem easier

AutomaticTheoremProver

Write optimizations in Cobalt, a domain-specific language.

Task of provingoptimizer correct

Page 13: Automatically Proving the Correctness of Compiler Optimizations

Making the problem easier

AutomaticTheoremProver

Separate correctness from profitability.

Write optimizations in Cobalt, a domain-specific language.

Task of provingoptimizer correct

Page 14: Automatically Proving the Correctness of Compiler Optimizations

Making the problem easier

Write optimizations in Cobalt, a domain-specific language.

Separate correctness from profitability.

Factor out the hard and common parts of the proof, and prove them once by hand.

AutomaticTheoremProver

Task of provingoptimizer correct

Page 15: Automatically Proving the Correctness of Compiler Optimizations

Results• Cobalt language

– realistic C-like IL– implemented const prop and folding, branch

folding, CSE, PRE, DAE, partial DAE, and simple forms of points-to analyses

• Correctness checker for Cobalt opts– using the Simplify theorem prover

• Execution engine for Cobalt opts– in the Whirlwind compiler

Page 16: Automatically Proving the Correctness of Compiler Optimizations

Caveats• May not be able to express your opt Cobalt:

– no interprocedural optimizations for now.– optimizations that build complicated data

structures may be difficult to express.

• A sound Cobalt optimization may be rejected by the correctness checker.

• Trusted computing base (TCB) includes:– front-end and code-generator, execution engine,

correctness checker, proofs done by hand once

Page 17: Automatically Proving the Correctness of Compiler Optimizations

Outline• Overview

• Forward optimizations (see paper for backwards)– Example: constant propagation– Strategy for proving forward optimizations sound

• Profitability heuristics

• Pure analyses

Page 18: Automatically Proving the Correctness of Compiler Optimizations

y := 5

x := yREPLACE

x := 5

statement y := 5

statements thatdon’t define y

statement x := y

Constant Prop (straight-line code)

Page 19: Automatically Proving the Correctness of Compiler Optimizations

Adding arbitrary control flow

y := 5

x := y REPLACE x := 5

statement y := 5

statements thatdon’t define y

statement x := y

y := 5y := 5

is followed by

until

transform statement to x := 5

if

then

Page 20: Automatically Proving the Correctness of Compiler Optimizations

Constant prop in

statement y := 5

statements thatdon’t define y

is followed by

until

if

thentransform statement to x := 5

statement x := y

English

Page 21: Automatically Proving the Correctness of Compiler Optimizations

boolean expressions evaluated at nodes in the CFG

stmt(Y := C)

X := Y

followed by

until

Cobalt versionEnglish version

: mayDef(Y)

statement y := 5

statements thatdon’t define y

is followed by

until

if

thentransform statement to x := 5

statement x := y

Constant prop inCobalt

X := C

Page 22: Automatically Proving the Correctness of Compiler Optimizations

Outline• Overview

• Forward optimizations (see paper for backwards)– Example: constant propagation– Strategy for proving forward optimizations sound

• Profitability heuristics

• Pure analyses

Page 23: Automatically Proving the Correctness of Compiler Optimizations

Proving correctness automatically

y := 5

x := y x := 5

y := 5y := 5

• Witnessing region• Invariant: y == 5

Page 24: Automatically Proving the Correctness of Compiler Optimizations

Constant prop revisited

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

Ask a theorem prover to show:1. A statement satisfying stmt(Y :=

C) establishes Y == C2. A statement satisfying :mayDef(Y)

maintains Y == C3. The statements X := Y and X := C

have the same semantics in a program state satisfying Y == C

X := C

Page 25: Automatically Proving the Correctness of Compiler Optimizations

Generalize to any forward optimization

Ask a theorem prover to show:1. A statement satisfying 1

establishes P2. A statement satisfying 2

maintains P3. The statements s and s’

have the same semantics in a program state satisfying P

We showed by hand once that these conditions imply correctness.

1

2

s

followed by

until

with witnessP

s’

Page 26: Automatically Proving the Correctness of Compiler Optimizations

Outline• Overview

• Forward optimizations (see paper for backwards)

• Profitability heuristics

• Pure analyses

Page 27: Automatically Proving the Correctness of Compiler Optimizations

Profitability heuristics

• Optimization correct ) safe to perform any subset of the matching transformations.

• So far, all transformations were also profitable.

• In some cases, many transformations are legal, but only a few are profitable.

Page 28: Automatically Proving the Correctness of Compiler Optimizations

The two pieces of an optimization

1

followed by 2

until s

s’with witness Pfiltered through choose

• Transformation pattern:– defines which

transformations are legal.

• Profitability heuristic:– describes which of the legal

transformations to actually perform.

– does not affect soundness.– can be written in a language

of the user’s choice.

• This way of factoring an optimization is crucial to our ability to prove optimizations sound automatically.

Page 29: Automatically Proving the Correctness of Compiler Optimizations

Profitability heuristic example: PRE

• PRE as code duplication followed by CSE

Page 30: Automatically Proving the Correctness of Compiler Optimizations

Profitability heuristic example: PRE

a := ...;

b := ...;

if (...) {

a := ...;

x := a + b;

} else {

...

}

x := a + b;x := a + b;

• Code duplication

• PRE as code duplication followed by CSE

Page 31: Automatically Proving the Correctness of Compiler Optimizations

Profitability heuristic example: PRE

• PRE as code duplication followed by CSE

a := ...;

b := ...;

if (...) {

a := ...;

x := a + b;

} else {

}

x :=

x := a + b;

• Code duplication

• CSE• self-assignment

removal

a + b; x;

Page 32: Automatically Proving the Correctness of Compiler Optimizations

Profitability heuristic example: PRE

a := ...;

b := ...;

if (...) {

a := ...;

x := a + b;

} else {

...

}

x := a + b;

Legal placements of x := a + bProfitable placement

Page 33: Automatically Proving the Correctness of Compiler Optimizations

Outline• Overview

• Forward optimizations (see paper for backwards)

• Profitability heuristics

• Pure analyses

Page 34: Automatically Proving the Correctness of Compiler Optimizations

Constant prop revisited (again)

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 35: Automatically Proving the Correctness of Compiler Optimizations

mayDef in Cobalt

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 36: Automatically Proving the Correctness of Compiler Optimizations

mayDef in Cobalt

• Very conservative!• Can we do better?

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 37: Automatically Proving the Correctness of Compiler Optimizations

mayDef in Cobalt

• Very conservative!• Can we do better?

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 38: Automatically Proving the Correctness of Compiler Optimizations

mayDef in Cobalt

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 39: Automatically Proving the Correctness of Compiler Optimizations

mayDef in Cobalt

• mayPntTo is a pure analysis.• It computes dataflow info,

but performs no transformations.

stmt(Y := C)

: mayDef(Y)

X := Y

followed by

until

with witnessY == C

X := C

Page 40: Automatically Proving the Correctness of Compiler Optimizations

mayPntTo in Cobalt

addrNotTaken(X)

“no location in the store points to X”

decl X

s

mayPntTo(X,Y) , : addrNotTaken(Y)

stmt(decl X)

followed by: stmt(... := &X)

defines

with witness

Page 41: Automatically Proving the Correctness of Compiler Optimizations

Future work

• Improving expressiveness– interprocedural optimizations– one-to-many and many-to-many

transformations

• Inferring the witness

• Generate specialized compiler binary from the Cobalt sources.

Page 42: Automatically Proving the Correctness of Compiler Optimizations

Summary and Conclusion

• Optimizations written in a domain-specific language can be proven correct automatically.

• Our correctness checker found several subtle bugs in Cobalt optimizations.

• A good step towards proving compilers correct automatically.