diff options
-rw-r--r-- | src/cmd/compile/internal/ssa/shortcircuit.go | 18 | ||||
-rw-r--r-- | test/fixedbugs/issue45175.go | 29 |
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 7b4ee2e81c..4dd86ec74f 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) + } +} |