aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/ssa/shortcircuit.go18
-rw-r--r--test/fixedbugs/issue45175.go29
2 files changed, 47 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go
index c5df457c4e..9cf29fe413 100644
--- a/src/cmd/compile/internal/ssa/shortcircuit.go
+++ b/src/cmd/compile/internal/ssa/shortcircuit.go
@@ -138,6 +138,24 @@ func shortcircuitBlock(b *Block) bool {
if len(b.Values) != nval+nOtherPhi {
return false
}
+ if nOtherPhi > 0 {
+ // Check for any phi which is the argument of another phi.
+ // These cases are tricky, as substitutions done by replaceUses
+ // are no longer trivial to do in any ordering. See issue 45175.
+ m := make(map[*Value]bool, 1+nOtherPhi)
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ m[v] = true
+ }
+ }
+ for v := range m {
+ for _, a := range v.Args {
+ if a != v && m[a] {
+ return false
+ }
+ }
+ }
+ }
// Locate index of first const phi arg.
cidx := -1
diff --git a/test/fixedbugs/issue45175.go b/test/fixedbugs/issue45175.go
new file mode 100644
index 0000000000..02dfe8a0a9
--- /dev/null
+++ b/test/fixedbugs/issue45175.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2021 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
+
+//go:noinline
+func f(c bool) int {
+ b := true
+ x := 0
+ y := 1
+ for b {
+ b = false
+ y = x
+ x = 2
+ if c {
+ return 3
+ }
+ }
+ return y
+}
+
+func main() {
+ if got := f(false); got != 0 {
+ panic(got)
+ }
+}