summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2015-01-09 22:13:31 +0000
committerHans Wennborg <hans@hanshq.net>2015-01-09 22:13:31 +0000
commitdcc6e5bc0365f484a78408e1841d1c81e32cd96c (patch)
tree5a70c7c76b19f7ea79f80b66af43530b1a1f67d9
parentec1f2c2cab6d00f7193c335ac06b984bb0c480e6 (diff)
downloadbcm5719-llvm-dcc6e5bc0365f484a78408e1841d1c81e32cd96c.tar.gz
bcm5719-llvm-dcc6e5bc0365f484a78408e1841d1c81e32cd96c.zip
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. llvm-svn: 225552
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp21
-rw-r--r--llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll40
2 files changed, 55 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ab45c1d21a5..50ebdb77158 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -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;
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index 95c9cc539d2..22f18cd4d43 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -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
+}
OpenPOWER on IntegriCloud