From 7d1d69032bdaae0e1805054e003fd0a745141728 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Thu, 24 Apr 2014 09:08:21 -0400 Subject: [PATCH] =?UTF-8?q?go.tools/go/ssa:=20don't=20attempt=20fusion=20o?= =?UTF-8?q?n=20single-pred=20blocks=20with=20=CF=86-nodes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During block optimization, degenerate conditional logic such as "false && x" may result in single-predecessor blocks containing φ-nodes. (Ideally such φ-nodes would be replaced by their sole operand, but that requires Referrers information which isn't computed until later.) It is obviously not safe to fuse such blocks, so now we don't. Fixes golang/go#7840 LGTM=gri R=gri CC=golang-codereviews, pcc https://golang.org/cl/90620043 --- go/ssa/blockopt.go | 8 ++++++++ go/ssa/interp/testdata/coverage.go | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/go/ssa/blockopt.go b/go/ssa/blockopt.go index 64cfbeb8..e79260a2 100644 --- a/go/ssa/blockopt.go +++ b/go/ssa/blockopt.go @@ -117,6 +117,14 @@ func fuseBlocks(f *Function, a *BasicBlock) bool { if len(b.Preds) != 1 { return false } + + // Degenerate &&/|| ops may result in a straight-line CFG + // containing φ-nodes. (Ideally we'd replace such them with + // their sole operand but that requires Referrers, built later.) + if b.hasPhi() { + return false // not sound without further effort + } + // Eliminate jump at end of A, then copy all of B across. a.Instrs = append(a.Instrs[:len(a.Instrs)-1], b.Instrs...) for _, instr := range b.Instrs { diff --git a/go/ssa/interp/testdata/coverage.go b/go/ssa/interp/testdata/coverage.go index 5921f296..503e4e2f 100644 --- a/go/ssa/interp/testdata/coverage.go +++ b/go/ssa/interp/testdata/coverage.go @@ -636,3 +636,9 @@ func init() { panic(got) } } + +// Regression test for issue 7840 (covered by SSA sanity checker). +func bug7840() bool { + // This creates a single-predecessor block with a φ-node. + return false && a == 0 && a == 0 +}