// fold offset into address
(ADDconst [off1] (MOVWaddr [off2] {sym} ptr)) -> (MOVWaddr [off1+off2] {sym} ptr)
+(SUBconst [off1] (MOVWaddr [off2] {sym} ptr)) -> (MOVWaddr [off2-off1] {sym} ptr)
// fold address into load/store
(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBload [off1+off2] {sym} ptr mem)
+(MOVBload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVBload [off1-off2] {sym} ptr mem)
(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBUload [off1+off2] {sym} ptr mem)
+(MOVBUload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVBUload [off1-off2] {sym} ptr mem)
(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVHload [off1+off2] {sym} ptr mem)
+(MOVHload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVHload [off1-off2] {sym} ptr mem)
(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVHUload [off1+off2] {sym} ptr mem)
+(MOVHUload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVHUload [off1-off2] {sym} ptr mem)
(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVWload [off1+off2] {sym} ptr mem)
+(MOVWload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVWload [off1-off2] {sym} ptr mem)
(MOVFload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVFload [off1+off2] {sym} ptr mem)
+(MOVFload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVFload [off1-off2] {sym} ptr mem)
(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVDload [off1+off2] {sym} ptr mem)
+(MOVDload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVDload [off1-off2] {sym} ptr mem)
(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem)
+(MOVBstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVBstore [off1-off2] {sym} ptr val mem)
(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVHstore [off1+off2] {sym} ptr val mem)
+(MOVHstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVHstore [off1-off2] {sym} ptr val mem)
(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVWstore [off1+off2] {sym} ptr val mem)
+(MOVWstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVWstore [off1-off2] {sym} ptr val mem)
(MOVFstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVFstore [off1+off2] {sym} ptr val mem)
+(MOVFstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVFstore [off1-off2] {sym} ptr val mem)
(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVDstore [off1+off2] {sym} ptr val mem)
+(MOVDstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVDstore [off1-off2] {sym} ptr val mem)
(MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(BICconst [c] _) && int32(c)==-1 -> (MOVWconst [0])
// generic constant folding
+(ADDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) -> (SUBconst [int64(int32(-c))] x)
+(SUBconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) -> (ADDconst [int64(int32(-c))] x)
(ADDconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(c+d))])
(ADDconst [c] (ADDconst [d] x)) -> (ADDconst [int64(int32(c+d))] x)
(ADDconst [c] (SUBconst [d] x)) -> (ADDconst [int64(int32(c-d))] x)
(XORconst [c] (MOVWconst [d])) -> (MOVWconst [c^d])
(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
(BICconst [c] (MOVWconst [d])) -> (MOVWconst [d&^c])
+(BICconst [c] (BICconst [d] x)) -> (BICconst [int64(int32(c|d))] x)
(MVN (MOVWconst [c])) -> (MOVWconst [^c])
(MOVBreg (MOVWconst [c])) -> (MOVWconst [int64(int8(c))])
(MOVBUreg (MOVWconst [c])) -> (MOVWconst [int64(uint8(c))])
v.AddArg(x)
return true
}
+ // match: (ADDconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))
+ // result: (SUBconst [int64(int32(-c))] x)
+ for {
+ c := v.AuxInt
+ x := v.Args[0]
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))) {
+ break
+ }
+ v.reset(OpARMSUBconst)
+ v.AuxInt = int64(int32(-c))
+ v.AddArg(x)
+ return true
+ }
// match: (ADDconst [c] (MOVWconst [d]))
// cond:
// result: (MOVWconst [int64(int32(c+d))])
v.AuxInt = d &^ c
return true
}
+ // match: (BICconst [c] (BICconst [d] x))
+ // cond:
+ // result: (BICconst [int64(int32(c|d))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMBICconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpARMBICconst)
+ v.AuxInt = int64(int32(c | d))
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueARM_OpARMBICshiftLL_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVBUload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVBUload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVBUload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVBload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVBload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVBload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVBstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // cond:
+ // result: (MOVBstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ v.reset(OpARMMOVBstore)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
v.AddArg(mem)
return true
}
+ // match: (MOVDload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVDload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVDload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVDstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // cond:
+ // result: (MOVDstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ v.reset(OpARMMOVDstore)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
v.AddArg(mem)
return true
}
+ // match: (MOVFload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVFload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVFload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVFstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // cond:
+ // result: (MOVFstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ v.reset(OpARMMOVFstore)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
v.AddArg(mem)
return true
}
+ // match: (MOVHUload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVHUload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVHUload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVHload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVHload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVHload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVHstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // cond:
+ // result: (MOVHstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ v.reset(OpARMMOVHstore)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
v.AddArg(mem)
return true
}
+ // match: (MOVWload [off1] {sym} (SUBconst [off2] ptr) mem)
+ // cond:
+ // result: (MOVWload [off1-off2] {sym} ptr mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ mem := v.Args[1]
+ v.reset(OpARMMOVWload)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
v.AddArg(mem)
return true
}
+ // match: (MOVWstore [off1] {sym} (SUBconst [off2] ptr) val mem)
+ // cond:
+ // result: (MOVWstore [off1-off2] {sym} ptr val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMSUBconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ ptr := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ v.reset(OpARMMOVWstore)
+ v.AuxInt = off1 - off2
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
return false
}
func rewriteValueARM_OpARMSUBconst_0(v *Value) bool {
+ // match: (SUBconst [off1] (MOVWaddr [off2] {sym} ptr))
+ // cond:
+ // result: (MOVWaddr [off2-off1] {sym} ptr)
+ for {
+ off1 := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARMMOVWaddr {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym := v_0.Aux
+ ptr := v_0.Args[0]
+ v.reset(OpARMMOVWaddr)
+ v.AuxInt = off2 - off1
+ v.Aux = sym
+ v.AddArg(ptr)
+ return true
+ }
// match: (SUBconst [0] x)
// cond:
// result: x
v.AddArg(x)
return true
}
+ // match: (SUBconst [c] x)
+ // cond: !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))
+ // result: (ADDconst [int64(int32(-c))] x)
+ for {
+ c := v.AuxInt
+ x := v.Args[0]
+ if !(!isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c))) {
+ break
+ }
+ v.reset(OpARMADDconst)
+ v.AuxInt = int64(int32(-c))
+ v.AddArg(x)
+ return true
+ }
// match: (SUBconst [c] (MOVWconst [d]))
// cond:
// result: (MOVWconst [int64(int32(d-c))])