mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: get more bounds info from logic operators in prove pass
Currently, the prove pass can get knowledge from some specific logic operators only before the CFG is explored, which means that the bounds information of the branch will be ignored. This CL updates the facts table by the logic operators in every branch. Combined with the branch information, this will be helpful for BCE in some circumstances. Fixes #57243 Change-Id: I0bd164f1b47804ccfc37879abe9788740b016fd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/419555 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Eric Fang <eric.fang@arm.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
4f4a9c7fff
commit
9be533a8ee
3 changed files with 46 additions and 1 deletions
|
|
@ -802,6 +802,7 @@ func prove(f *Func) {
|
|||
ft.checkpoint()
|
||||
|
||||
var lensVars map[*Block][]*Value
|
||||
var logicVars map[*Block][]*Value
|
||||
|
||||
// Find length and capacity ops.
|
||||
for _, b := range f.Blocks {
|
||||
|
|
@ -856,6 +857,16 @@ func prove(f *Func) {
|
|||
case OpAnd64, OpAnd32, OpAnd16, OpAnd8:
|
||||
ft.update(b, v, v.Args[1], unsigned, lt|eq)
|
||||
ft.update(b, v, v.Args[0], unsigned, lt|eq)
|
||||
for i := 0; i < 2; i++ {
|
||||
if isNonNegative(v.Args[i]) {
|
||||
ft.update(b, v, v.Args[i], signed, lt|eq)
|
||||
ft.update(b, v, ft.zero, signed, gt|eq)
|
||||
}
|
||||
}
|
||||
if logicVars == nil {
|
||||
logicVars = make(map[*Block][]*Value)
|
||||
}
|
||||
logicVars[b] = append(logicVars[b], v)
|
||||
case OpDiv64u, OpDiv32u, OpDiv16u, OpDiv8u,
|
||||
OpRsh8Ux64, OpRsh8Ux32, OpRsh8Ux16, OpRsh8Ux8,
|
||||
OpRsh16Ux64, OpRsh16Ux32, OpRsh16Ux16, OpRsh16Ux8,
|
||||
|
|
@ -982,6 +993,21 @@ func prove(f *Func) {
|
|||
|
||||
if branch != unknown {
|
||||
addBranchRestrictions(ft, parent, branch)
|
||||
// After we add the branch restriction, re-check the logic operations in the parent block,
|
||||
// it may give us more info to omit some branches
|
||||
if logic, ok := logicVars[parent]; ok {
|
||||
for _, v := range logic {
|
||||
// we only have OpAnd for now
|
||||
ft.update(parent, v, v.Args[1], unsigned, lt|eq)
|
||||
ft.update(parent, v, v.Args[0], unsigned, lt|eq)
|
||||
for i := 0; i < 2; i++ {
|
||||
if isNonNegative(v.Args[i]) {
|
||||
ft.update(parent, v, v.Args[i], signed, lt|eq)
|
||||
ft.update(parent, v, ft.zero, signed, gt|eq)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ft.unsat {
|
||||
// node.block is unreachable.
|
||||
// Remove it and don't visit
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue