mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: fold constants found by prove
It is hit ~70k times building go.
This make the go binary, 0.04% smaller.
I didn't included benchmarks because this is just constant foldings
and is hard to mesure objectively.
For example, this enable rewriting things like:
if x == 20 {
return x + 30 + z
}
Into:
if x == 20 {
return 50 + z
}
It's not just fixing programer's code,
the ssa generator generate code like this sometimes.
Change-Id: I0861f342b27f7227b5f1c34d8267fa0057b1bbbc
GitHub-Last-Rev: 4c2f9b5216
GitHub-Pull-Request: golang/go#52669
Reviewed-on: https://go-review.googlesource.com/c/go/+/403735
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
fbb47e81c1
commit
e1e056fa6a
3 changed files with 100 additions and 10 deletions
|
|
@ -1222,13 +1222,13 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
|
|||
// Replace OpSlicemask operations in b with constants where possible.
|
||||
x, delta := isConstDelta(v.Args[0])
|
||||
if x == nil {
|
||||
continue
|
||||
break
|
||||
}
|
||||
// slicemask(x + y)
|
||||
// if x is larger than -y (y is negative), then slicemask is -1.
|
||||
lim, ok := ft.limits[x.ID]
|
||||
if !ok {
|
||||
continue
|
||||
break
|
||||
}
|
||||
if lim.umin > uint64(-delta) {
|
||||
if v.Args[0].Op == OpAdd64 {
|
||||
|
|
@ -1248,7 +1248,7 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
|
|||
x := v.Args[0]
|
||||
lim, ok := ft.limits[x.ID]
|
||||
if !ok {
|
||||
continue
|
||||
break
|
||||
}
|
||||
if lim.umin > 0 || lim.min > 0 || lim.max < 0 {
|
||||
if b.Func.pass.debug > 0 {
|
||||
|
|
@ -1280,7 +1280,7 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
|
|||
panic("unexpected integer size")
|
||||
}
|
||||
v.AuxInt = 0
|
||||
continue // Be sure not to fallthrough - this is no longer OpRsh.
|
||||
break // Be sure not to fallthrough - this is no longer OpRsh.
|
||||
}
|
||||
// If the Rsh hasn't been replaced with 0, still check if it is bounded.
|
||||
fallthrough
|
||||
|
|
@ -1297,7 +1297,7 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
|
|||
by := v.Args[1]
|
||||
lim, ok := ft.limits[by.ID]
|
||||
if !ok {
|
||||
continue
|
||||
break
|
||||
}
|
||||
bits := 8 * v.Args[0].Type.Size()
|
||||
if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) {
|
||||
|
|
@ -1331,6 +1331,60 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Fold provable constant results.
|
||||
// Helps in cases where we reuse a value after branching on its equality.
|
||||
for i, arg := range v.Args {
|
||||
switch arg.Op {
|
||||
case OpConst64, OpConst32, OpConst16, OpConst8:
|
||||
continue
|
||||
}
|
||||
lim, ok := ft.limits[arg.ID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var constValue int64
|
||||
typ := arg.Type
|
||||
bits := 8 * typ.Size()
|
||||
switch {
|
||||
case lim.min == lim.max:
|
||||
constValue = lim.min
|
||||
case lim.umin == lim.umax:
|
||||
// truncate then sign extand
|
||||
switch bits {
|
||||
case 64:
|
||||
constValue = int64(lim.umin)
|
||||
case 32:
|
||||
constValue = int64(int32(lim.umin))
|
||||
case 16:
|
||||
constValue = int64(int16(lim.umin))
|
||||
case 8:
|
||||
constValue = int64(int8(lim.umin))
|
||||
default:
|
||||
panic("unexpected integer size")
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
var c *Value
|
||||
f := b.Func
|
||||
switch bits {
|
||||
case 64:
|
||||
c = f.ConstInt64(typ, constValue)
|
||||
case 32:
|
||||
c = f.ConstInt32(typ, int32(constValue))
|
||||
case 16:
|
||||
c = f.ConstInt16(typ, int16(constValue))
|
||||
case 8:
|
||||
c = f.ConstInt8(typ, int8(constValue))
|
||||
default:
|
||||
panic("unexpected integer size")
|
||||
}
|
||||
v.SetArg(i, c)
|
||||
if b.Func.pass.debug > 1 {
|
||||
b.Func.Warnl(v.Pos, "Proved %v's arg %d (%v) is constant %d", v, i, arg, constValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if b.Kind != BlockIf {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue