mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: generate constants for NeqPtr, EqPtr and IsNonNil ops
If both inputs are constant offsets from the same pointer then we can evaluate NeqPtr and EqPtr at compile time. Triggers a few times during all.bash. Removes a conditional branch in the following code: copy(x[1:], x[:]) This branch was recently added as an optimization in CL 94596. We now skip the memmove if the pointers are equal. However, in the above code we know at compile time that they are never equal. Also, when the offset is variable, check if the offset is zero rather than if the pointers are equal. For example: copy(x[a:], x[:]) This would now skip the copy if a == 0, rather than if x + a == x. Finally I've also added a rule to make IsNonNil true for pointers to values on the stack. The nil check elimination pass will catch these anyway, but eliminating them here might eliminate branches earlier. Change-Id: If72f436fef0a96ad0f4e296d3a1f8b6c3e712085 Reviewed-on: https://go-review.googlesource.com/106635 Run-TryBot: Michael Munday <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
89d576c933
commit
58cdecb9c8
3 changed files with 737 additions and 119 deletions
|
|
@ -528,11 +528,6 @@
|
|||
(Phi (Const32 [c]) (Const32 [c])) -> (Const32 [c])
|
||||
(Phi (Const64 [c]) (Const64 [c])) -> (Const64 [c])
|
||||
|
||||
// user nil checks
|
||||
(NeqPtr p (ConstNil)) -> (IsNonNil p)
|
||||
(EqPtr p (ConstNil)) -> (Not (IsNonNil p))
|
||||
(IsNonNil (ConstNil)) -> (ConstBool [0])
|
||||
|
||||
// slice and interface comparisons
|
||||
// The frontend ensures that we can only compare against nil,
|
||||
// so we need only compare the first word (interface type or slice ptr).
|
||||
|
|
@ -1241,11 +1236,30 @@
|
|||
&& warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
|
||||
-> (Invalid)
|
||||
|
||||
// Address comparison shows up in type assertions.
|
||||
(EqPtr x x) -> (ConstBool [1])
|
||||
(EqPtr (Addr {a} x) (Addr {b} x)) -> (ConstBool [b2i(a == b)])
|
||||
// Evaluate constant address comparisons.
|
||||
(EqPtr x x) -> (ConstBool [1])
|
||||
(NeqPtr x x) -> (ConstBool [0])
|
||||
(NeqPtr (Addr {a} x) (Addr {b} x)) -> (ConstBool [b2i(a != b)])
|
||||
(EqPtr (Addr {a} _) (Addr {b} _)) -> (ConstBool [b2i(a == b)])
|
||||
(NeqPtr (Addr {a} _) (Addr {b} _)) -> (ConstBool [b2i(a != b)])
|
||||
(EqPtr (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 == 0)])
|
||||
(NeqPtr (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 != 0)])
|
||||
(EqPtr (OffPtr [o1] p1) (OffPtr [o2] p2)) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 == o2)])
|
||||
(NeqPtr (OffPtr [o1] p1) (OffPtr [o2] p2)) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 != o2)])
|
||||
(EqPtr (Const(32|64) [c]) (Const(32|64) [d])) -> (ConstBool [b2i(c == d)])
|
||||
(NeqPtr (Const(32|64) [c]) (Const(32|64) [d])) -> (ConstBool [b2i(c != d)])
|
||||
|
||||
// Simplify address comparisons.
|
||||
(EqPtr (AddPtr p1 o1) p2) && isSamePtr(p1, p2) -> (Not (IsNonNil o1))
|
||||
(NeqPtr (AddPtr p1 o1) p2) && isSamePtr(p1, p2) -> (IsNonNil o1)
|
||||
(EqPtr (Const(32|64) [0]) p) -> (Not (IsNonNil p))
|
||||
(NeqPtr (Const(32|64) [0]) p) -> (IsNonNil p)
|
||||
(EqPtr (ConstNil) p) -> (Not (IsNonNil p))
|
||||
(NeqPtr (ConstNil) p) -> (IsNonNil p)
|
||||
|
||||
// Evaluate constant user nil checks.
|
||||
(IsNonNil (ConstNil)) -> (ConstBool [0])
|
||||
(IsNonNil (Const(32|64) [c])) -> (ConstBool [b2i(c != 0)])
|
||||
(IsNonNil (Addr _)) -> (ConstBool [1])
|
||||
|
||||
// Inline small runtime.memmove calls with constant length.
|
||||
(StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func rewriteValuegeneric(v *Value) bool {
|
|||
case OpEqInter:
|
||||
return rewriteValuegeneric_OpEqInter_0(v)
|
||||
case OpEqPtr:
|
||||
return rewriteValuegeneric_OpEqPtr_0(v)
|
||||
return rewriteValuegeneric_OpEqPtr_0(v) || rewriteValuegeneric_OpEqPtr_10(v)
|
||||
case OpEqSlice:
|
||||
return rewriteValuegeneric_OpEqSlice_0(v)
|
||||
case OpGeq16:
|
||||
|
|
@ -298,7 +298,7 @@ func rewriteValuegeneric(v *Value) bool {
|
|||
case OpNeqInter:
|
||||
return rewriteValuegeneric_OpNeqInter_0(v)
|
||||
case OpNeqPtr:
|
||||
return rewriteValuegeneric_OpNeqPtr_0(v)
|
||||
return rewriteValuegeneric_OpNeqPtr_0(v) || rewriteValuegeneric_OpNeqPtr_10(v)
|
||||
case OpNeqSlice:
|
||||
return rewriteValuegeneric_OpNeqSlice_0(v)
|
||||
case OpNilCheck:
|
||||
|
|
@ -10221,18 +10221,338 @@ func rewriteValuegeneric_OpEqInter_0(v *Value) bool {
|
|||
}
|
||||
}
|
||||
func rewriteValuegeneric_OpEqPtr_0(v *Value) bool {
|
||||
// match: (EqPtr x x)
|
||||
// cond:
|
||||
// result: (ConstBool [1])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
if x != v.Args[1] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 1
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Addr {a} _) (Addr {b} _))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a == b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_0.Aux
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_1.Aux
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a == b)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Addr {b} _) (Addr {a} _))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a == b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_0.Aux
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_1.Aux
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a == b)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (OffPtr [o1] p1) p2)
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 == 0)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_0.AuxInt
|
||||
p1 := v_0.Args[0]
|
||||
p2 := v.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 == 0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr p2 (OffPtr [o1] p1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 == 0)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p2 := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_1.AuxInt
|
||||
p1 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 == 0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (OffPtr [o1] p1) (OffPtr [o2] p2))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 == o2)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_0.AuxInt
|
||||
p1 := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o2 := v_1.AuxInt
|
||||
p2 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 == o2)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (OffPtr [o2] p2) (OffPtr [o1] p1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 == o2)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o2 := v_0.AuxInt
|
||||
p2 := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_1.AuxInt
|
||||
p1 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 == o2)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Const32 [c]) (Const32 [d]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c == d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
d := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c == d)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Const32 [d]) (Const32 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c == d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c == d)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Const64 [c]) (Const64 [d]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c == d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
d := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c == d)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
typ := &b.Func.Config.Types
|
||||
_ = typ
|
||||
// match: (EqPtr p (ConstNil))
|
||||
// match: (EqPtr (Const64 [d]) (Const64 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c == d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c == d)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (AddPtr p1 o1) p2)
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (Not (IsNonNil o1))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddPtr {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
p1 := v_0.Args[0]
|
||||
o1 := v_0.Args[1]
|
||||
p2 := v.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(o1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr p2 (AddPtr p1 o1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (Not (IsNonNil o1))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p2 := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddPtr {
|
||||
break
|
||||
}
|
||||
_ = v_1.Args[1]
|
||||
p1 := v_1.Args[0]
|
||||
o1 := v_1.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(o1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Const32 [0]) p)
|
||||
// cond:
|
||||
// result: (Not (IsNonNil p))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
p := v.Args[1]
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(p)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr p (Const32 [0]))
|
||||
// cond:
|
||||
// result: (Not (IsNonNil p))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConstNil {
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
if v_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(p)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Const64 [0]) p)
|
||||
// cond:
|
||||
// result: (Not (IsNonNil p))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
p := v.Args[1]
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(p)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr p (Const64 [0]))
|
||||
// cond:
|
||||
// result: (Not (IsNonNil p))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
if v_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpNot)
|
||||
|
|
@ -10257,63 +10577,20 @@ func rewriteValuegeneric_OpEqPtr_0(v *Value) bool {
|
|||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr x x)
|
||||
// match: (EqPtr p (ConstNil))
|
||||
// cond:
|
||||
// result: (ConstBool [1])
|
||||
// result: (Not (IsNonNil p))
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
if x != v.Args[1] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 1
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Addr {a} x) (Addr {b} x))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a == b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_0.Aux
|
||||
x := v_0.Args[0]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
if v_1.Op != OpConstNil {
|
||||
break
|
||||
}
|
||||
b := v_1.Aux
|
||||
if x != v_1.Args[0] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a == b)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Addr {b} x) (Addr {a} x))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a == b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_0.Aux
|
||||
x := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_1.Aux
|
||||
if x != v_1.Args[0] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a == b)
|
||||
v.reset(OpNot)
|
||||
v0 := b.NewValue0(v.Pos, OpIsNonNil, typ.Bool)
|
||||
v0.AddArg(p)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -11940,6 +12217,44 @@ func rewriteValuegeneric_OpIsNonNil_0(v *Value) bool {
|
|||
v.AuxInt = 0
|
||||
return true
|
||||
}
|
||||
// match: (IsNonNil (Const32 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != 0)])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != 0)
|
||||
return true
|
||||
}
|
||||
// match: (IsNonNil (Const64 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != 0)])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != 0)
|
||||
return true
|
||||
}
|
||||
// match: (IsNonNil (Addr _))
|
||||
// cond:
|
||||
// result: (ConstBool [1])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 1
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpIsSliceInBounds_0(v *Value) bool {
|
||||
|
|
@ -18020,14 +18335,324 @@ func rewriteValuegeneric_OpNeqInter_0(v *Value) bool {
|
|||
}
|
||||
}
|
||||
func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
|
||||
// match: (NeqPtr p (ConstNil))
|
||||
// match: (NeqPtr x x)
|
||||
// cond:
|
||||
// result: (ConstBool [0])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
if x != v.Args[1] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 0
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Addr {a} _) (Addr {b} _))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a != b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_0.Aux
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_1.Aux
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a != b)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Addr {b} _) (Addr {a} _))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a != b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_0.Aux
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_1.Aux
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a != b)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (OffPtr [o1] p1) p2)
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 != 0)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_0.AuxInt
|
||||
p1 := v_0.Args[0]
|
||||
p2 := v.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 != 0)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr p2 (OffPtr [o1] p1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 != 0)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p2 := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_1.AuxInt
|
||||
p1 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 != 0)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (OffPtr [o1] p1) (OffPtr [o2] p2))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 != o2)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_0.AuxInt
|
||||
p1 := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o2 := v_1.AuxInt
|
||||
p2 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 != o2)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (OffPtr [o2] p2) (OffPtr [o1] p1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (ConstBool [b2i(o1 != o2)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o2 := v_0.AuxInt
|
||||
p2 := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
o1 := v_1.AuxInt
|
||||
p1 := v_1.Args[0]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(o1 != o2)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Const32 [c]) (Const32 [d]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
d := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != d)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Const32 [d]) (Const32 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != d)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Const64 [c]) (Const64 [d]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
d := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != d)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
|
||||
// match: (NeqPtr (Const64 [d]) (Const64 [c]))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(c != d)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(c != d)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (AddPtr p1 o1) p2)
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (IsNonNil o1)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddPtr {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
p1 := v_0.Args[0]
|
||||
o1 := v_0.Args[1]
|
||||
p2 := v.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(o1)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr p2 (AddPtr p1 o1))
|
||||
// cond: isSamePtr(p1, p2)
|
||||
// result: (IsNonNil o1)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p2 := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddPtr {
|
||||
break
|
||||
}
|
||||
_ = v_1.Args[1]
|
||||
p1 := v_1.Args[0]
|
||||
o1 := v_1.Args[1]
|
||||
if !(isSamePtr(p1, p2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(o1)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Const32 [0]) p)
|
||||
// cond:
|
||||
// result: (IsNonNil p)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
p := v.Args[1]
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(p)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr p (Const32 [0]))
|
||||
// cond:
|
||||
// result: (IsNonNil p)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConstNil {
|
||||
if v_1.Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
if v_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(p)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Const64 [0]) p)
|
||||
// cond:
|
||||
// result: (IsNonNil p)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
p := v.Args[1]
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(p)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr p (Const64 [0]))
|
||||
// cond:
|
||||
// result: (IsNonNil p)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
if v_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpIsNonNil)
|
||||
|
|
@ -18048,63 +18673,18 @@ func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
|
|||
v.AddArg(p)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr x x)
|
||||
// match: (NeqPtr p (ConstNil))
|
||||
// cond:
|
||||
// result: (ConstBool [0])
|
||||
// result: (IsNonNil p)
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
if x != v.Args[1] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 0
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Addr {a} x) (Addr {b} x))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a != b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_0.Aux
|
||||
x := v_0.Args[0]
|
||||
p := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
if v_1.Op != OpConstNil {
|
||||
break
|
||||
}
|
||||
b := v_1.Aux
|
||||
if x != v_1.Args[0] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a != b)
|
||||
return true
|
||||
}
|
||||
// match: (NeqPtr (Addr {b} x) (Addr {a} x))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a != b)])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
b := v_0.Aux
|
||||
x := v_0.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
a := v_1.Aux
|
||||
if x != v_1.Args[0] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = b2i(a != b)
|
||||
v.reset(OpIsNonNil)
|
||||
v.AddArg(p)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
package codegen
|
||||
|
||||
// These tests check that memmoves calls on small data are replaced
|
||||
// with MOVs
|
||||
// Check small copies are replaced with moves.
|
||||
|
||||
func movesmall4() {
|
||||
x := [...]byte{1, 2, 3, 4}
|
||||
|
|
@ -31,3 +30,28 @@ func movesmall16() {
|
|||
// amd64:-".*memmove"
|
||||
copy(x[1:], x[:])
|
||||
}
|
||||
|
||||
// Check that no branches are generated when the pointers are [not] equal.
|
||||
|
||||
var x [256]byte
|
||||
|
||||
func ptrEqual() {
|
||||
// amd64:-"JEQ",-"JNE"
|
||||
// ppc64le:-"BEQ",-"BNE"
|
||||
// s390x:-"BEQ",-"BNE"
|
||||
copy(x[:], x[:])
|
||||
}
|
||||
|
||||
func ptrOneOffset() {
|
||||
// amd64:-"JEQ",-"JNE"
|
||||
// ppc64le:-"BEQ",-"BNE"
|
||||
// s390x:-"BEQ",-"BNE"
|
||||
copy(x[1:], x[:])
|
||||
}
|
||||
|
||||
func ptrBothOffset() {
|
||||
// amd64:-"JEQ",-"JNE"
|
||||
// ppc64le:-"BEQ",-"BNE"
|
||||
// s390x:-"BEQ",-"BNE"
|
||||
copy(x[1:], x[2:])
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue