Skip to content

Commit d0a64f7

Browse files
randall77gopherbot
authored andcommitted
Revert "cmd/compile/internal/ssa: Use transitive properties for len/cap"
This reverts commit a3295df (CL 679155) Reason for revert: leads to a very expensive prove pass, see golang#74974 (Maybe not this CL's fault, just tickling some superlinear behavior.) Change-Id: I75302c04cfc5e1e075aeb80edb73080bfb1efcac Reviewed-on: https://go-review.googlesource.com/c/go/+/695175 Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Daniel Morsing <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Auto-Submit: Keith Randall <[email protected]>
1 parent 00a7bdc commit d0a64f7

File tree

1 file changed

+41
-32
lines changed

1 file changed

+41
-32
lines changed

src/cmd/compile/internal/ssa/prove.go

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,12 @@ type factsTable struct {
406406
limits []limit // indexed by value ID
407407
limitStack []limitFact // previous entries
408408
recurseCheck []bool // recursion detector for limit propagation
409+
410+
// For each slice s, a map from s to a len(s)/cap(s) value (if any)
411+
// TODO: check if there are cases that matter where we have
412+
// more than one len(s) for a slice. We could keep a list if necessary.
413+
lens map[ID]*Value
414+
caps map[ID]*Value
409415
}
410416

411417
// checkpointBound is an invalid value used for checkpointing
@@ -657,11 +663,6 @@ func (ft *factsTable) newLimit(v *Value, newLim limit) bool {
657663
}
658664
if !isTrue {
659665
r ^= lt | gt | eq
660-
} else if d == unsigned && (r == lt || r == lt|eq) && ft.isNonNegative(v.Args[1]) {
661-
// Since every representation of a non-negative signed number is the same
662-
// as in the unsigned domain, we can transfer x <= y to the signed domain,
663-
// but only for the true branch.
664-
d |= signed
665666
}
666667
// TODO: v.Block is wrong?
667668
addRestrictions(v.Block, ft, d, v.Args[0], v.Args[1], r)
@@ -726,7 +727,7 @@ func (ft *factsTable) addOrdering(v, w *Value, d domain, r relation) {
726727
// restricting it to r.
727728
func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
728729
if parent.Func.pass.debug > 2 {
729-
parent.Func.Warnl(parent.Pos, "parent=%s, update %s %s %s %s", parent, d, v, w, r)
730+
parent.Func.Warnl(parent.Pos, "parent=%s, update %s %s %s", parent, v, w, r)
730731
}
731732
// No need to do anything else if we already found unsat.
732733
if ft.unsat {
@@ -938,6 +939,32 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
938939
return
939940
}
940941

942+
// Additional facts we know given the relationship between len and cap.
943+
//
944+
// TODO: Since prove now derives transitive relations, it
945+
// should be sufficient to learn that len(w) <= cap(w) at the
946+
// beginning of prove where we look for all len/cap ops.
947+
if v.Op == OpSliceLen && r&lt == 0 && ft.caps[v.Args[0].ID] != nil {
948+
// len(s) > w implies cap(s) > w
949+
// len(s) >= w implies cap(s) >= w
950+
// len(s) == w implies cap(s) >= w
951+
ft.update(parent, ft.caps[v.Args[0].ID], w, d, r|gt)
952+
}
953+
if w.Op == OpSliceLen && r&gt == 0 && ft.caps[w.Args[0].ID] != nil {
954+
// same, length on the RHS.
955+
ft.update(parent, v, ft.caps[w.Args[0].ID], d, r|lt)
956+
}
957+
if v.Op == OpSliceCap && r&gt == 0 && ft.lens[v.Args[0].ID] != nil {
958+
// cap(s) < w implies len(s) < w
959+
// cap(s) <= w implies len(s) <= w
960+
// cap(s) == w implies len(s) <= w
961+
ft.update(parent, ft.lens[v.Args[0].ID], w, d, r|lt)
962+
}
963+
if w.Op == OpSliceCap && r&lt == 0 && ft.lens[w.Args[0].ID] != nil {
964+
// same, capacity on the RHS.
965+
ft.update(parent, v, ft.lens[w.Args[0].ID], d, r|gt)
966+
}
967+
941968
// Process fence-post implications.
942969
//
943970
// First, make the condition > or >=.
@@ -1391,8 +1418,6 @@ func prove(f *Func) {
13911418
ft := newFactsTable(f)
13921419
ft.checkpoint()
13931420

1394-
var lens map[ID]*Value
1395-
var caps map[ID]*Value
13961421
// Find length and capacity ops.
13971422
for _, b := range f.Blocks {
13981423
for _, v := range b.Values {
@@ -1403,39 +1428,26 @@ func prove(f *Func) {
14031428
}
14041429
switch v.Op {
14051430
case OpSliceLen:
1406-
if lens == nil {
1407-
lens = map[ID]*Value{}
1431+
if ft.lens == nil {
1432+
ft.lens = map[ID]*Value{}
14081433
}
14091434
// Set all len Values for the same slice as equal in the poset.
14101435
// The poset handles transitive relations, so Values related to
14111436
// any OpSliceLen for this slice will be correctly related to others.
1412-
//
1413-
// Since we know that lens/caps are non-negative, their relation
1414-
// can be added in both the signed and unsigned domain.
1415-
if l, ok := lens[v.Args[0].ID]; ok {
1437+
if l, ok := ft.lens[v.Args[0].ID]; ok {
14161438
ft.update(b, v, l, signed, eq)
1417-
ft.update(b, v, l, unsigned, eq)
14181439
} else {
1419-
lens[v.Args[0].ID] = v
1420-
}
1421-
if c, ok := caps[v.Args[0].ID]; ok {
1422-
ft.update(b, v, c, signed, lt|eq)
1423-
ft.update(b, v, c, unsigned, lt|eq)
1440+
ft.lens[v.Args[0].ID] = v
14241441
}
14251442
case OpSliceCap:
1426-
if caps == nil {
1427-
caps = map[ID]*Value{}
1443+
if ft.caps == nil {
1444+
ft.caps = map[ID]*Value{}
14281445
}
14291446
// Same as case OpSliceLen above, but for slice cap.
1430-
if c, ok := caps[v.Args[0].ID]; ok {
1447+
if c, ok := ft.caps[v.Args[0].ID]; ok {
14311448
ft.update(b, v, c, signed, eq)
1432-
ft.update(b, v, c, unsigned, eq)
14331449
} else {
1434-
caps[v.Args[0].ID] = v
1435-
}
1436-
if l, ok := lens[v.Args[0].ID]; ok {
1437-
ft.update(b, v, l, signed, gt|eq)
1438-
ft.update(b, v, l, unsigned, gt|eq)
1450+
ft.caps[v.Args[0].ID] = v
14391451
}
14401452
}
14411453
}
@@ -2245,9 +2257,6 @@ func addLocalFacts(ft *factsTable, b *Block) {
22452257
OpRsh32Ux64, OpRsh32Ux32, OpRsh32Ux16, OpRsh32Ux8,
22462258
OpRsh64Ux64, OpRsh64Ux32, OpRsh64Ux16, OpRsh64Ux8:
22472259
ft.update(b, v, v.Args[0], unsigned, lt|eq)
2248-
if ft.isNonNegative(v.Args[0]) {
2249-
ft.update(b, v, v.Args[0], signed, lt|eq)
2250-
}
22512260
case OpMod64u, OpMod32u, OpMod16u, OpMod8u:
22522261
ft.update(b, v, v.Args[0], unsigned, lt|eq)
22532262
// Note: we have to be careful that this doesn't imply

0 commit comments

Comments
 (0)