// 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 !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]
+ }
}
}
}
--- /dev/null
+// 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)
+ }
+}