cmd/compile: preempt repeated checks for the zero constant in prove

Prove requires access to a zero-valued constant in multiple heavily-used
code paths. Currently, prove is checking for the existence of the constant on
every iteration of these paths, and creating it if not found.

This CL preempts all of these checks by finding or creating the zero constant
Value, just once, when the factsTable is initialised on entry to prove(). The
Method used to initialise the zero constant, func.ConstInt64(), finds an
existing constant if present, or creates one in the entry block otherwise.

Fixes #31141

Change-Id: Ic9a2fd9d79b67025e24d4483f6e87cf8213ead24
Reviewed-on: https://go-review.googlesource.com/c/go/+/170118
Reviewed-by: Giovanni Bajo <rasky@develer.com>
Run-TryBot: Giovanni Bajo <rasky@develer.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
zdjones 2019-03-29 19:17:35 +00:00 committed by Giovanni Bajo
parent ee780d4a78
commit 576442b27b

View file

@ -195,6 +195,7 @@ func newFactsTable(f *Func) *factsTable {
ft.stack = make([]fact, 4)
ft.limits = make(map[ID]limit)
ft.limitStack = make([]limitFact, 4)
ft.zero = f.ConstInt64(f.Config.Types.Int64, 0)
return ft
}
@ -571,9 +572,6 @@ func (ft *factsTable) isNonNegative(v *Value) bool {
}
// Check if the signed poset can prove that the value is >= 0
if ft.zero == nil {
ft.zero = v.Block.NewValue0I(v.Block.Pos, OpConst64, v.Block.Func.Config.Types.Int64, 0)
}
return ft.order[0].OrderedOrEqual(ft.zero, v)
}
@ -744,11 +742,6 @@ func prove(f *Func) {
// Find length and capacity ops.
for _, b := range f.Blocks {
for _, v := range b.Values {
// If we found a zero constant, save it (so we don't have
// to build one later).
if ft.zero == nil && v.Op == OpConst64 && v.AuxInt == 0 {
ft.zero = v
}
if v.Uses == 0 {
// We don't care about dead values.
// (There can be some that are CSEd but not removed yet.)
@ -756,27 +749,18 @@ func prove(f *Func) {
}
switch v.Op {
case OpStringLen:
if ft.zero == nil {
ft.zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
}
ft.update(b, v, ft.zero, signed, gt|eq)
case OpSliceLen:
if ft.lens == nil {
ft.lens = map[ID]*Value{}
}
ft.lens[v.Args[0].ID] = v
if ft.zero == nil {
ft.zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
}
ft.update(b, v, ft.zero, signed, gt|eq)
case OpSliceCap:
if ft.caps == nil {
ft.caps = map[ID]*Value{}
}
ft.caps[v.Args[0].ID] = v
if ft.zero == nil {
ft.zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
}
ft.update(b, v, ft.zero, signed, gt|eq)
}
}