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:
parent
0fa48054ca
commit
142566e529
@ -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
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
|
6
go/ssa/testdata/objlookup.go
vendored
6
go/ssa/testdata/objlookup.go
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
2
oracle/testdata/src/main/callgraph.golden
vendored
2
oracle/testdata/src/main/callgraph.golden
vendored
@ -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
|
||||||
|
|
||||||
|
3
oracle/testdata/src/main/calls.golden
vendored
3
oracle/testdata/src/main/calls.golden
vendored
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user