From 7a301c1b8c96770cc946a128b41d79402354fe3f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 24 Apr 2015 20:57:56 +0000 Subject: [PATCH] SimplifyCFG: Correctly handle switch lookup tables which fully cover the input type and use bit tests to check for holes When using bit tests for hole checks, we call AddPredecessorToBlock to give the phi node a value from the bit test block. This would break if we've previously called removePredecessor on the default destination because the switch is fully covered. Test case by Mark Lacey. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235771 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 13 ++++++--- .../SimplifyCFG/X86/switch_to_lookup_table.ll | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 7c239cb19b7..60ac271bceb 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4159,10 +4159,8 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, if (!DefaultIsReachable || GeneratingCoveredLookupTable) { Builder.CreateBr(LookupBB); - // We cached PHINodes in PHIs, to avoid accessing deleted PHINodes later, - // do not delete PHINodes here. - SI->getDefaultDest()->removePredecessor(SI->getParent(), - /*DontDeleteUselessPHIs=*/true); + // Note: We call removeProdecessor later since we need to be able to get the + // PHI value for the default case in case we're using a bit mask. } else { Value *Cmp = Builder.CreateICmpULT(TableIndex, ConstantInt::get( MinCaseVal->getType(), TableSize)); @@ -4214,6 +4212,13 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, AddPredecessorToBlock(SI->getDefaultDest(), MaskBB, SI->getParent()); } + if (!DefaultIsReachable || GeneratingCoveredLookupTable) { + // We cached PHINodes in PHIs, to avoid accessing deleted PHINodes later, + // do not delete PHINodes here. + SI->getDefaultDest()->removePredecessor(SI->getParent(), + /*DontDeleteUselessPHIs=*/true); + } + bool ReturnedEarly = false; for (size_t I = 0, E = PHIs.size(); I != E; ++I) { PHINode *PHI = PHIs[I]; diff --git a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll index cdc0488991a..732e7cafe5e 100644 --- a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1273,3 +1273,32 @@ end: ; CHECK-LABEL: @pr20210 ; CHECK: switch i8 %x } + +; Make sure we do not crash due to trying to generate an unguarded +; lookup (since i3 can only hold values in the range of explicit +; values) and simultaneously trying to generate a branch to deal with +; the fact that we have holes in the range. +define i32 @covered_switch_with_bit_tests(i3) { +entry: + switch i3 %0, label %l6 [ + i3 -3, label %l5 + i3 -4, label %l5 + i3 3, label %l1 + i3 2, label %l1 + ] + +l1: br label %l2 + +l2: + %x = phi i32 [ 1, %l1 ], [ 2, %l5 ] + br label %l6 + +l5: br label %l2 + +l6: + %r = phi i32 [ %x, %l2 ], [ 0, %entry ] + ret i32 %r +; CHECK-LABEL: @covered_switch_with_bit_tests +; CHECK: entry +; CHECK-NEXT: switch +} -- 2.34.1