mirror of
https://github.com/golang/go
synced 2024-11-26 01:07:57 -07:00
cmd/compile: fix wrong optimization for eliding Not in Phi
The previous rule may move the phi value into a wrong block. This CL make it only rewrite the phi value not the If block, so that the phi value will stay in old block. Fixes #56777 Change-Id: I9479a5c7f28529786968413d35b82a16181bb1f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/451496 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
205f636e0a
commit
8893da7c72
@ -961,10 +961,11 @@
|
||||
(NilCheck (GetG mem) mem) => mem
|
||||
|
||||
(If (Not cond) yes no) => (If cond no yes)
|
||||
(If (Phi <t> nx:(Not x) ny:(Not y)) yes no) && nx.Uses == 1 && ny.Uses == 1 => (If (Phi <t> x y) no yes)
|
||||
(If (ConstBool [c]) yes no) && c => (First yes no)
|
||||
(If (ConstBool [c]) yes no) && !c => (First no yes)
|
||||
|
||||
(Phi <t> nx:(Not x) ny:(Not y)) && nx.Uses == 1 && ny.Uses == 1 => (Not (Phi <t> x y))
|
||||
|
||||
// Get rid of Convert ops for pointer arithmetic on unsafe.Pointer.
|
||||
(Convert (Add(64|32) (Convert ptr mem) off) mem) => (AddPtr ptr off)
|
||||
(Convert (Convert ptr mem) mem) => ptr
|
||||
|
@ -21903,6 +21903,7 @@ func rewriteValuegeneric_OpOrB(v *Value) bool {
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpPhi(v *Value) bool {
|
||||
b := v.Block
|
||||
// match: (Phi (Const8 [c]) (Const8 [c]))
|
||||
// result: (Const8 [c])
|
||||
for {
|
||||
@ -21983,6 +21984,34 @@ func rewriteValuegeneric_OpPhi(v *Value) bool {
|
||||
v.AuxInt = int64ToAuxInt(c)
|
||||
return true
|
||||
}
|
||||
// match: (Phi <t> nx:(Not x) ny:(Not y))
|
||||
// cond: nx.Uses == 1 && ny.Uses == 1
|
||||
// result: (Not (Phi <t> x y))
|
||||
for {
|
||||
if len(v.Args) != 2 {
|
||||
break
|
||||
}
|
||||
t := v.Type
|
||||
_ = v.Args[1]
|
||||
nx := v.Args[0]
|
||||
if nx.Op != OpNot {
|
||||
break
|
||||
}
|
||||
x := nx.Args[0]
|
||||
ny := v.Args[1]
|
||||
if ny.Op != OpNot {
|
||||
break
|
||||
}
|
||||
y := ny.Args[0]
|
||||
if !(nx.Uses == 1 && ny.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpPhi, t)
|
||||
v0.AddArg2(x, y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpPtrIndex(v *Value) bool {
|
||||
@ -32462,35 +32491,6 @@ func rewriteBlockgeneric(b *Block) bool {
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (If (Phi <t> nx:(Not x) ny:(Not y)) yes no)
|
||||
// cond: nx.Uses == 1 && ny.Uses == 1
|
||||
// result: (If (Phi <t> x y) no yes)
|
||||
for b.Controls[0].Op == OpPhi {
|
||||
v_0 := b.Controls[0]
|
||||
if len(v_0.Args) != 2 {
|
||||
break
|
||||
}
|
||||
t := v_0.Type
|
||||
_ = v_0.Args[1]
|
||||
nx := v_0.Args[0]
|
||||
if nx.Op != OpNot {
|
||||
break
|
||||
}
|
||||
x := nx.Args[0]
|
||||
ny := v_0.Args[1]
|
||||
if ny.Op != OpNot {
|
||||
break
|
||||
}
|
||||
y := ny.Args[0]
|
||||
if !(nx.Uses == 1 && ny.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v0 := b.NewValue0(v_0.Pos, OpPhi, t)
|
||||
v0.AddArg2(x, y)
|
||||
b.resetWithControl(BlockIf, v0)
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (If (ConstBool [c]) yes no)
|
||||
// cond: c
|
||||
// result: (First yes no)
|
||||
|
56
test/fixedbugs/issue56777.go
Normal file
56
test/fixedbugs/issue56777.go
Normal file
@ -0,0 +1,56 @@
|
||||
// compile
|
||||
|
||||
// Copyright 2022 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.
|
||||
|
||||
package p
|
||||
|
||||
func fn(setText []rune, negate bool) int {
|
||||
ranges := []singleRange{}
|
||||
|
||||
if len(setText) > 0 {
|
||||
fillFirst := false
|
||||
l := len(setText)
|
||||
if negate {
|
||||
if setText[0] == 0 {
|
||||
setText = setText[1:]
|
||||
} else {
|
||||
l++
|
||||
fillFirst = true
|
||||
}
|
||||
}
|
||||
|
||||
if l%2 == 0 {
|
||||
ranges = make([]singleRange, l/2)
|
||||
} else {
|
||||
ranges = make([]singleRange, l/2+1)
|
||||
}
|
||||
|
||||
first := true
|
||||
if fillFirst {
|
||||
ranges[0] = singleRange{first: 0}
|
||||
first = false
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, r := range setText {
|
||||
if first {
|
||||
// lower bound in a new range
|
||||
ranges[i] = singleRange{first: r}
|
||||
first = false
|
||||
} else {
|
||||
ranges[i].last = r - 1
|
||||
i++
|
||||
first = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len(ranges)
|
||||
}
|
||||
|
||||
type singleRange struct {
|
||||
first rune
|
||||
last rune
|
||||
}
|
Loading…
Reference in New Issue
Block a user