diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2016-10-07 01:38:35 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2016-10-07 01:38:35 +0000 |
| commit | 8c03c1bade5b7fcfb3724dc65771ef9dcf8f8072 (patch) | |
| tree | 845e5ce8b9ff3b89d9fa68af6f298c7825142b61 | |
| parent | 16d29e31113b5fd593c66716d81d2da729a8cfec (diff) | |
| download | bcm5719-llvm-8c03c1bade5b7fcfb3724dc65771ef9dcf8f8072.tar.gz bcm5719-llvm-8c03c1bade5b7fcfb3724dc65771ef9dcf8f8072.zip | |
[SimplifyCFG] Correctly test for unconditional branches in GetCaseResults
GetCaseResults assumed that a terminator with one successor was an
unconditional branch. This is not necessarily the case, it could be a
cleanupret.
Strengthen the check by querying whether or not the terminator is
exceptional.
llvm-svn: 283517
| -rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 | ||||
| -rw-r--r-- | llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll | 60 |
2 files changed, 61 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 90ce6720182..1546a60c337 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4503,7 +4503,7 @@ GetCaseResults(SwitchInst *SI, ConstantInt *CaseVal, BasicBlock *CaseDest, ++I) { if (TerminatorInst *T = dyn_cast<TerminatorInst>(I)) { // If the terminator is a simple branch, continue to the next block. - if (T->getNumSuccessors() != 1) + if (T->getNumSuccessors() != 1 || T->isExceptional()) return false; Pred = CaseDest; CaseDest = T->getSuccessor(0); 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 bae8c1dc5a4..77e355a0052 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1334,3 +1334,63 @@ cleanup4: br label %while.body } +declare void @throw(i1) + +define void @wineh_test(i64 %val) personality i32 (...)* @__CxxFrameHandler3 { +entry: + invoke void @throw(i1 false) + to label %unreachable unwind label %cleanup1 + +unreachable: + unreachable + +cleanup1: + %cleanuppad1 = cleanuppad within none [] + switch i64 %val, label %cleanupdone2 [ + i64 0, label %cleanupdone1 + i64 1, label %cleanupdone1 + i64 6, label %cleanupdone1 + ] + +cleanupdone1: + cleanupret from %cleanuppad1 unwind label %cleanup2 + +cleanupdone2: + cleanupret from %cleanuppad1 unwind label %cleanup2 + +cleanup2: + %phi = phi i1 [ true, %cleanupdone1 ], [ false, %cleanupdone2 ] + %cleanuppad2 = cleanuppad within none [] + call void @throw(i1 %phi) [ "funclet"(token %cleanuppad2) ] + unreachable +} + +; CHECK-LABEL: @wineh_test( +; CHECK: entry: +; CHECK: invoke void @throw(i1 false) +; CHECK: to label %[[unreachable:.*]] unwind label %[[cleanup1:.*]] + +; CHECK: [[unreachable]]: +; CHECK: unreachable + +; CHECK: [[cleanup1]]: +; CHECK: %[[cleanuppad1:.*]] = cleanuppad within none [] +; CHECK: switch i64 %val, label %[[cleanupdone2:.*]] [ +; CHECK: i64 0, label %[[cleanupdone1:.*]] +; CHECK: i64 1, label %[[cleanupdone1]] +; CHECK: i64 6, label %[[cleanupdone1]] +; CHECK: ] + +; CHECK: [[cleanupdone1]]: +; CHECK: cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2:.*]] + +; CHECK: [[cleanupdone2]]: +; CHECK: cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2]] + +; CHECK: [[cleanup2]]: +; CHECK: %[[phi:.*]] = phi i1 [ true, %[[cleanupdone1]] ], [ false, %[[cleanupdone2]] ] +; CHECK: %[[cleanuppad2:.*]] = cleanuppad within none [] +; CHECK: call void @throw(i1 %[[phi]]) [ "funclet"(token %[[cleanuppad2]]) ] +; CHECK: unreachable + +declare i32 @__CxxFrameHandler3(...) |

