1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:14:41 -07:00

cmd/compile: pull multiple adds out of an unsafe.Pointer<->uintptr conversion

This came up in some swissmap code.

Change-Id: I3c6705a5cafec8cb4953dfa9535cf0b45255cc83
Reviewed-on: https://go-review.googlesource.com/c/go/+/629516
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2024-11-18 15:52:13 -08:00
parent fab2b8b0fa
commit f0b0109242
3 changed files with 94 additions and 0 deletions

View File

@ -988,6 +988,9 @@
// 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.

View File

@ -5759,6 +5759,7 @@ func rewriteValuegeneric_OpConstString(v *Value) bool {
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 {
@ -5823,6 +5824,80 @@ func rewriteValuegeneric_OpConvert(v *Value) bool {
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 {

16
test/codegen/unsafe.go Normal file
View File

@ -0,0 +1,16 @@
// 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)
}