Keith Randall would like David Chase to review this change.
cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75569
diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go
index 48efdb5..0de586a 100644
--- a/src/cmd/compile/internal/ssa/tighten.go
+++ b/src/cmd/compile/internal/ssa/tighten.go
@@ -5,6 +5,7 @@
package ssa
import "cmd/compile/internal/base"
+import "fmt"
// tighten moves Values closer to the Blocks in which they are used.
// This can reduce the amount of register spilling required,
@@ -123,18 +124,30 @@
// If the target location is inside a loop,
// move the target location up to just before the loop head.
- for _, b := range f.Blocks {
- origloop := loops.b2l[b.ID]
- for _, v := range b.Values {
- t := target[v.ID]
- if t == nil {
- continue
- }
- targetloop := loops.b2l[t.ID]
- for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
- t = idom[targetloop.header.ID]
- target[v.ID] = t
- targetloop = loops.b2l[t.ID]
+ if f.Name == "fff" || f.Name == "(*Machine).Parse" {
+ fmt.Printf("irred: %v\n", loops.hasIrreducible)
+ for _, loop := range loops.loops {
+ fmt.Printf("LOOP header=%v outer=%v\n", loop.header, loop.outer)
+ }
+ for _, b := range f.Blocks {
+ fmt.Printf(" b=%v loop=%v\n", b, loops.b2l[b.ID])
+ }
+ }
+ if !loops.hasIrreducible {
+ // Loop info might not be correct for irreducible loops. See issue 75569.
+ for _, b := range f.Blocks {
+ origloop := loops.b2l[b.ID]
+ for _, v := range b.Values {
+ t := target[v.ID]
+ if t == nil {
+ continue
+ }
+ targetloop := loops.b2l[t.ID]
+ for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
+ t = idom[targetloop.header.ID]
+ target[v.ID] = t
+ targetloop = loops.b2l[t.ID]
+ }
}
}
}
diff --git a/test/fixedbugs/issue75569.go b/test/fixedbugs/issue75569.go
new file mode 100644
index 0000000..8420641
--- /dev/null
+++ b/test/fixedbugs/issue75569.go
@@ -0,0 +1,77 @@
+// run
+
+// 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 main
+
+func fff(a []int, b bool, p, q *int) {
+outer:
+ n := a[0]
+ a = a[1:]
+ switch n {
+ case 1:
+ goto one
+ case 2:
+ goto two
+ case 3:
+ goto three
+ case 4:
+ goto four
+ }
+
+one:
+ goto inner
+two:
+ goto outer
+three:
+ goto inner
+four:
+ goto innerSideEntry
+
+inner:
+ n = a[0]
+ a = a[1:]
+ switch n {
+ case 1:
+ goto outer
+ case 2:
+ goto inner
+ case 3:
+ goto innerSideEntry
+ default:
+ return
+ }
+innerSideEntry:
+ n = a[0]
+ a = a[1:]
+ switch n {
+ case 1:
+ goto outer
+ case 2:
+ goto inner
+ case 3:
+ goto inner
+ }
+ ggg(p, q)
+ goto inner
+}
+
+var b bool
+
+func ggg(p, q *int) {
+ n := *p + 5 // this +5 ends up in the entry block, well before the *p load
+ if b {
+ *q = 0
+ }
+ *p = n
+}
+
+func main() {
+ var x, y int
+ fff([]int{4, 4, 4}, false, &x, &y)
+ if x != 5 {
+ panic(x)
+ }
+}
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Code-Review | +1 |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75569
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
[release-branch.go1.24] cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75594
Change-Id: Idd80e6d2268094b8ae6387563081fdc1e211856a
Reviewed-on: https://go-review.googlesource.com/c/go/+/706355
Reviewed-by: David Chase <drc...@google.com>
LUCI-TryBot-Result: Go LUCI <golang...@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <k...@google.com>
(cherry picked from commit f15cd63ec4860c4f2c23cc992843546e0265c332)
diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go
index 85b6a84..bfb1862 100644
--- a/src/cmd/compile/internal/ssa/tighten.go
+++ b/src/cmd/compile/internal/ssa/tighten.go
@@ -118,18 +118,21 @@
// If the target location is inside a loop,
// move the target location up to just before the loop head.
- for _, b := range f.Blocks {
- origloop := loops.b2l[b.ID]
- for _, v := range b.Values {
- t := target[v.ID]
- if t == nil {
- continue
- }
- targetloop := loops.b2l[t.ID]
- for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
- t = idom[targetloop.header.ID]
- target[v.ID] = t
- targetloop = loops.b2l[t.ID]
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
[release-branch.go1.25] cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75595
Change-Id: Idd80e6d2268094b8ae6387563081fdc1e211856a
Reviewed-on: https://go-review.googlesource.com/c/go/+/706355
Reviewed-by: David Chase <drc...@google.com>
LUCI-TryBot-Result: Go LUCI <golang...@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <k...@google.com>
(cherry picked from commit f15cd63ec4860c4f2c23cc992843546e0265c332)
diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go
index eb5007b..0a4b56d 100644
--- a/src/cmd/compile/internal/ssa/tighten.go
+++ b/src/cmd/compile/internal/ssa/tighten.go
@@ -124,18 +124,21 @@
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Code-Review | +1 |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Code-Review | +2 |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Commit-Queue | +1 |
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
[release-branch.go1.24] cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75594
Change-Id: Idd80e6d2268094b8ae6387563081fdc1e211856a
Reviewed-on: https://go-review.googlesource.com/c/go/+/706355
Reviewed-by: David Chase <drc...@google.com>
LUCI-TryBot-Result: Go LUCI <golang...@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <k...@google.com>
(cherry picked from commit f15cd63ec4860c4f2c23cc992843546e0265c332)
Reviewed-on: https://go-review.googlesource.com/c/go/+/706575
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
[release-branch.go1.25] cmd/compile: don't rely on loop info when there are irreducible loops
Loop information is sketchy when there are irreducible loops.
Sometimes blocks inside 2 loops can be recorded as only being part of
the outer loop. That causes tighten to move values that want to move
into such a block to move out of the loop altogether, breaking the
invariant that operations have to be scheduled after their args.
Fixes #75595
Change-Id: Idd80e6d2268094b8ae6387563081fdc1e211856a
Reviewed-on: https://go-review.googlesource.com/c/go/+/706355
Reviewed-by: David Chase <drc...@google.com>
LUCI-TryBot-Result: Go LUCI <golang...@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <k...@google.com>
(cherry picked from commit f15cd63ec4860c4f2c23cc992843546e0265c332)
Reviewed-on: https://go-review.googlesource.com/c/go/+/706576
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |