SimplifyCFG: check uses of constant-foldable instrs in switch destinations (PR20210)

The previous code assumed that such instructions could not have any uses
outside CaseDest, with the motivation that the instruction could not
dominate CommonDest because CommonDest has phi nodes in it. That simply
isn't true; e.g., CommonDest could have an edge back to itself.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225552 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Hans Wennborg 2015-01-09 22:13:31 +00:00
parent 34630b6ea9
commit ca71be6415
2 changed files with 55 additions and 6 deletions

View File

@ -3486,6 +3486,21 @@ GetCaseResults(SwitchInst *SI,
continue;
} else if (Constant *C = ConstantFold(I, ConstantPool, DL)) {
// Instruction is side-effect free and constant.
// If the instruction has uses outside this block or a phi node slot for
// the block, it is not safe to bypass the instruction since it would then
// no longer dominate all its uses.
for (auto &Use : I->uses()) {
User *User = Use.getUser();
if (Instruction *I = dyn_cast<Instruction>(User))
if (I->getParent() == CaseDest)
continue;
if (PHINode *Phi = dyn_cast<PHINode>(User))
if (Phi->getIncomingBlock(Use) == CaseDest)
continue;
return false;
}
ConstantPool.insert(std::make_pair(I, C));
} else {
break;
@ -3511,12 +3526,6 @@ GetCaseResults(SwitchInst *SI,
if (!ConstVal)
return false;
// Note: If the constant comes from constant-propagating the case value
// through the CaseDest basic block, it will be safe to remove the
// instructions in that block. They cannot be used (except in the phi nodes
// we visit) outside CaseDest, because that block does not dominate its
// successor. If it did, we would not be in this phi node.
// Be conservative about which kinds of constants we support.
if (!ValidLookupTableConstant(ConstVal))
return false;

View File

@ -1204,3 +1204,43 @@ return:
; CHECK-NEXT: [[R:%.+]] = select i1 %cmp
; CHECK-NEXT: ret i32 [[R]]
}
define void @pr20210(i8 %x, i1 %y) {
; %z has uses outside of its BB or the phi it feeds into,
; so doing a table lookup and jumping directly to while.cond would
; cause %z to cease dominating all its uses.
entry:
br i1 %y, label %sw, label %intermediate
sw:
switch i8 %x, label %end [
i8 7, label %intermediate
i8 3, label %intermediate
i8 2, label %intermediate
i8 1, label %intermediate
i8 0, label %intermediate
]
intermediate:
%z = zext i8 %x to i32
br label %while.cond
while.cond:
%i = phi i32 [ %z, %intermediate ], [ %j, %while.body ]
%b = icmp ne i32 %i, 7
br i1 %b, label %while.body, label %while.end
while.body:
%j = add i32 %i, 1
br label %while.cond
while.end:
call void @exit(i32 %z)
unreachable
end:
ret void
; CHECK-LABEL: @pr20210
; CHECK: switch i8 %x
}