// Get rid of Convert ops for pointer arithmetic on unsafe.Pointer.
(Convert (Add(64|32) (Convert ptr mem) off) mem) => (AddPtr ptr off)
(Convert (Convert ptr mem) mem) => ptr
+// Note: it is important that the target rewrite is ptr+(off1+off2), not (ptr+off1)+off2.
+// We must ensure that no intermediate computations are invalid pointers.
+(Convert a:(Add(64|32) (Add(64|32) (Convert ptr mem) off1) off2) mem) => (AddPtr ptr (Add(64|32) <a.Type> off1 off2))
// strength reduction of divide by a constant.
// See ../magic.go for a detailed description of these algorithms.
func rewriteValuegeneric_OpConvert(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
+ b := v.Block
// match: (Convert (Add64 (Convert ptr mem) off) mem)
// result: (AddPtr ptr off)
for {
v.copyOf(ptr)
return true
}
+ // match: (Convert a:(Add64 (Add64 (Convert ptr mem) off1) off2) mem)
+ // result: (AddPtr ptr (Add64 <a.Type> off1 off2))
+ for {
+ a := v_0
+ if a.Op != OpAdd64 {
+ break
+ }
+ _ = a.Args[1]
+ a_0 := a.Args[0]
+ a_1 := a.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, a_0, a_1 = _i0+1, a_1, a_0 {
+ if a_0.Op != OpAdd64 {
+ continue
+ }
+ _ = a_0.Args[1]
+ a_0_0 := a_0.Args[0]
+ a_0_1 := a_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, a_0_0, a_0_1 = _i1+1, a_0_1, a_0_0 {
+ if a_0_0.Op != OpConvert {
+ continue
+ }
+ mem := a_0_0.Args[1]
+ ptr := a_0_0.Args[0]
+ off1 := a_0_1
+ off2 := a_1
+ if mem != v_1 {
+ continue
+ }
+ v.reset(OpAddPtr)
+ v0 := b.NewValue0(v.Pos, OpAdd64, a.Type)
+ v0.AddArg2(off1, off2)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+ }
+ break
+ }
+ // match: (Convert a:(Add32 (Add32 (Convert ptr mem) off1) off2) mem)
+ // result: (AddPtr ptr (Add32 <a.Type> off1 off2))
+ for {
+ a := v_0
+ if a.Op != OpAdd32 {
+ break
+ }
+ _ = a.Args[1]
+ a_0 := a.Args[0]
+ a_1 := a.Args[1]
+ for _i0 := 0; _i0 <= 1; _i0, a_0, a_1 = _i0+1, a_1, a_0 {
+ if a_0.Op != OpAdd32 {
+ continue
+ }
+ _ = a_0.Args[1]
+ a_0_0 := a_0.Args[0]
+ a_0_1 := a_0.Args[1]
+ for _i1 := 0; _i1 <= 1; _i1, a_0_0, a_0_1 = _i1+1, a_0_1, a_0_0 {
+ if a_0_0.Op != OpConvert {
+ continue
+ }
+ mem := a_0_0.Args[1]
+ ptr := a_0_0.Args[0]
+ off1 := a_0_1
+ off2 := a_1
+ if mem != v_1 {
+ continue
+ }
+ v.reset(OpAddPtr)
+ v0 := b.NewValue0(v.Pos, OpAdd32, a.Type)
+ v0.AddArg2(off1, off2)
+ v.AddArg2(ptr, v0)
+ return true
+ }
+ }
+ break
+ }
return false
}
func rewriteValuegeneric_OpCtz16(v *Value) bool {
--- /dev/null
+// asmcheck
+
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "unsafe"
+
+func f(p unsafe.Pointer, x, y uintptr) int64 {
+ p = unsafe.Pointer(uintptr(p) + x + y)
+ // amd64:`MOVQ\s\(.*\)\(.*\*1\), `
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\), `
+ return *(*int64)(p)
+}