1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:28:32 -06: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) {
case *Const:
// Dispatch constant conditions statically.
if exact.BoolVal(cond.Value) {
emitJump(fn, t)
} else {
emitJump(fn, f)
}
default:
emitIf(fn, cond, t, f)
}
// A traditional compiler would simplify "if false" (etc) here
// but we do not, for better fidelity to the source code.
//
// The value of a constant condition may be platform-specific,
// and may cause blocks that are reachable in some configuration
// to be hidden from subsequent analyses such as bug-finding tools.
emitIf(fn, b.expr(fn, e), t, f)
}
// 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(),
// e.g. reject Consts with "untyped" types.
//
// Untyped constants are legal as instruction Operands(),
// for example:
// _ = "foo"[0]
// or:
// if wordsize==64 {...}
// All other non-Instruction Values can be found via their
// enclosing Function or Package.
}

View File

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

View File

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

View File

@ -12,6 +12,7 @@ Non-numbered nodes indicate back- or cross-edges to the node whose
4 B
5 call2
6 main$1
main (1)
7 nop
-------- @callgraph callgraph-complete --------
@ -31,5 +32,6 @@ Non-numbered nodes indicate back- or cross-edges to the node whose
7 main.B
8 main.call2
9 main$1
main.main (3)
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)
-------- @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 --------
dynamic function call on nil value