diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 83f98d022cac0861ab6339cca3951b339a613e5d..e5925545acaa217ecb05b41d64249dce8b7f1a59 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5309,9 +5309,9 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, for (SwitchInst::CaseIt E = SI->case_end(); CI != E; ++CI) { ConstantInt *CaseVal = CI->getCaseValue(); - if (CaseVal->getValue().slt(MinCaseVal->getValue())) + if (CaseVal->getValue().ult(MinCaseVal->getValue())) MinCaseVal = CaseVal; - if (CaseVal->getValue().sgt(MaxCaseVal->getValue())) + if (CaseVal->getValue().ugt(MaxCaseVal->getValue())) MaxCaseVal = CaseVal; // Resulting value at phi nodes for this case value. @@ -5337,8 +5337,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, } uint64_t NumResults = ResultLists[PHIs[0]].size(); - APInt RangeSpread = MaxCaseVal->getValue() - MinCaseVal->getValue(); - uint64_t TableSize = RangeSpread.getLimitedValue() + 1; + uint64_t TableSize = MaxCaseVal->getValue().getLimitedValue() + 1; bool TableHasHoles = (NumResults < TableSize); // If the table has holes, we need a constant result for the default case @@ -5373,12 +5372,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, // Compute the table index value. Builder.SetInsertPoint(SI); - Value *TableIndex; - if (MinCaseVal->isNullValue()) - TableIndex = SI->getCondition(); - else - TableIndex = - Builder.CreateSub(SI->getCondition(), MinCaseVal, "switch.tableidx"); + Value *TableIndex = SI->getCondition(); // Compute the maximum table size representable by the integer type we are // switching upon. @@ -5418,6 +5412,10 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, LookupBB = BasicBlock::Create(Mod.getContext(), "switch.lookup", CommonDest->getParent(), CommonDest); + // When doing the register-sized hole-check, unconditionally use a + // subtraction. + TableIndex = Builder.CreateSub(TableIndex, MinCaseVal); + // Make the mask's bitwidth at least 8-bit and a power-of-2 to avoid // unnecessary illegal types. uint64_t TableSizePowOf2 = NextPowerOf2(std::max(7ULL, TableSize - 1ULL)); @@ -5461,8 +5459,11 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, // If using a bitmask, use any value to fill the lookup table holes. Constant *DV = NeedMask ? ResultLists[PHI][0].second : DefaultResults[PHI]; StringRef FuncName = Fn->getName(); - SwitchLookupTable Table(Mod, TableSize, MinCaseVal, ResultList, DV, DL, - FuncName); + // Base is 0 unless using a hole check + ConstantInt *Base = + NeedMask ? MinCaseVal + : ConstantInt::get(Mod.getContext(), APInt(CaseSize, 0)); + SwitchLookupTable Table(Mod, TableSize, Base, ResultList, DV, DL, FuncName); Value *Result = Table.BuildLookup(TableIndex, Builder); @@ -5507,18 +5508,6 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, return true; } -static bool isSwitchDense(ArrayRef Values) { - // See also SelectionDAGBuilder::isDense(), which this function was based on. - uint64_t Diff = (uint64_t)Values.back() - (uint64_t)Values.front(); - uint64_t Range = Diff + 1; - uint64_t NumCases = Values.size(); - // 40% is the default density for building a jump table in optsize/minsize - // mode. - uint64_t MinDensity = 40; - - return NumCases * 100 >= Range * MinDensity; -} - /// Try to transform a switch that has "holes" in it to a contiguous sequence /// of cases. /// @@ -5530,32 +5519,47 @@ static bool isSwitchDense(ArrayRef Values) { static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder, const DataLayout &DL, const TargetTransformInfo &TTI) { + // The number of cases that need to be removed by a subtraction operation + // to make it worth using. + const unsigned SubThreshold = (SI->getFunction()->hasOptSize() ? 2 : 8); auto *CondTy = cast(SI->getCondition()->getType()); - if (CondTy->getIntegerBitWidth() > 64 || - !DL.fitsInLegalInteger(CondTy->getIntegerBitWidth())) + unsigned BitWidth = CondTy->getIntegerBitWidth(); + if (BitWidth > 64 || !DL.fitsInLegalInteger(BitWidth)) return false; // Only bother with this optimization if there are more than 3 switch cases; // SDAG will only bother creating jump tables for 4 or more cases. + // This is also useful when using the LowerSwitch transform, but not with + // so few cases. if (SI->getNumCases() < 4) return false; - // This transform is agnostic to the signedness of the input or case values. - // We can treat the case values as signed or unsigned. We can optimize more - // common cases such as a sequence crossing zero {-4,0,4,8} if we interpret - // case values as signed. - SmallVector Values; + // We organize the range to start from 0, if it is not already close. + SmallVector Values; for (auto &C : SI->cases()) - Values.push_back(C.getCaseValue()->getValue().getSExtValue()); + Values.push_back(C.getCaseValue()->getValue().getLimitedValue()); llvm::sort(Values); - // If the switch is already dense, there's nothing useful to do here. - if (isSwitchDense(Values)) - return false; - - // First, transform the values such that they start at zero and ascend. - int64_t Base = Values[0]; - for (auto &V : Values) - V -= (uint64_t)(Base); + bool MadeChanges = false; + // We must first look find the best start point, for example if we have a + // series that crosses zero: -2, -1, 0, 1, 2. + uint64_t BestDistance = + APInt::getMaxValue(CondTy->getIntegerBitWidth()).getLimitedValue() - + Values.back() + Values.front() + 1; + unsigned BestIndex = 0; + for (unsigned I = 1, E = Values.size(); I != E; I++) { + if (Values[I] - Values[I - 1] > BestDistance) { + BestIndex = I; + BestDistance = Values[I] - Values[I - 1]; + } + } + uint64_t Base = 0; + // Now transform the values such that they start at zero and ascend. + if (Values[BestIndex] >= SubThreshold) { + Base = Values[BestIndex]; + MadeChanges = true; + for (auto &V : Values) + V = (APInt(BitWidth, V) - Base).getLimitedValue(); + } // Now we have signed numbers that have been shifted so that, given enough // precision, there are no negative values. Since the rest of the transform @@ -5572,14 +5576,16 @@ static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder, // less than 64. unsigned Shift = 64; for (auto &V : Values) - Shift = std::min(Shift, countTrailingZeros((uint64_t)V); + Shift = std::min(Shift, countTrailingZeros(V)); assert(Shift < 64); - if (Shift > 0) + if (Shift > 0) { + MadeChanges = true; for (auto &V : Values) - V = (int64_t)((uint64_t)V >> Shift); + V >>= Shift; + } - if (!isSwitchDense(Values)) - // Transform didn't create a dense switch. + if (!MadeChanges) + // We didn't do anything. return false; // The obvious transform is to shift the switch condition right and emit a @@ -5594,18 +5600,22 @@ static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder, auto *Ty = cast(SI->getCondition()->getType()); Builder.SetInsertPoint(SI); - auto *ShiftC = ConstantInt::get(Ty, Shift); - auto *Sub = Builder.CreateSub(SI->getCondition(), ConstantInt::get(Ty, Base)); - auto *LShr = Builder.CreateLShr(Sub, ShiftC); - auto *Shl = Builder.CreateShl(Sub, Ty->getBitWidth() - Shift); - auto *Rot = Builder.CreateOr(LShr, Shl); - SI->replaceUsesOfWith(SI->getCondition(), Rot); + Value *Key = SI->getCondition(); + if (Base > 0) + Key = Builder.CreateSub(Key, ConstantInt::get(Ty, Base)); + if (Shift > 0) { + // FIXME replace with fshr? + auto *ShiftC = ConstantInt::get(Ty, Shift); + auto *LShr = Builder.CreateLShr(Key, ShiftC); + auto *Shl = Builder.CreateShl(Key, Ty->getBitWidth() - Shift); + Key = Builder.CreateOr(LShr, Shl); + } + SI->replaceUsesOfWith(SI->getCondition(), Key); for (auto Case : SI->cases()) { auto *Orig = Case.getCaseValue(); auto Sub = Orig->getValue() - APInt(Ty->getBitWidth(), Base); - Case.setValue( - cast(ConstantInt::get(Ty, Sub.lshr(ShiftC->getValue())))); + Case.setValue(cast(ConstantInt::get(Ty, Sub.lshr(Shift)))); } return true; } @@ -5646,6 +5656,9 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) { if (Options.ForwardSwitchCondToPhi && ForwardSwitchConditionToPHI(SI)) return requestResimplify(); + if (ReduceSwitchRange(SI, Builder, DL, TTI)) + return requestResimplify(); + // The conversion from switch to lookup tables results in difficult-to-analyze // code and makes pruning branches much harder. This is a problem if the // switch expression itself can still be restricted as a result of inlining or @@ -5655,9 +5668,6 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) { SwitchToLookupTable(SI, Builder, DL, TTI)) return requestResimplify(); - if (ReduceSwitchRange(SI, Builder, DL, TTI)) - return requestResimplify(); - return false; } diff --git a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll index adb0a9819dc6437ec9df138dab89a5d0309e8e91..735a97f305e20358ae380a21bbcd2fb406644ab2 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll @@ -2,6 +2,7 @@ ; RUN: opt < %s -simplifycfg -switch-to-lookup -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; RUN: opt < %s -passes='simplify-cfg' -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; In the presence of "-no-jump-tables"="true", simplifycfg should not convert switches to lookup tables. ; CHECK: @switch.table.bar = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1] @@ -11,11 +12,12 @@ define i32 @foo(i32 %c) "no-jump-tables"="true" { ; CHECK-LABEL: @foo( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 42 +; CHECK-NEXT: switch i32 [[TMP0]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[RETURN:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[RETURN]] @@ -50,11 +52,11 @@ return: define i32 @bar(i32 %c) { ; CHECK-LABEL: @bar( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 42 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.bar, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.bar, i32 0, i32 [[TMP0]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; CHECK: return: diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll index b7bf8054a6f108a6cb603f3e749be66cf86ddb32..08d266c7c9122fbec8accaf1e798e071e19a41cf 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll @@ -9,11 +9,16 @@ target triple = "x86_64-apple-darwin12.0.0" define i64 @test(i3 %arg) { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[ARG:%.*]], -4 -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], [8 x i64]* @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i3 [[ARG:%.*]], -1 +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[DEFAULT:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[ARG]] to i4 +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i64], [7 x i64]* @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, i64* [[SWITCH_GEP]] -; CHECK-NEXT: [[V3:%.*]] = add i64 [[SWITCH_LOAD]], 0 +; CHECK-NEXT: br label [[DEFAULT]] +; CHECK: Default: +; CHECK-NEXT: [[V1:%.*]] = phi i64 [ 8, [[ENTRY:%.*]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ] +; CHECK-NEXT: [[V3:%.*]] = add i64 [[V1]], 0 ; CHECK-NEXT: ret i64 [[V3]] ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll index e50a913f9e50afb3d61cdc566a8cfaa1cc74f4bd..5d2297f58d4048ffadc9499ecbd436735f9b4970 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll @@ -9,11 +9,8 @@ target triple = "x86_64-apple-darwin12.0.0" define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) { ; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2 -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], [4 x i64]* @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]] -; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, i64* [[SWITCH_GEP]] -; CHECK-NEXT: ret i64 [[SWITCH_LOAD]] +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i2 [[TMP0:%.*]] to i64 +; CHECK-NEXT: ret i64 [[SWITCH_IDX_CAST]] ; entry: switch i2 %0, label %1 [ 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 c77438974b2d2921683b464bcaf6e681f300f91e..f1c550cf94f20aa746b77829cb4ba6b9c417f6c9 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -36,11 +36,11 @@ target triple = "x86_64-unknown-linux-gnu" define i32 @f(i32 %c) { ; CHECK-LABEL: @f( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 42 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 7 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 [[TMP0]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; CHECK: return: @@ -75,11 +75,11 @@ return: define i8 @char(i32 %c) { ; CHECK-LABEL: @char( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 9 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 42 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 9 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i8], [9 x i8]* @switch.table.char, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i8], [9 x i8]* @switch.table.char, i32 0, i32 [[TMP0]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8, i8* [[SWITCH_GEP]] ; CHECK-NEXT: ret i8 [[SWITCH_LOAD]] ; CHECK: return: @@ -245,18 +245,18 @@ define i32 @crud(i8 zeroext %c) { ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C:%.*]], 33 ; CHECK-NEXT: br i1 [[CMP]], label [[LOR_END:%.*]], label [[SWITCH_EARLY_TEST:%.*]] ; CHECK: switch.early.test: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C]], 34 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 59 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[C]], 34 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[TMP0]], 59 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i59 +; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[TMP0]] to i59 ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i59 [[SWITCH_CAST]], 1 ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i59 -288230375765830623, [[SWITCH_SHIFTAMT]] ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i59 [[SWITCH_DOWNSHIFT]] to i1 ; CHECK-NEXT: br label [[LOR_END]] ; CHECK: lor.end: -; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ false, [[SWITCH_EARLY_TEST]] ] -; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP1]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ false, [[SWITCH_EARLY_TEST]] ] +; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[LOR_EXT]] ; entry: @@ -300,11 +300,12 @@ lor.end: define i32 @overflow(i32 %type) { ; CHECK-LABEL: @overflow( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[TYPE:%.*]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 -2147483645, label [[SW_BB3]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[TYPE:%.*]], -2147483645 +; CHECK-NEXT: switch i32 [[TMP0]], label [[IF_END:%.*]] [ +; CHECK-NEXT: i32 -2147483648, label [[SW_BB3:%.*]] +; CHECK-NEXT: i32 0, label [[SW_BB3]] +; CHECK-NEXT: i32 2147483646, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 2147483647, label [[SW_BB2:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[IF_END]] @@ -378,11 +379,10 @@ define i32 @large(i32 %x) { ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X]], -10 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[MUL]], i32 [[X]] -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[SPEC_SELECT]], 1 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 199 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SPEC_SELECT]], 200 ; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [199 x i32], [199 x i32]* @switch.table.large, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [200 x i32], [200 x i32]* @switch.table.large, i32 0, i32 [[SPEC_SELECT]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; CHECK: return: @@ -808,11 +808,10 @@ return: define i32 @cprop(i32 %x, i32 %y) { ; CHECK-LABEL: @cprop( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[X:%.*]], 1 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 8 ; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.cprop, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], [8 x i32]* @switch.table.cprop, i32 0, i32 [[X]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; CHECK: return: @@ -923,12 +922,13 @@ return: define i96 @illegaltype(i32 %c) { ; CHECK-LABEL: @illegaltype( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 42 +; CHECK-NEXT: switch i32 [[TMP0]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[RETURN:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] +; CHECK-NEXT: i32 4, label [[SW_BB4:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[RETURN]] @@ -1008,12 +1008,13 @@ define i32 @nodefaultwithholes(i32 %c) { ; CHECK-NEXT: call void @exit(i32 1) ; CHECK-NEXT: unreachable ; CHECK: switch.hole_check: -; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = trunc i32 [[C]] to i8 +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[C]], 0 +; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = trunc i32 [[TMP1]] to i8 ; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 47, [[SWITCH_MASKINDEX]] ; CHECK-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1 ; CHECK-NEXT: br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[SW_DEFAULT]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @switch.table.nodefaultwithholes, i32 0, i32 [[C]] +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @switch.table.nodefaultwithholes, i32 0, i32 [[TMP1]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] ; @@ -1212,11 +1213,11 @@ return: define i8 @linearmap1(i32 %c) { ; CHECK-LABEL: @linearmap1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 10 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 10 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[TMP0]] to i8 ; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], -5 ; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], 18 ; CHECK-NEXT: ret i8 [[SWITCH_OFFSET]] @@ -1243,11 +1244,11 @@ return: define i32 @linearmap2(i8 %c) { ; CHECK-LABEL: @linearmap2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C:%.*]], -13 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[C:%.*]], -13 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i32 +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = zext i8 [[TMP0]] to i32 ; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i32 [[SWITCH_IDX_CAST]], 18 ; CHECK-NEXT: ret i32 [[SWITCH_OFFSET]] ; CHECK: return: @@ -1273,11 +1274,11 @@ return: define i8 @linearmap3(i32 %c) { ; CHECK-LABEL: @linearmap3( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 10 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], 10 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[TMP0]] to i8 ; CHECK-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 100 ; CHECK-NEXT: ret i8 [[SWITCH_IDX_MULT]] ; CHECK: return: @@ -1303,11 +1304,11 @@ return: define i8 @linearmap4(i32 %c) { ; CHECK-LABEL: @linearmap4( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], -2 -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[C:%.*]], -2 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8 +; CHECK-NEXT: [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[TMP0]] to i8 ; CHECK-NEXT: ret i8 [[SWITCH_IDX_CAST]] ; CHECK: return: ; CHECK-NEXT: ret i8 3 @@ -1546,18 +1547,21 @@ end: define i32 @covered_switch_with_bit_tests(i3) { ; CHECK-LABEL: @covered_switch_with_bit_tests( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[TMP0:%.*]], -4 -; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i8 -; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 -61, [[SWITCH_MASKINDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i3 [[TMP0:%.*]], -2 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_HOLE_CHECK:%.*]], label [[L6:%.*]] +; CHECK: switch.hole_check: +; CHECK-NEXT: [[TMP2:%.*]] = sub i3 [[TMP0]], 2 +; CHECK-NEXT: [[SWITCH_MASKINDEX:%.*]] = zext i3 [[TMP2]] to i8 +; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 15, [[SWITCH_MASKINDEX]] ; CHECK-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1 -; CHECK-NEXT: br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[L6:%.*]] +; CHECK-NEXT: br i1 [[SWITCH_LOBIT]], label [[SWITCH_LOOKUP:%.*]], label [[L6]] ; CHECK: switch.lookup: -; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4 -; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], [8 x i32]* @switch.table.covered_switch_with_bit_tests, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] +; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[TMP2]] to i4 +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @switch.table.covered_switch_with_bit_tests, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]] ; CHECK-NEXT: br label [[L6]] ; CHECK: l6: -; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ] +; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 0, [[SWITCH_HOLE_CHECK]] ], [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ] ; CHECK-NEXT: ret i32 [[R]] ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll index 849f55f6f392bb9521d6ce74f9fef19f69ca68e8..e9be26e94e4e1643cdaecd6132ba7a72dae7dd27 100644 --- a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll +++ b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll @@ -119,11 +119,12 @@ three: ; Optimization shouldn't trigger; not an arithmetic progression define i32 @test4(i32 %a) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[DEF:%.*]] [ -; CHECK-NEXT: i32 97, label [[ONE:%.*]] -; CHECK-NEXT: i32 102, label [[TWO:%.*]] -; CHECK-NEXT: i32 105, label [[THREE:%.*]] -; CHECK-NEXT: i32 109, label [[THREE]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 97 +; CHECK-NEXT: switch i32 [[TMP1]], label [[DEF:%.*]] [ +; CHECK-NEXT: i32 0, label [[ONE:%.*]] +; CHECK-NEXT: i32 5, label [[TWO:%.*]] +; CHECK-NEXT: i32 8, label [[THREE:%.*]] +; CHECK-NEXT: i32 12, label [[THREE]] ; CHECK-NEXT: ] ; CHECK: def: ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] @@ -156,11 +157,12 @@ three: ; Optimization shouldn't trigger; not a power of two define i32 @test5(i32 %a) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[DEF:%.*]] [ -; CHECK-NEXT: i32 97, label [[ONE:%.*]] -; CHECK-NEXT: i32 102, label [[TWO:%.*]] -; CHECK-NEXT: i32 107, label [[THREE:%.*]] -; CHECK-NEXT: i32 112, label [[THREE]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 97 +; CHECK-NEXT: switch i32 [[TMP1]], label [[DEF:%.*]] [ +; CHECK-NEXT: i32 0, label [[ONE:%.*]] +; CHECK-NEXT: i32 5, label [[TWO:%.*]] +; CHECK-NEXT: i32 10, label [[THREE:%.*]] +; CHECK-NEXT: i32 15, label [[THREE]] ; CHECK-NEXT: ] ; CHECK: def: ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] @@ -307,15 +309,14 @@ three: define i32 @test9(i32 %a) { ; CHECK-LABEL: @test9( -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 6 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 1 -; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 31 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[DEF:%.*]] [ -; CHECK-NEXT: i32 6, label [[ONE:%.*]] -; CHECK-NEXT: i32 7, label [[TWO:%.*]] -; CHECK-NEXT: i32 0, label [[THREE:%.*]] -; CHECK-NEXT: i32 2, label [[THREE]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[A:%.*]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = shl i32 [[A]], 31 +; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP1]], [[TMP2]] +; CHECK-NEXT: switch i32 [[TMP3]], label [[DEF:%.*]] [ +; CHECK-NEXT: i32 9, label [[ONE:%.*]] +; CHECK-NEXT: i32 10, label [[TWO:%.*]] +; CHECK-NEXT: i32 3, label [[THREE:%.*]] +; CHECK-NEXT: i32 5, label [[THREE]] ; CHECK-NEXT: ] ; CHECK: def: ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] diff --git a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll index 9a4b4fe2632660251c1973831e42c7ed6703654f..6b74eb2221f483f8b7730ee67039acdfd53520bf 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll @@ -5,12 +5,14 @@ declare void @foo(i32) define void @test(i1 %a) { ; CHECK-LABEL: @test( -; CHECK-NEXT: br i1 [[A:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK-NEXT: [[A_OFF:%.*]] = add i1 [[A:%.*]], true +; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i1 [[A_OFF]], true +; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: false: -; CHECK-NEXT: tail call void @foo(i32 3) +; CHECK-NEXT: call void @foo(i32 3) ; CHECK-NEXT: ret void ; switch i1 %a, label %default [i1 1, label %true @@ -35,16 +37,16 @@ define void @test2(i2 %a) { ; CHECK-NEXT: i2 -1, label [[CASE3:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: -; CHECK-NEXT: tail call void @foo(i32 0) +; CHECK-NEXT: call void @foo(i32 0) ; CHECK-NEXT: ret void ; CHECK: case1: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: case2: -; CHECK-NEXT: tail call void @foo(i32 2) +; CHECK-NEXT: call void @foo(i32 2) ; CHECK-NEXT: ret void ; CHECK: case3: -; CHECK-NEXT: tail call void @foo(i32 3) +; CHECK-NEXT: call void @foo(i32 3) ; CHECK-NEXT: ret void ; CHECK: default1: ; CHECK-NEXT: unreachable @@ -80,16 +82,16 @@ define void @test3(i2 %a) { ; CHECK-NEXT: i2 -2, label [[CASE2:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: -; CHECK-NEXT: tail call void @foo(i32 0) +; CHECK-NEXT: call void @foo(i32 0) ; CHECK-NEXT: ret void ; CHECK: case1: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: case2: -; CHECK-NEXT: tail call void @foo(i32 2) +; CHECK-NEXT: call void @foo(i32 2) ; CHECK-NEXT: ret void ; CHECK: default: -; CHECK-NEXT: tail call void @foo(i32 0) +; CHECK-NEXT: call void @foo(i32 0) ; CHECK-NEXT: ret void ; switch i2 %a, label %default [i2 0, label %case0 @@ -119,13 +121,13 @@ define void @test4(i128 %a) { ; CHECK-NEXT: i128 1, label [[CASE1:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: -; CHECK-NEXT: tail call void @foo(i32 0) +; CHECK-NEXT: call void @foo(i32 0) ; CHECK-NEXT: ret void ; CHECK: case1: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: default: -; CHECK-NEXT: tail call void @foo(i32 0) +; CHECK-NEXT: call void @foo(i32 0) ; CHECK-NEXT: ret void ; switch i128 %a, label %default [i128 0, label %case0 @@ -146,14 +148,15 @@ default: define void @test5(i8 %a) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A:%.*]], 2 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i8 [[A]], 1 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], -1 +; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: false: -; CHECK-NEXT: tail call void @foo(i32 3) +; CHECK-NEXT: call void @foo(i32 3) ; CHECK-NEXT: ret void ; %cmp = icmp ult i8 %a, 2 @@ -174,15 +177,17 @@ default: ;; All but one bit known one define void @test6(i8 %a) { ; CHECK-LABEL: @test6( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A:%.*]], -3 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i8 [[A]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 +; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: false: -; CHECK-NEXT: tail call void @foo(i32 3) +; CHECK-NEXT: call void @foo(i32 3) ; CHECK-NEXT: ret void ; %and = and i8 %a, 254 @@ -205,15 +210,17 @@ default: ; within a single run of simplify-cfg define void @test7(i8 %a) { ; CHECK-LABEL: @test7( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A:%.*]], -3 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i8 [[A]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 +; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: tail call void @foo(i32 1) +; CHECK-NEXT: call void @foo(i32 1) ; CHECK-NEXT: ret void ; CHECK: false: -; CHECK-NEXT: tail call void @foo(i32 3) +; CHECK-NEXT: call void @foo(i32 3) ; CHECK-NEXT: ret void ; %and = and i8 %a, 254 @@ -243,7 +250,22 @@ default: ;; but it doesn't hurt to confirm. define void @test8(i8 %a) { ; CHECK-LABEL: @test8( -; CHECK-NEXT: unreachable +; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], undef +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: switch i8 [[A]], label [[DEFAULT:%.*]] [ +; CHECK-NEXT: i8 -1, label [[TRUE:%.*]] +; CHECK-NEXT: i8 -2, label [[FALSE:%.*]] +; CHECK-NEXT: ] +; CHECK: true: +; CHECK-NEXT: call void @foo(i32 1) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: ret void +; CHECK: default: +; CHECK-NEXT: call void @foo(i32 2) +; CHECK-NEXT: ret void ; %and = and i8 %a, 254 %cmp = icmp eq i8 %and, undef