Skip to content

Commit

Permalink
cmd/compile: reject some rare looping CFGs in shortcircuit
Browse files Browse the repository at this point in the history
One CFGs that shortcircuit looks for is:
 
p   q
 \ /
  b
 / \
t   u

The test case creates a CFG like that in which p == t.
That caused the compiler to generate a (short-lived) invalid phi value.

Fix this with a relatively big hammer: Disallow single-length loops entirely.
This is probably overkill, but it such loops are very rare.
This doesn't change the generated code for anything in std.

It generates worse code for the test case:
It no longer compiles the entire function away.

Fixes #44465

Change-Id: Ib8cdcd6cc9d7f48b4dab253652038ace24eae152
Reviewed-on: https://go-review.googlesource.com/c/go/+/295130
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
  • Loading branch information
josharian committed Feb 22, 2021
1 parent 87e984a commit 0490347
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/cmd/compile/internal/ssa/shortcircuit.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions test/fixedbugs/issue44465.go
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 0490347

Please sign in to comment.