1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:04:45 -07:00

go/ssa: avoid "premature optimization" of dead branch removal.

Blocks dominated by "if false" should be retained in the
initial SSA form so they remain visible to subsequent source
code analysis tools.

In any case, true compilers already need a stronger version of
this optimization so they can simplify CFGs such as this:
	const x, y = ...
        switch x {case y:...}
where a branch is constant but the comparison of constants
does not occur within an expression.

LGTM=gri
R=gri
CC=golang-codereviews, pcc
https://golang.org/cl/101250043
This commit is contained in:
Alan Donovan 2014-06-12 11:31:41 -04:00
parent 0fa48054ca
commit 142566e529
6 changed files with 21 additions and 18 deletions

View File

@ -106,17 +106,13 @@ func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
} }
} }
switch cond := b.expr(fn, e).(type) { // A traditional compiler would simplify "if false" (etc) here
case *Const: // but we do not, for better fidelity to the source code.
// Dispatch constant conditions statically. //
if exact.BoolVal(cond.Value) { // The value of a constant condition may be platform-specific,
emitJump(fn, t) // and may cause blocks that are reachable in some configuration
} else { // to be hidden from subsequent analyses such as bug-finding tools.
emitJump(fn, f) emitIf(fn, b.expr(fn, e), t, f)
}
default:
emitIf(fn, cond, t, f)
}
} }
// logicalBinop emits code to fn to evaluate e, a &&- or // logicalBinop emits code to fn to evaluate e, a &&- or

View File

@ -197,9 +197,12 @@ func (s *sanity) checkInstr(idx int, instr Instruction) {
} }
} }
// TODO(adonovan): sanity-check Consts used as instruction Operands(), // Untyped constants are legal as instruction Operands(),
// e.g. reject Consts with "untyped" types. // for example:
// // _ = "foo"[0]
// or:
// if wordsize==64 {...}
// All other non-Instruction Values can be found via their // All other non-Instruction Values can be found via their
// enclosing Function or Package. // enclosing Function or Package.
} }

View File

@ -112,10 +112,10 @@ func main() {
_ = v11.method // v11::Const _ = v11.method // v11::Const
_ = (*struct{ J }).method // J::nil _ = (*struct{ J }).method // J::nil
// These vars are optimised away. // These vars are not optimised away.
if false { if false {
v13 := 0 // v13::nil v13 := 0 // v13::Const
println(v13) // v13::nil println(v13) // v13::Const
} }
switch x := 1; x { // x::Const switch x := 1; x { // x::Const

View File

@ -6,6 +6,7 @@
"name": "main.main", "name": "main.main",
"pos": "testdata/src/main/callgraph-json.go:24:6", "pos": "testdata/src/main/callgraph-json.go:24:6",
"children": [ "children": [
0,
1, 1,
2, 2,
3 3

View File

@ -12,6 +12,7 @@ Non-numbered nodes indicate back- or cross-edges to the node whose
4 B 4 B
5 call2 5 call2
6 main$1 6 main$1
main (1)
7 nop 7 nop
-------- @callgraph callgraph-complete -------- -------- @callgraph callgraph-complete --------
@ -31,5 +32,6 @@ Non-numbered nodes indicate back- or cross-edges to the node whose
7 main.B 7 main.B
8 main.call2 8 main.call2
9 main$1 9 main$1
main.main (3)
10 main.nop 10 main.nop

View File

@ -71,8 +71,9 @@ Error: this is a type conversion, not a function call
Error: ambiguous selection within function call (or conversion) Error: ambiguous selection within function call (or conversion)
-------- @callees callees-err-deadcode1 -------- -------- @callees callees-err-deadcode1 --------
this static function call dispatches to:
main.main
Error: this call site is unreachable in this analysis
-------- @callees callees-err-nil-func -------- -------- @callees callees-err-nil-func --------
dynamic function call on nil value dynamic function call on nil value