mirror of
https://github.com/golang/go
synced 2024-11-02 13:42:29 +00:00
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
4 changed files with 616 additions and 6 deletions
|
@ -742,10 +742,47 @@
|
|||
(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)
|
||||
|
||||
(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
|
||||
(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)
|
||||
|
||||
(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)
|
||||
(NE (CMPconst [0] x) yes no) => (NZ 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 {
|
||||
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])
|
||||
// result: (FlagConstant [addFlags32(int32(x),y)])
|
||||
for {
|
||||
|
@ -2521,6 +2535,20 @@ func rewriteValueARM64_OpARM64CMNWconst(v *Value) bool {
|
|||
}
|
||||
func rewriteValueARM64_OpARM64CMNconst(v *Value) bool {
|
||||
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])
|
||||
// result: (FlagConstant [addFlags64(x,y)])
|
||||
for {
|
||||
|
@ -2866,6 +2894,20 @@ func rewriteValueARM64_OpARM64CMPW(v *Value) bool {
|
|||
}
|
||||
func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
|
||||
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])
|
||||
// result: (FlagConstant [subFlags32(int32(x),y)])
|
||||
for {
|
||||
|
@ -2906,6 +2948,20 @@ func rewriteValueARM64_OpARM64CMPWconst(v *Value) bool {
|
|||
}
|
||||
func rewriteValueARM64_OpARM64CMPconst(v *Value) bool {
|
||||
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])
|
||||
// result: (FlagConstant [subFlags64(x,y)])
|
||||
for {
|
||||
|
@ -3985,6 +4041,242 @@ func rewriteValueARM64_OpARM64Equal(v *Value) bool {
|
|||
v.AddArg(v0)
|
||||
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]))
|
||||
// result: (MOVDconst [b2i(fc.eq())])
|
||||
for {
|
||||
|
@ -16435,6 +16727,242 @@ func rewriteValueARM64_OpARM64NotEqual(v *Value) bool {
|
|||
v.AddArg(v0)
|
||||
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]))
|
||||
// result: (MOVDconst [b2i(fc.ne())])
|
||||
for {
|
||||
|
|
|
@ -45,10 +45,6 @@ var complements = []obj.As{
|
|||
AADDW: ASUBW,
|
||||
ASUB: AADD,
|
||||
ASUBW: AADDW,
|
||||
ACMP: ACMN,
|
||||
ACMPW: ACMNW,
|
||||
ACMN: ACMP,
|
||||
ACMNW: ACMPW,
|
||||
}
|
||||
|
||||
// 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
|
||||
// complementary instruction.
|
||||
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 {
|
||||
p.From.Offset = -p.From.Offset
|
||||
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 {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = complements[p.As]
|
||||
|
|
|
@ -665,3 +665,52 @@ func equalVarString8(a string) bool {
|
|||
// ppc64le:-".*memequal"
|
||||
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 a new issue