mirror of
https://github.com/golang/go.git
synced 2025-10-19 19:13:18 +00:00
[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 <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit f15cd63ec4
)
Reviewed-on: https://go-review.googlesource.com/c/go/+/706575
This commit is contained in:
parent
2e1e356e33
commit
9b28db7770
2 changed files with 92 additions and 12 deletions
|
@ -118,6 +118,8 @@ func tighten(f *Func) {
|
||||||
|
|
||||||
// If the target location is inside a loop,
|
// If the target location is inside a loop,
|
||||||
// move the target location up to just before the loop head.
|
// move the target location up to just before the loop head.
|
||||||
|
if !loops.hasIrreducible {
|
||||||
|
// Loop info might not be correct for irreducible loops. See issue 75569.
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
origloop := loops.b2l[b.ID]
|
origloop := loops.b2l[b.ID]
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
|
@ -133,6 +135,7 @@ func tighten(f *Func) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Move values to target locations.
|
// Move values to target locations.
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
|
|
77
test/fixedbugs/issue75569.go
Normal file
77
test/fixedbugs/issue75569.go
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue