]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: schedule induction variable increments late
authorKeith Randall <khr@golang.org>
Wed, 14 May 2025 22:57:58 +0000 (15:57 -0700)
committerKeith Randall <khr@golang.org>
Thu, 15 May 2025 21:06:41 +0000 (14:06 -0700)
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>
src/cmd/compile/internal/ssa/schedule.go
test/codegen/schedule.go [new file with mode: 0644]

index bce0108dcbbb1cf46cc5ebc23f892d19b208e105..325118a1827b04c37f75521b7758385b1ff1d8e0 100644 (file)
@@ -22,6 +22,7 @@ const (
        ScoreMemory
        ScoreReadFlags
        ScoreDefault
+       ScoreInductionInc // an increment of an induction variable
        ScoreFlags
        ScoreControl // towards bottom of block
 )
@@ -185,14 +186,29 @@ func schedule(f *Func) {
                                // Note that this case is after the case above, so values
                                // which both read and generate flags are given ScoreReadFlags.
                                score[v.ID] = ScoreFlags
+                       case (len(v.Args) == 1 &&
+                               v.Args[0].Op == OpPhi &&
+                               v.Args[0].Uses > 1 &&
+                               len(b.Succs) == 1 &&
+                               b.Succs[0].b == v.Args[0].Block &&
+                               v.Args[0].Args[b.Succs[0].i] == v):
+                               // This is a value computing v++ (or similar) in a loop.
+                               // Try to schedule it later, so we issue all uses of v before the v++.
+                               // If we don't, then we need an additional move.
+                               // loop:
+                               //     p = (PHI v ...)
+                               //     ... ok other uses of p ...
+                               //     v = (ADDQconst [1] p)
+                               //     ... troublesome other uses of p ...
+                               //     goto loop
+                               // We want to allocate p and v to the same register so when we get to
+                               // the end of the block we don't have to move v back to p's register.
+                               // But we can only do that if v comes after all the other uses of p.
+                               // Any "troublesome" use means we have to reg-reg move either p or v
+                               // somewhere in the loop.
+                               score[v.ID] = ScoreInductionInc
                        default:
                                score[v.ID] = ScoreDefault
-                               // If we're reading flags, schedule earlier to keep flag lifetime short.
-                               for _, a := range v.Args {
-                                       if a.isFlagOp() {
-                                               score[v.ID] = ScoreReadFlags
-                                       }
-                               }
                        }
                }
                for _, c := range b.ControlValues() {
diff --git a/test/codegen/schedule.go b/test/codegen/schedule.go
new file mode 100644 (file)
index 0000000..aafffd8
--- /dev/null
@@ -0,0 +1,17 @@
+// asmcheck
+
+// Copyright 2025 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
+
+func f(n int) int {
+       r := 0
+       // arm64:-"MOVD\t R"
+       // amd64:-"LEAQ","INCQ"
+       for i := range n {
+               r += i
+       }
+       return r
+}