diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go index 7b4ee2e81c..c72c86a67e 100644 --- a/src/cmd/compile/internal/ssa/shortcircuit.go +++ b/src/cmd/compile/internal/ssa/shortcircuit.go @@ -266,6 +266,13 @@ func shortcircuitPhiPlan(b *Block, ctl *Value, cidx int, ti int64) func(*Value, // u is the "untaken" branch: the successor we never go to when coming in from p. u := b.Succs[1^ti].b + // In the following CFG matching, ensure that b's preds are entirely distinct from b's succs. + // This is probably a stronger condition than required, but this happens extremely rarely, + // and it makes it easier to avoid getting deceived by pretty ASCII charts. See #44465. + if p0, p1 := b.Preds[0].b, b.Preds[1].b; p0 == t || p1 == t || p0 == u || p1 == u { + return nil + } + // Look for some common CFG structures // in which the outbound paths from b merge, // with no other preds joining them. diff --git a/test/fixedbugs/issue44465.go b/test/fixedbugs/issue44465.go new file mode 100644 index 0000000000..8cb62adaac --- /dev/null +++ b/test/fixedbugs/issue44465.go @@ -0,0 +1,21 @@ +// compile -d=ssa/check/seed + +// 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. + +// This code caused an internal consistency error due to a bad shortcircuit optimization. + +package p + +func f() { + var b bool + if b { + b = true + } +l: + for !b { + b = true + goto l + } +}