mirror of https://github.com/golang/go.git
cmd/compile: Add some CMP and CMN optimization rules on arm64
This CL adds some optimizaion rules: 1, Converts CMP to CMN, or vice versa, when comparing with a negative number. 2, For equal and not equal comparisons, CMP can be converted to CMN in some cases. In theory we could do the same optimization for LT, LE, GT and GE, but need to account for overflow, this CL doesn't handle them. There are no noticeable performance changes. Change-Id: Ia49266c019ab7908ebc9510c2f02e121b1607869 Reviewed-on: https://go-review.googlesource.com/c/go/+/429795 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Eric Fang <eric.fang@arm.com>
This commit is contained in:
parent
7db923fe56
commit
cf53990b18
|
|
@ -742,10 +742,47 @@
|
||||||
(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
|
(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMN x y) yes no)
|
||||||
(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
|
(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMN x y) yes no)
|
||||||
|
|
||||||
|
(Equal (CMP x z:(NEG y))) && z.Uses == 1 => (Equal (CMN x y))
|
||||||
|
(NotEqual (CMP x z:(NEG y))) && z.Uses == 1 => (NotEqual (CMN x y))
|
||||||
|
|
||||||
// CMPW(x,-y) -> CMNW(x,y) is only valid for unordered comparison, if y can be -1<<31
|
// CMPW(x,-y) -> CMNW(x,y) is only valid for unordered comparison, if y can be -1<<31
|
||||||
(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
|
(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (EQ (CMNW x y) yes no)
|
||||||
(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
|
(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 => (NE (CMNW x y) yes no)
|
||||||
|
|
||||||
|
(Equal (CMPW x z:(NEG y))) && z.Uses == 1 => (Equal (CMNW x y))
|
||||||
|
(NotEqual (CMPW x z:(NEG y))) && z.Uses == 1 => (NotEqual (CMNW x y))
|
||||||
|
|
||||||
|
// For conditional instructions such as CSET, CSEL.
|
||||||
|
// TODO: add support for LT, LE, GT, GE, overflow needs to be considered.
|
||||||
|
(Equal (CMPconst [0] x:(ADDconst [c] y))) && x.Uses == 1 => (Equal (CMNconst [c] y))
|
||||||
|
(NotEqual (CMPconst [0] x:(ADDconst [c] y))) && x.Uses == 1 => (NotEqual (CMNconst [c] y))
|
||||||
|
|
||||||
|
(Equal (CMPWconst [0] x:(ADDconst [c] y))) && x.Uses == 1 => (Equal (CMNWconst [int32(c)] y))
|
||||||
|
(NotEqual (CMPWconst [0] x:(ADDconst [c] y))) && x.Uses == 1 => (NotEqual (CMNWconst [int32(c)] y))
|
||||||
|
|
||||||
|
(Equal (CMPconst [0] z:(ADD x y))) && z.Uses == 1 => (Equal (CMN x y))
|
||||||
|
(NotEqual (CMPconst [0] z:(ADD x y))) && z.Uses == 1 => (NotEqual (CMN x y))
|
||||||
|
|
||||||
|
(Equal (CMPWconst [0] z:(ADD x y))) && z.Uses == 1 => (Equal (CMNW x y))
|
||||||
|
(NotEqual (CMPWconst [0] z:(ADD x y))) && z.Uses == 1 => (NotEqual (CMNW x y))
|
||||||
|
|
||||||
|
(Equal (CMPconst [0] z:(MADD a x y))) && z.Uses==1 => (Equal (CMN a (MUL <x.Type> x y)))
|
||||||
|
(NotEqual (CMPconst [0] z:(MADD a x y))) && z.Uses==1 => (NotEqual (CMN a (MUL <x.Type> x y)))
|
||||||
|
|
||||||
|
(Equal (CMPconst [0] z:(MSUB a x y))) && z.Uses==1 => (Equal (CMP a (MUL <x.Type> x y)))
|
||||||
|
(NotEqual (CMPconst [0] z:(MSUB a x y))) && z.Uses==1 => (NotEqual (CMP a (MUL <x.Type> x y)))
|
||||||
|
|
||||||
|
(Equal (CMPWconst [0] z:(MADDW a x y))) && z.Uses==1 => (Equal (CMNW a (MULW <x.Type> x y)))
|
||||||
|
(NotEqual (CMPWconst [0] z:(MADDW a x y))) && z.Uses==1 => (NotEqual (CMNW a (MULW <x.Type> x y)))
|
||||||
|
|
||||||
|
(Equal (CMPWconst [0] z:(MSUBW a x y))) && z.Uses==1 => (Equal (CMPW a (MULW <x.Type> x y)))
|
||||||
|
(NotEqual (CMPWconst [0] z:(MSUBW a x y))) && z.Uses==1 => (NotEqual (CMPW a (MULW <x.Type> x y)))
|
||||||
|
|
||||||
|
(CMPconst [c] y) && c < 0 && c != -1<<63 => (CMNconst [-c] y)
|
||||||
|
(CMPWconst [c] y) && c < 0 && c != -1<<31 => (CMNWconst [-c] y)
|
||||||
|
(CMNconst [c] y) && c < 0 && c != -1<<63 => (CMPconst [-c] y)
|
||||||
|
(CMNWconst [c] y) && c < 0 && c != -1<<31 => (CMPWconst [-c] y)
|
||||||
|
|
||||||
(EQ (CMPconst [0] x) yes no) => (Z x yes no)
|
(EQ (CMPconst [0] x) yes no) => (Z x yes no)
|
||||||
(NE (CMPconst [0] x) yes no) => (NZ x yes no)
|
(NE (CMPconst [0] x) yes no) => (NZ x yes no)
|
||||||
(EQ (CMPWconst [0] x) yes no) => (ZW x yes no)
|
(EQ (CMPWconst [0] x) yes no) => (ZW x yes no)
|
||||||
|
|
|
||||||
|
|
@ -2505,6 +2505,20 @@ func rewriteValueARM64_OpARM64CMNW(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64CMNWconst(v *Value) bool {
|
func rewriteValueARM64_OpARM64CMNWconst(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
// match: (CMNWconst [c] y)
|
||||||
|
// cond: c < 0 && c != -1<<31
|
||||||
|
// result: (CMPWconst [-c] y)
|
||||||
|
for {
|
||||||
|
c := auxIntToInt32(v.AuxInt)
|
||||||
|
y := v_0
|
||||||
|
if !(c < 0 && c != -1<<31) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64CMPWconst)
|
||||||
|
v.AuxInt = int32ToAuxInt(-c)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (CMNWconst (MOVDconst [x]) [y])
|
// match: (CMNWconst (MOVDconst [x]) [y])
|
||||||
// result: (FlagConstant [addFlags32(int32(x),y)])
|
// result: (FlagConstant [addFlags32(int32(x),y)])
|
||||||
for {
|
for {
|
||||||
|
|
@ -2521,6 +2535,20 @@ func rewriteValueARM64_OpARM64CMNWconst(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64CMNconst(v *Value) bool {
|
func rewriteValueARM64_OpARM64CMNconst(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
// match: (CMNconst [c] y)
|
||||||
|
// cond: c < 0 && c != -1<<63
|
||||||
|
// result: (CMPconst [-c] y)
|
||||||
|
for {
|
||||||
|
c := auxIntToInt64(v.AuxInt)
|
||||||
|
y := v_0
|
||||||
|
if !(c < 0 && c != -1<<63) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64CMPconst)
|
||||||
|
v.AuxInt = int64ToAuxInt(-c)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (CMNconst (MOVDconst [x]) [y])
|
// match: (CMNconst (MOVDconst [x]) [y])
|
||||||
// result: (FlagConstant [addFlags64(x,y)])
|
// result: (FlagConstant [addFlags64(x,y)])
|
||||||
for {
|
for {
|
||||||
|
|
@ -2866,6 +2894,20 @@ func rewriteValueARM64_OpARM64CMPW(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
|
func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
// match: (CMPWconst [c] y)
|
||||||
|
// cond: c < 0 && c != -1<<31
|
||||||
|
// result: (CMNWconst [-c] y)
|
||||||
|
for {
|
||||||
|
c := auxIntToInt32(v.AuxInt)
|
||||||
|
y := v_0
|
||||||
|
if !(c < 0 && c != -1<<31) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64CMNWconst)
|
||||||
|
v.AuxInt = int32ToAuxInt(-c)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (CMPWconst (MOVDconst [x]) [y])
|
// match: (CMPWconst (MOVDconst [x]) [y])
|
||||||
// result: (FlagConstant [subFlags32(int32(x),y)])
|
// result: (FlagConstant [subFlags32(int32(x),y)])
|
||||||
for {
|
for {
|
||||||
|
|
@ -2906,6 +2948,20 @@ func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64CMPconst(v *Value) bool {
|
func rewriteValueARM64_OpARM64CMPconst(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
// match: (CMPconst [c] y)
|
||||||
|
// cond: c < 0 && c != -1<<63
|
||||||
|
// result: (CMNconst [-c] y)
|
||||||
|
for {
|
||||||
|
c := auxIntToInt64(v.AuxInt)
|
||||||
|
y := v_0
|
||||||
|
if !(c < 0 && c != -1<<63) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64CMNconst)
|
||||||
|
v.AuxInt = int64ToAuxInt(-c)
|
||||||
|
v.AddArg(y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (CMPconst (MOVDconst [x]) [y])
|
// match: (CMPconst (MOVDconst [x]) [y])
|
||||||
// result: (FlagConstant [subFlags64(x,y)])
|
// result: (FlagConstant [subFlags64(x,y)])
|
||||||
for {
|
for {
|
||||||
|
|
@ -3985,6 +4041,242 @@ func rewriteValueARM64_OpARM64Equal(v *Value) bool {
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (Equal (CMP x z:(NEG y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (Equal (CMN x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMP {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
z := v_0.Args[1]
|
||||||
|
if z.Op != OpARM64NEG {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPW x z:(NEG y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (Equal (CMNW x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
z := v_0.Args[1]
|
||||||
|
if z.Op != OpARM64NEG {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPconst [0] x:(ADDconst [c] y)))
|
||||||
|
// cond: x.Uses == 1
|
||||||
|
// result: (Equal (CMNconst [c] y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if x.Op != OpARM64ADDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(x.AuxInt)
|
||||||
|
y := x.Args[0]
|
||||||
|
if !(x.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
v0.AddArg(y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPWconst [0] x:(ADDconst [c] y)))
|
||||||
|
// cond: x.Uses == 1
|
||||||
|
// result: (Equal (CMNWconst [int32(c)] y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if x.Op != OpARM64ADDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(x.AuxInt)
|
||||||
|
y := x.Args[0]
|
||||||
|
if !(x.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = int32ToAuxInt(int32(c))
|
||||||
|
v0.AddArg(y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPconst [0] z:(ADD x y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (Equal (CMN x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64ADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPWconst [0] z:(ADD x y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (Equal (CMNW x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64ADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPconst [0] z:(MADD a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (Equal (CMN a (MUL <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPconst [0] z:(MSUB a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (Equal (CMP a (MUL <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MSUB {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPWconst [0] z:(MADDW a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (Equal (CMNW a (MULW <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MADDW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Equal (CMPWconst [0] z:(MSUBW a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (Equal (CMPW a (MULW <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MSUBW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64Equal)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (Equal (FlagConstant [fc]))
|
// match: (Equal (FlagConstant [fc]))
|
||||||
// result: (MOVDconst [b2i(fc.eq())])
|
// result: (MOVDconst [b2i(fc.eq())])
|
||||||
for {
|
for {
|
||||||
|
|
@ -16435,6 +16727,242 @@ func rewriteValueARM64_OpARM64NotEqual(v *Value) bool {
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (NotEqual (CMP x z:(NEG y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NotEqual (CMN x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMP {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
z := v_0.Args[1]
|
||||||
|
if z.Op != OpARM64NEG {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPW x z:(NEG y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NotEqual (CMNW x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
z := v_0.Args[1]
|
||||||
|
if z.Op != OpARM64NEG {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPconst [0] x:(ADDconst [c] y)))
|
||||||
|
// cond: x.Uses == 1
|
||||||
|
// result: (NotEqual (CMNconst [c] y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if x.Op != OpARM64ADDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(x.AuxInt)
|
||||||
|
y := x.Args[0]
|
||||||
|
if !(x.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
v0.AddArg(y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPWconst [0] x:(ADDconst [c] y)))
|
||||||
|
// cond: x.Uses == 1
|
||||||
|
// result: (NotEqual (CMNWconst [int32(c)] y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if x.Op != OpARM64ADDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(x.AuxInt)
|
||||||
|
y := x.Args[0]
|
||||||
|
if !(x.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
|
||||||
|
v0.AuxInt = int32ToAuxInt(int32(c))
|
||||||
|
v0.AddArg(y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPconst [0] z:(ADD x y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NotEqual (CMN x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64ADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPWconst [0] z:(ADD x y)))
|
||||||
|
// cond: z.Uses == 1
|
||||||
|
// result: (NotEqual (CMNW x y))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64ADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[1]
|
||||||
|
x := z.Args[0]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v0.AddArg2(x, y)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPconst [0] z:(MADD a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (NotEqual (CMN a (MUL <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MADD {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPconst [0] z:(MSUB a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (NotEqual (CMP a (MUL <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MSUB {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMP, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPWconst [0] z:(MADDW a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (NotEqual (CMNW a (MULW <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MADDW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NotEqual (CMPWconst [0] z:(MSUBW a x y)))
|
||||||
|
// cond: z.Uses==1
|
||||||
|
// result: (NotEqual (CMPW a (MULW <x.Type> x y)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
z := v_0.Args[0]
|
||||||
|
if z.Op != OpARM64MSUBW {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
y := z.Args[2]
|
||||||
|
a := z.Args[0]
|
||||||
|
x := z.Args[1]
|
||||||
|
if !(z.Uses == 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64NotEqual)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpARM64CMPW, types.TypeFlags)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
|
||||||
|
v1.AddArg2(x, y)
|
||||||
|
v0.AddArg2(a, v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (NotEqual (FlagConstant [fc]))
|
// match: (NotEqual (FlagConstant [fc]))
|
||||||
// result: (MOVDconst [b2i(fc.ne())])
|
// result: (MOVDconst [b2i(fc.ne())])
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,6 @@ var complements = []obj.As{
|
||||||
AADDW: ASUBW,
|
AADDW: ASUBW,
|
||||||
ASUB: AADD,
|
ASUB: AADD,
|
||||||
ASUBW: AADDW,
|
ASUBW: AADDW,
|
||||||
ACMP: ACMN,
|
|
||||||
ACMPW: ACMNW,
|
|
||||||
ACMN: ACMP,
|
|
||||||
ACMNW: ACMPW,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// zrReplace is the set of instructions for which $0 in the From operand
|
// zrReplace is the set of instructions for which $0 in the From operand
|
||||||
|
|
@ -382,12 +378,12 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||||
// Rewrite negative immediates as positive immediates with
|
// Rewrite negative immediates as positive immediates with
|
||||||
// complementary instruction.
|
// complementary instruction.
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case AADD, ASUB, ACMP, ACMN:
|
case AADD, ASUB:
|
||||||
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
|
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
|
||||||
p.From.Offset = -p.From.Offset
|
p.From.Offset = -p.From.Offset
|
||||||
p.As = complements[p.As]
|
p.As = complements[p.As]
|
||||||
}
|
}
|
||||||
case AADDW, ASUBW, ACMPW, ACMNW:
|
case AADDW, ASUBW:
|
||||||
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
|
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
|
||||||
p.From.Offset = -p.From.Offset
|
p.From.Offset = -p.From.Offset
|
||||||
p.As = complements[p.As]
|
p.As = complements[p.As]
|
||||||
|
|
|
||||||
|
|
@ -665,3 +665,52 @@ func equalVarString8(a string) bool {
|
||||||
// ppc64le:-".*memequal"
|
// ppc64le:-".*memequal"
|
||||||
return a[:8] == b
|
return a[:8] == b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmpToCmn(a, b, c, d int) int {
|
||||||
|
var c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11 int
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a < -8 {
|
||||||
|
c1 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a+1 == 0 {
|
||||||
|
c2 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a+3 != 0 {
|
||||||
|
c3 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a+b == 0 {
|
||||||
|
c4 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if b+c != 0 {
|
||||||
|
c5 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a == -c {
|
||||||
|
c6 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if b != -d {
|
||||||
|
c7 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a*b+c == 0 {
|
||||||
|
c8 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMN`,-`CMP`
|
||||||
|
if a*c+b != 0 {
|
||||||
|
c9 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMP`,-`CMN`
|
||||||
|
if b*c-a == 0 {
|
||||||
|
c10 = 1
|
||||||
|
}
|
||||||
|
// arm64:`CMP`,-`CMN`
|
||||||
|
if a*d-b != 0 {
|
||||||
|
c11 = 1
|
||||||
|
}
|
||||||
|
return c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9 + c10 + c11
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue