(EqSlice x y) -> (EqPtr (SlicePtr x) (SlicePtr y))
(NeqSlice x y) -> (NeqPtr (SlicePtr x) (SlicePtr y))
+
+// Load of store of same address, with compatibly typed value and same size
+(Load <t1> p1 (Store [w] p2 x _)) && isSamePtr(p1,p2) && t1.Compare(x.Type)==CMPeq && w == t1.Size() -> x
+
+
// indexing operations
// Note: bounds check has already been done
(ArrayIndex (Load ptr mem) idx) && b == v.Args[0].Block -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
return uint64(a)+uint64(b) < uint64(a)
}
+// isSamePtr reports whether p1 and p2 point to the same address.
+func isSamePtr(p1, p2 *Value) bool {
+ // Aux isn't used in OffPtr, and AuxInt isn't currently used in
+ // Addr, but this still works as the values will be null/0
+ return (p1.Op == OpOffPtr || p1.Op == OpAddr) && p1.Op == p2.Op &&
+ p1.Aux == p2.Aux && p1.AuxInt == p2.AuxInt &&
+ p1.Args[0] == p2.Args[0]
+}
+
// DUFFZERO consists of repeated blocks of 4 MOVUPSs + ADD,
// See runtime/mkduff.go.
const (
func rewriteValuegeneric_OpLoad(v *Value, config *Config) bool {
b := v.Block
_ = b
+ // match: (Load <t1> p1 (Store [w] p2 x _))
+ // cond: isSamePtr(p1,p2) && t1.Compare(x.Type)==CMPeq && w == t1.Size()
+ // result: x
+ for {
+ t1 := v.Type
+ p1 := v.Args[0]
+ if v.Args[1].Op != OpStore {
+ break
+ }
+ w := v.Args[1].AuxInt
+ p2 := v.Args[1].Args[0]
+ x := v.Args[1].Args[1]
+ if !(isSamePtr(p1, p2) && t1.Compare(x.Type) == CMPeq && w == t1.Size()) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (Load <t> _ _)
// cond: t.IsStruct() && t.NumFields() == 0 && config.fe.CanSSA(t)
// result: (StructMake0)