Skip to content

Commit d681270

Browse files
committed
cmd/compile: allow load-op merging in additional situations
x += *p We want to do this with a single load+add operation on amd64. The tricky part is that we don't want to combine if there are other uses of x after this instruction. Implement a simple detector that seems to capture a common situation - x += *p is in a loop, and the other use of x is after loop exit. In that case, it does not hurt to do the load+add combo. Change-Id: I466174cce212e78bde83f908cc1f2752b560c49c Reviewed-on: https://go-review.googlesource.com/c/go/+/672957 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent a88f093 commit d681270

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,18 @@ func canMergeLoadClobber(target, load, x *Value) bool {
286286
// approximate x dying with:
287287
// 1) target is x's only use.
288288
// 2) target is not in a deeper loop than x.
289-
if x.Uses != 1 {
289+
switch {
290+
case x.Uses == 2 && x.Op == OpPhi && len(x.Args) == 2 && (x.Args[0] == target || x.Args[1] == target) && target.Uses == 1:
291+
// This is a simple detector to determine that x is probably
292+
// not live after target. (It does not need to be perfect,
293+
// regalloc will issue a reg-reg move to save it if we are wrong.)
294+
// We have:
295+
// x = Phi(?, target)
296+
// target = Op(load, x)
297+
// Because target has only one use as a Phi argument, we can schedule it
298+
// very late. Hopefully, later than the other use of x. (The other use died
299+
// between x and target, or exists on another branch entirely).
300+
case x.Uses > 1:
290301
return false
291302
}
292303
loopnest := x.Block.Func.loopnest()

test/codegen/memcombine.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,15 @@ func load_op_no_merge(p, q *int) {
396396
}
397397
}
398398

399+
func load_op_in_loop(a []int) int {
400+
r := 0
401+
for _, x := range a {
402+
// amd64:`ADDQ\t\([A-Z]+\)\([A-Z]+\*8\), [A-Z]+`
403+
r += x
404+
}
405+
return r
406+
}
407+
399408
// Make sure offsets are folded into loads and stores.
400409
func offsets_fold(_, a [20]byte) (b [20]byte) {
401410
// arm64:`MOVD\tcommand-line-arguments\.a\+[0-9]+\(FP\), R[0-9]+`,`MOVD\tR[0-9]+, command-line-arguments\.b\+[0-9]+\(FP\)`

0 commit comments

Comments
 (0)