Skip to content

Commit 19f0577

Browse files
committed
cmd/compile: schedule induction variable increments late
for ..; ..; i++ { ... } We want to schedule the i++ late in the block, so that all other uses of i in the block are scheduled first. That way, i++ can happen in place in a register instead of requiring a temporary register. Change-Id: Id777407c7e67a5ddbd8e58251099b0488138c0df Reviewed-on: https://go-review.googlesource.com/c/go/+/672998 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@google.com>
1 parent 11fa0de commit 19f0577

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const (
2222
ScoreMemory
2323
ScoreReadFlags
2424
ScoreDefault
25+
ScoreInductionInc // an increment of an induction variable
2526
ScoreFlags
2627
ScoreControl // towards bottom of block
2728
)
@@ -185,14 +186,29 @@ func schedule(f *Func) {
185186
// Note that this case is after the case above, so values
186187
// which both read and generate flags are given ScoreReadFlags.
187188
score[v.ID] = ScoreFlags
189+
case (len(v.Args) == 1 &&
190+
v.Args[0].Op == OpPhi &&
191+
v.Args[0].Uses > 1 &&
192+
len(b.Succs) == 1 &&
193+
b.Succs[0].b == v.Args[0].Block &&
194+
v.Args[0].Args[b.Succs[0].i] == v):
195+
// This is a value computing v++ (or similar) in a loop.
196+
// Try to schedule it later, so we issue all uses of v before the v++.
197+
// If we don't, then we need an additional move.
198+
// loop:
199+
// p = (PHI v ...)
200+
// ... ok other uses of p ...
201+
// v = (ADDQconst [1] p)
202+
// ... troublesome other uses of p ...
203+
// goto loop
204+
// We want to allocate p and v to the same register so when we get to
205+
// the end of the block we don't have to move v back to p's register.
206+
// But we can only do that if v comes after all the other uses of p.
207+
// Any "troublesome" use means we have to reg-reg move either p or v
208+
// somewhere in the loop.
209+
score[v.ID] = ScoreInductionInc
188210
default:
189211
score[v.ID] = ScoreDefault
190-
// If we're reading flags, schedule earlier to keep flag lifetime short.
191-
for _, a := range v.Args {
192-
if a.isFlagOp() {
193-
score[v.ID] = ScoreReadFlags
194-
}
195-
}
196212
}
197213
}
198214
for _, c := range b.ControlValues() {

test/codegen/schedule.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// asmcheck
2+
3+
// Copyright 2025 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package codegen
8+
9+
func f(n int) int {
10+
r := 0
11+
// arm64:-"MOVD\t R"
12+
// amd64:-"LEAQ","INCQ"
13+
for i := range n {
14+
r += i
15+
}
16+
return r
17+
}

0 commit comments

Comments
 (0)