mirror of
https://github.com/golang/go
synced 2024-11-26 03:47:57 -07:00
cmd/compile: make DCE remove nodes after terminating if
This change makes compiler frontend dead code elimination of const expr if statements introduced in https://golang.org/cl/38773 treat both if constCondTrue { ...; returnStmt } toBeRemoved... if constCondFalse { ...; } else { returnStmt } toBeRemoved... identically to: if constCondTrue { ...; returnStmt } else { toBeRemoved... } Where "constCondTrue" is a an expression that can be evaluated to "true" during compile time. The additional checks are only triggered for const expr if conditions that evaluate to true. name old time/op new time/op delta Template 431ms ± 2% 429ms ± 1% ~ (p=0.491 n=8+6) Unicode 198ms ± 4% 201ms ± 2% ~ (p=0.234 n=7+6) GoTypes 1.40s ± 1% 1.41s ± 2% ~ (p=0.053 n=7+7) Compiler 6.72s ± 2% 6.81s ± 1% +1.35% (p=0.011 n=7+7) SSA 17.3s ± 1% 17.3s ± 2% ~ (p=0.731 n=6+7) Flate 275ms ± 2% 275ms ± 2% ~ (p=0.902 n=7+7) GoParser 340ms ± 2% 339ms ± 2% ~ (p=0.902 n=7+7) Reflect 910ms ± 2% 905ms ± 1% ~ (p=0.310 n=6+6) Tar 403ms ± 1% 403ms ± 2% ~ (p=0.366 n=7+6) XML 486ms ± 1% 490ms ± 1% ~ (p=0.065 n=6+6) StdCmd 56.2s ± 1% 56.6s ± 2% ~ (p=0.620 n=7+7) name old user-time/op new user-time/op delta Template 559ms ± 8% 557ms ± 7% ~ (p=0.713 n=8+7) Unicode 266ms ±13% 277ms ± 9% ~ (p=0.157 n=8+7) GoTypes 1.83s ± 2% 1.84s ± 1% ~ (p=0.522 n=8+7) Compiler 8.67s ± 4% 8.89s ± 4% ~ (p=0.077 n=7+7) SSA 23.9s ± 1% 24.2s ± 1% +1.31% (p=0.005 n=7+7) Flate 351ms ± 4% 342ms ± 5% ~ (p=0.105 n=7+7) GoParser 437ms ± 2% 423ms ± 5% -3.14% (p=0.016 n=7+7) Reflect 1.16s ± 3% 1.15s ± 2% ~ (p=0.362 n=7+7) Tar 517ms ± 4% 511ms ± 3% ~ (p=0.538 n=7+7) XML 619ms ± 3% 617ms ± 4% ~ (p=0.483 n=7+7) Fixes #23521 Change-Id: I165a7827d869aeb93ce6047d026ff873d039a4f3 Reviewed-on: https://go-review.googlesource.com/91056 Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
19ee2ef950
commit
dcaf3fb134
@ -3926,24 +3926,45 @@ func deadcode(fn *Node) {
|
||||
}
|
||||
|
||||
func deadcodeslice(nn Nodes) {
|
||||
for _, n := range nn.Slice() {
|
||||
for i, n := range nn.Slice() {
|
||||
// Cut is set to true when all nodes after i'th position
|
||||
// should be removed.
|
||||
// In other words, it marks whole slice "tail" as dead.
|
||||
cut := false
|
||||
if n == nil {
|
||||
continue
|
||||
}
|
||||
if n.Op == OIF {
|
||||
n.Left = deadcodeexpr(n.Left)
|
||||
if Isconst(n.Left, CTBOOL) {
|
||||
var body Nodes
|
||||
if n.Left.Bool() {
|
||||
n.Rlist = Nodes{}
|
||||
body = n.Nbody
|
||||
} else {
|
||||
n.Nbody = Nodes{}
|
||||
body = n.Rlist
|
||||
}
|
||||
// If "then" or "else" branch ends with panic or return statement,
|
||||
// it is safe to remove all statements after this node.
|
||||
// isterminating is not used to avoid goto-related complications.
|
||||
if body := body.Slice(); len(body) != 0 {
|
||||
switch body[(len(body) - 1)].Op {
|
||||
case ORETURN, ORETJMP, OPANIC:
|
||||
cut = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deadcodeslice(n.Ninit)
|
||||
deadcodeslice(n.Nbody)
|
||||
deadcodeslice(n.List)
|
||||
deadcodeslice(n.Rlist)
|
||||
if cut {
|
||||
*nn.slice = nn.Slice()[:i+1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
43
test/fixedbugs/issue23521.go
Normal file
43
test/fixedbugs/issue23521.go
Normal file
@ -0,0 +1,43 @@
|
||||
// errorcheck -0 -m
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 23521: improve early DCE for if without explicit else.
|
||||
|
||||
package p
|
||||
|
||||
//go:noinline
|
||||
func nonleaf() {}
|
||||
|
||||
const truth = true
|
||||
|
||||
func f() int { // ERROR "can inline f"
|
||||
if truth {
|
||||
return 0
|
||||
}
|
||||
// If everything below is removed, as it should,
|
||||
// function f should be inlineable.
|
||||
nonleaf()
|
||||
for {
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
|
||||
func g() int { // ERROR "can inline g"
|
||||
return f() // ERROR "inlining call to f"
|
||||
}
|
||||
|
||||
func f2() int { // ERROR "can inline f2"
|
||||
if !truth {
|
||||
nonleaf()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
panic("")
|
||||
}
|
||||
|
||||
func g2() int { // ERROR "can inline g2"
|
||||
return f2() // ERROR "inlining call to f2"
|
||||
}
|
Loading…
Reference in New Issue
Block a user