[ifcnv] Don't duplicate blocks that contain convergent instructions.

It's unsafe to duplicate blocks that contain convergent instructions
during ifcnv.  See the patch for details.

Reviewers: hfinkel

Differential Revision: http://reviews.llvm.org/D17518

llvm-svn: 266404
This commit is contained in:
Justin Lebar 2016-04-15 01:38:41 +00:00
parent f04e678e36
commit 7dba2e0d0c
1 changed files with 31 additions and 1 deletions

View File

@ -678,7 +678,37 @@ void IfConverter::ScanInstructions(BBInfo &BBI) {
if (MI.isDebugValue())
continue;
if (MI.isNotDuplicable())
// It's unsafe to duplicate convergent instructions in this context, so set
// BBI.CannotBeCopied to true if MI is convergent. To see why, consider the
// following CFG, which is subject to our "simple" transformation.
//
// BB0 // if (c1) goto BB1; else goto BB2;
// / \
// BB1 |
// | BB2 // if (c2) goto TBB; else goto FBB;
// | / |
// | / |
// TBB |
// | |
// | FBB
// |
// exit
//
// Suppose we want to move TBB's contents up into BB1 and BB2 (in BB1 they'd
// be unconditional, and in BB2, they'd be predicated upon c2), and suppose
// TBB contains a convergent instruction. This is safe iff doing so does
// not add a control-flow dependency to the convergent instruction -- i.e.,
// it's safe iff the set of control flows that leads us to the convergent
// instruction does not get smaller after the transformation.
//
// Originally we executed TBB if c1 || c2. After the transformation, there
// are two copies of TBB's instructions. We get to the first if c1, and we
// get to the second if !c1 && c2.
//
// There are clearly fewer ways to satisfy the condition "c1" than
// "c1 || c2". Since we've shrunk the set of control flows which lead to
// our convergent instruction, the transformation is unsafe.
if (MI.isNotDuplicable() || MI.isConvergent())
BBI.CannotBeCopied = true;
bool isPredicated = TII->isPredicated(MI);