Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -3674,6 +3674,428 @@ return SI->getNumCases() * 10 >= TableSize * 4; } +// InitializeUniqueCases - Helper function that initializes a map containing +// results for the PHI node of the common destination block for a switch +// instruction. Returns false if multiple PHI nodes have been found or if +// there is not a common destination block for the switch. +static bool InitializeUniqueCases( + SwitchInst *SI, const DataLayout *DL, PHINode *&PHI, + BasicBlock *&CommonDest, + SmallDenseMap> &UniqueResults, + Constant *&DefaultResult) { + for (auto I = SI->case_begin(), E = SI->case_end(); I != E; ++I) { + ConstantInt *CaseVal = I.getCaseValue(); + BasicBlock *CaseSuccessor = I.getCaseSuccessor(); + + // Resulting value at phi nodes for this case value. + typedef SmallVector, 4> ResultsTy; + ResultsTy Results; + if (!GetCaseResults(SI, CaseVal, I.getCaseSuccessor(), &CommonDest, Results, + DL)) + return false; + + BranchInst *BI = dyn_cast(CaseSuccessor->getTerminator()); + // Support only the case where the switch branches directly or through an + // intermediate unconditional block to the common destination. + if (CaseSuccessor != CommonDest && + !(BI && BI->isUnconditional() && BI->getSuccessor(0) == CommonDest)) + return false; + // Only one value per case is permitted + if (Results.size() > 1) + return false; + auto &Result = *Results.begin(); + auto ResultFound = UniqueResults.find(Result.second); + if (ResultFound == UniqueResults.end()) { + UniqueResults[Result.second].push_back(CaseVal); + } else { + // Avoid querying the map again if we already found the result. + ResultFound->second.push_back(CaseVal); + } + + // Append the result from this case to the list and find the PHI + if (PHI == nullptr) + PHI = Result.first; + else if (PHI != Result.first) + return false; + } + // Find the default result value + SmallVector, 1> DefaultResults; + BasicBlock *DefaultDest = SI->getDefaultDest(); + GetCaseResults(SI, nullptr, SI->getDefaultDest(), &CommonDest, DefaultResults, + DL); + // No default case makes us assume that default is not possible. + DefaultResult = + DefaultResults.size() == 1 ? DefaultResults.begin()->second : nullptr; + BranchInst *BI = dyn_cast(DefaultDest->getTerminator()); + if (DefaultDest != CommonDest && + !(BI && BI->isUnconditional() && BI->getSuccessor(0) == CommonDest)) + return false; + + return true; +} + +// AnalyzeSwitchCases - Helper function to compute information about switch +// cases, like known ones and zeroes, the minimum and the maximum case and +// the number of case patterns that match the bitmask of the switch value. +static void AnalyzeSwitchCases(const SmallVectorImpl *Cases, + const APInt &KnownZeroesCond, + const APInt &KnownOnesCond, APInt &KnownZeroes, + APInt &KnownOnes, ConstantInt *&MinCase, + ConstantInt *&MaxCase, unsigned &PossibleHits) { + if (Cases == nullptr) + return; + // Compute the number of patterns covered by the cases of each result, + // the minimum and maximum cases and the zeroes and ones for this case group. + for (auto &Case : *Cases) { + bool CaseMatchesCondPattern = + ((~Case->getValue() & KnownZeroesCond) == KnownZeroesCond) && + ((Case->getValue() & KnownOnesCond) == KnownOnesCond); + + if (CaseMatchesCondPattern) + ++PossibleHits; + + KnownZeroes &= ~(Case->getValue()); + KnownOnes &= Case->getValue(); + if (MinCase->getValue().sgt(Case->getValue())) + MinCase = Case; + if (MaxCase->getValue().slt(Case->getValue())) + MaxCase = Case; + } +} + +// ConvertTwoCaseSwitch - Helper function that checks if it is possible to +// transform a switch with only two cases (or two cases + default) +// that produces a result into a value select. +// Example: +// switch (a) { +// case 10: %0 = icmp eq i32 %a, 1 +// return 10; %1 = select i1 %0, i32 10, i32 4 +// case 20: ----> %2 = icmp eq i32 %a, 20 +// return 2; %3 = select i1 %2, i32 2, i32 %1 +// default: +// return 4; +// } +static Value * +ConvertTwoCaseSwitch(const SmallVectorImpl *FirstGroupCasesPtr, + const SmallVectorImpl *SecondGroupCasesPtr, + Constant *FirstGroupResult, Constant *SecondGroupResult, + Constant *DefaultResult, Value *Condition, + const APInt &KnownZeroCond, const APInt &KnownOneCond, + unsigned Bits, IRBuilder<> &Builder) { + if (FirstGroupCasesPtr == nullptr || SecondGroupCasesPtr == nullptr) + return nullptr; + auto &FirstGroupCases = *FirstGroupCasesPtr; + auto &SecondGroupCases = *SecondGroupCasesPtr; + const unsigned CondStuckBits = + (KnownZeroCond | KnownOneCond).countPopulation(); + // If we are selecting between only two cases transform into a simple + // select or a two-way select if default is possible. + if (FirstGroupCases.size() == 1 && SecondGroupCases.size() == 1) { + ConstantInt *const FirstCase = FirstGroupCases[0]; + ConstantInt *const SecondCase = SecondGroupCases[0]; + // In this case we have only one case per result. From the analysis of + // the condition value done above we can determine if the condition value + // can assume the value of the case or if the case is dead. + const unsigned FirstCanHit = + ((~FirstCase->getValue() & KnownZeroCond) == KnownZeroCond) && + ((FirstCase->getValue() & KnownOneCond) == KnownOneCond); + const unsigned SecondCanHit = + ((~SecondCase->getValue() & KnownZeroCond) == KnownZeroCond) && + ((SecondCase->getValue() & KnownOneCond) == KnownOneCond); + + // The default case can trigger if a default value has been found and + // if there are some possible bit combination of the condition value + // that are not covered from the case labels + bool DefaultCanTrigger = + ((1 << (Bits - CondStuckBits)) - (FirstCanHit + SecondCanHit) != 0); + DefaultCanTrigger &= (DefaultResult != nullptr); + Value *SelectValue = SecondGroupResult; + if (DefaultCanTrigger) { + Value *const ValueCompare = + Builder.CreateICmpEQ(Condition, SecondCase, "switch.selectcmp"); + SelectValue = Builder.CreateSelect(ValueCompare, SecondGroupResult, + DefaultResult, "switch.select"); + } + Value *const ValueCompare = + Builder.CreateICmpEQ(Condition, FirstCase, "switch.selectcmp"); + return Builder.CreateSelect(ValueCompare, FirstGroupResult, SelectValue, + "switch.select"); + } + + return nullptr; +} + +// ConvertRangeSwitch - Helper function that checks if it is possible to +// transform a switch with cases arranged into two ordered not overlapping +// groups into a value select. +// +// Example: +// switch (a) { +// case 0: case 2: +// case 4: case 6: +// case 8: case 10: +// case 12: case 14: +// return 10; ----> %0 = icmp ult i32 %a, 15 +// %1 = select i1 %0, i32 10, i32 20 +// case 16: case 18: +// case 20: case 22: +// case 24: case 26: +// case 28: case 30: +// return 20; +// } +static Value * +ConvertRangeSwitch(Constant *FirstGroupResult, Constant *SecondGroupResult, + Value *Condition, Constant *DefaultResult, unsigned NumCases, + bool DefaultCanTrigger, ConstantInt *MinCaseFirst, + ConstantInt *MinCaseSecond, ConstantInt *MaxCaseFirst, + ConstantInt *MaxCaseSecond, IRBuilder<> &Builder) { + if (FirstGroupResult == nullptr) + return nullptr; + + const bool RangeIsContinuous = + (MaxCaseFirst->getValue() - MinCaseFirst->getValue()) + 1 == NumCases; + if (RangeIsContinuous && SecondGroupResult == nullptr && + DefaultResult != nullptr) { + Constant *Offset = ConstantExpr::getNeg(MinCaseFirst); + Constant *NCases = ConstantInt::get(Offset->getType(), NumCases); + + Value *Sub = Condition; + if (!Offset->isNullValue()) + Sub = Builder.CreateAdd(Sub, Offset, "switch.off"); + Value *ValueCompare; + // If NumCases overflowed, then all possible values jump to the successor. + if (NCases->isNullValue() && NumCases != 0) + ValueCompare = ConstantInt::getTrue(FirstGroupResult->getContext()); + else + ValueCompare = Builder.CreateICmpULT(Sub, NCases, "switch.cmp"); + return Builder.CreateSelect(ValueCompare, FirstGroupResult, DefaultResult, + "switch.rangeselect"); + } + + if (SecondGroupResult == nullptr) + return nullptr; + const bool FirstIsBigger = + MaxCaseSecond->getValue().slt(MinCaseFirst->getValue()); + const bool SecondIsBigger = + MaxCaseFirst->getValue().slt(MinCaseSecond->getValue()); + // If the case statements ranges do not overlap use a comparison to + // distinguish between the two groups. + if (!DefaultCanTrigger && (FirstIsBigger || SecondIsBigger)) { + ConstantInt *Pivot = SecondIsBigger ? MaxCaseFirst : MaxCaseSecond; + Value *const SelectLHS = + SecondIsBigger ? FirstGroupResult : SecondGroupResult; + Value *const SelectRHS = + SecondIsBigger ? SecondGroupResult : FirstGroupResult; + Value *const ValueCompare = + Builder.CreateICmpSLE(Condition, Pivot, "switch.rangesub"); + return Builder.CreateSelect(ValueCompare, SelectLHS, SelectRHS, + "switch.rangeselect"); + } + + return nullptr; +} + +// ConvertBitPatternSwitch - Helper function that checks if it is possible to +// transform a switch with cases that are groupable by some bit pattern into +// a value select. +// +// Example: +// a &= 0x6; +// switch (a) { +// case 0: +// return 1; +// case 2: +// return 2; +// case 4: ----> %0 = and i32 %a, 6 +// return 1; %1 = and i32 %0, 2 +// case 6: %2 = icmp eq i32 %1, 0 +// return 2; %3 = select i1 %3, i32 1, i32 2 +// default: +// return 10; +// } +static Value *ConvertBitPatternSwitch( + Constant *FirstGroupResult, Constant *SecondGroupResult, Value *Condition, + bool DefaultCanTrigger, const APInt &KnownZeroFirst, APInt KnownOneFirst, + const APInt &KnownZeroSecond, APInt KnownOneSecond, IRBuilder<> &Builder) { + + if (FirstGroupResult == nullptr || SecondGroupResult == nullptr) + return nullptr; + // If there is no default case and we have unambiguous + // patterns do it with one select and one compare. + if (!DefaultCanTrigger && ((KnownOneFirst & KnownZeroSecond) != 0 || + (KnownOneSecond & KnownZeroFirst) != 0)) { + Value *ValueCompare = nullptr; + // KnownOneFirst and KnownOneSecond after this assignment + // are bitvectors containing the bits that are always one + // in a group of case labels and always zero in the other + KnownOneFirst &= KnownZeroSecond; + KnownOneSecond &= KnownZeroFirst; + // The comparison checks for ones that are always present in + // one of the groups that are always zero in the other. + if (KnownOneFirst != 0) { + ConstantInt *const MaskValue = + ConstantInt::get(Condition->getContext(), KnownOneFirst); + ValueCompare = + Builder.CreateAnd(Condition, MaskValue, "switch.selectmask"); + ValueCompare = Builder.CreateICmpNE( + ValueCompare, ConstantInt::get(Condition->getType(), 0), + "switch.selectcmp"); + } else if (KnownOneSecond != 0) { + ConstantInt *const MaskValue = + ConstantInt::get(Condition->getContext(), KnownOneSecond); + ValueCompare = + Builder.CreateAnd(Condition, MaskValue, "switch.selectmask"); + ValueCompare = Builder.CreateICmpEQ( + ValueCompare, ConstantInt::get(Condition->getType(), 0), + "switch.selectcmp"); + } + return Builder.CreateSelect(ValueCompare, FirstGroupResult, + SecondGroupResult, "switch.select"); + } + + return nullptr; +} + +// RemoveSwitchAfterSelectConversion - Helper function to cleanup a switch +// instruction that has been converted into a select, fixing up PHI nodes and +// basic blocks. +static void RemoveSwitchAfterSelectConversion(SwitchInst *SI, PHINode *PHI, + Value *SelectValue, + BasicBlock *Destination, + IRBuilder<> &Builder) { + PHI->addIncoming(SelectValue, SI->getParent()); + + Builder.CreateBr(Destination); + + // Remove the switch. + for (unsigned i = 0, e = SI->getNumSuccessors(); i < e; ++i) { + BasicBlock *Succ = SI->getSuccessor(i); + + if (Succ == SI->getDefaultDest()) + continue; + Succ->removePredecessor(SI->getParent()); + } + SI->eraseFromParent(); +} + +/// SwitchToSelect - If the switch is only used to initialize one or more +/// phi nodes in a common successor block with only two different +/// constant values, replace the switch with select. +static bool SwitchToSelect(SwitchInst *SI, IRBuilder<> &Builder, + const DataLayout *DL) { + Value *const Cond = SI->getCondition(); + PHINode *PHI = nullptr; + BasicBlock *CommonDest = nullptr; + Type *ResultType; + Constant *DefaultResult; + + SmallDenseMap> UniqueResults; + // Collect all the cases that will deliver the same value from the switch. + if (!InitializeUniqueCases(SI, DL, PHI, CommonDest, UniqueResults, + DefaultResult)) + return false; + const unsigned NumOfResults = UniqueResults.size(); + // Selects choose between maximum two values. + if (NumOfResults > 2) + return false; + assert(PHI != nullptr && "PHI for value select not found"); + ResultType = PHI->getType(); + + const unsigned Bits = Cond->getType()->getIntegerBitWidth(); + + const SmallVectorImpl *FirstGroupCases = nullptr; + const SmallVectorImpl *SecondGroupCases = nullptr; + Constant *FirstGroupResult = nullptr; + Constant *SecondGroupResult = nullptr; + { + auto ResultIt = UniqueResults.begin(); + if (NumOfResults >= 1) { + FirstGroupCases = &ResultIt->second; + FirstGroupResult = ResultIt->first; + } + if (NumOfResults == 2) { + ++ResultIt; + SecondGroupCases = &ResultIt->second; + SecondGroupResult = ResultIt->first; + } + } + // SmallDenseMap is unordered. Enforce a stable ordering here. + if (SecondGroupCases != nullptr && + (isa(SecondGroupResult) || + (!isa(FirstGroupResult) && + FirstGroupResult->getUniqueInteger().sgt( + SecondGroupResult->getUniqueInteger())))) { + std::swap(FirstGroupCases, SecondGroupCases); + std::swap(FirstGroupResult, SecondGroupResult); + } + + APInt KnownZeroCond(Bits, 0), KnownOneCond(Bits, 0); + computeKnownBits(Cond, KnownZeroCond, KnownOneCond); + // Number of bits that are fixed in the switch condition value. + const unsigned CondStuckBits = + (KnownZeroCond | KnownOneCond).countPopulation(); + Value *SelectValue = nullptr; + + Builder.SetInsertPoint(SI); + SelectValue = ConvertTwoCaseSwitch( + FirstGroupCases, SecondGroupCases, FirstGroupResult, SecondGroupResult, + DefaultResult, Cond, KnownZeroCond, KnownOneCond, Bits, Builder); + if (SelectValue != nullptr) { + RemoveSwitchAfterSelectConversion(SI, PHI, SelectValue, CommonDest, + Builder); + return true; + } + + // The switch has more than only two cases. Check to see if we can + // still transform it into a select + bool DefaultCanTrigger; + APInt KnownZeroFirst(Bits, ~(0ULL)), KnownOneFirst(Bits, ~(0ULL)), + KnownZeroSecond(Bits, ~(0ULL)), KnownOneSecond(Bits, ~(0ULL)); + unsigned FirstPossibleHits = 0, SecondPossibleHits = 0; + ConstantInt *MinCaseFirst = FirstGroupCases ? (*FirstGroupCases)[0] : nullptr, + *MinCaseSecond = + SecondGroupCases ? (*SecondGroupCases)[0] : nullptr, + *MaxCaseFirst = MinCaseFirst, *MaxCaseSecond = MinCaseSecond; + AnalyzeSwitchCases(FirstGroupCases, KnownZeroCond, KnownOneCond, + KnownZeroFirst, KnownOneFirst, MinCaseFirst, MaxCaseFirst, + FirstPossibleHits); + AnalyzeSwitchCases(SecondGroupCases, KnownZeroCond, KnownOneCond, + KnownZeroSecond, KnownOneSecond, MinCaseSecond, + MaxCaseSecond, SecondPossibleHits); + // The default case can trigger if a default value has been found and + // if there are some possible bit combination of the condition value + // that are not covered from the case labels + DefaultCanTrigger = (((1 << (Bits - CondStuckBits)) - + (FirstPossibleHits + SecondPossibleHits)) != 0); + DefaultCanTrigger &= DefaultResult != nullptr; + + SelectValue = ConvertRangeSwitch( + FirstGroupResult, SecondGroupResult, Cond, DefaultResult, + SI->getNumCases(), DefaultCanTrigger, MinCaseFirst, MinCaseSecond, + MaxCaseFirst, MaxCaseSecond, Builder); + + if (SelectValue != nullptr) { + RemoveSwitchAfterSelectConversion(SI, PHI, SelectValue, CommonDest, + Builder); + return true; + } + + // If we couldn't split the switch results into two ranges of values + // try finding a bit pattern that covers the cases and test on that + SelectValue = ConvertBitPatternSwitch( + FirstGroupResult, SecondGroupResult, Cond, DefaultCanTrigger, + KnownZeroFirst, KnownOneFirst, KnownZeroSecond, KnownOneSecond, Builder); + + if (SelectValue != nullptr) { + RemoveSwitchAfterSelectConversion(SI, PHI, SelectValue, CommonDest, + Builder); + return true; + } + + // The switch couldn't be converted into a select. + return false; +} + /// SwitchToLookupTable - If the switch is only used to initialize one or more /// phi nodes in a common successor block with different constant values, /// replace the switch with lookup tables. @@ -3916,10 +4338,6 @@ return SimplifyCFG(BB, TTI, DL) | true; } - // Try to transform the switch into an icmp and a branch. - if (TurnSwitchRangeIntoICmp(SI, Builder)) - return SimplifyCFG(BB, TTI, DL) | true; - // Remove unreachable cases. if (EliminateDeadSwitchCases(SI)) return SimplifyCFG(BB, TTI, DL) | true; @@ -3927,6 +4345,13 @@ if (ForwardSwitchConditionToPHI(SI)) return SimplifyCFG(BB, TTI, DL) | true; + if (SwitchToSelect(SI, Builder, DL)) + return SimplifyCFG(BB, TTI, DL) | true; + + // Try to transform the switch into an icmp and a branch. + if (TurnSwitchRangeIntoICmp(SI, Builder)) + return SimplifyCFG(BB, TTI, DL) | true; + if (SwitchToLookupTable(SI, Builder, TTI, DL)) return SimplifyCFG(BB, TTI, DL) | true; Index: test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectBitPattern.ll =================================================================== --- /dev/null +++ test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectBitPattern.ll @@ -0,0 +1,95 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; int foo3_with_def(int a) { +; switch (a) { +; case 0: +; return 1; +; case 1: +; return 2; +; case 2: +; return 1; +; case 3: +; return 2; +; default: +; return 10; +; } +; } +; +; int foo3_without_def(int a) { +; a &= 0x6; +; switch (a) { +; case 0: +; return 1; +; case 2: +; return 2; +; case 4: +; return 1; +; case 6: +; return 2; +; default: +; return 10; +; } +; } + +define i32 @foo3_with_def(i32 %a) #0 { +; CHECK-LABEL: @foo3_with_def +; CHECK: switch i32 +entry: + switch i32 %a, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.bb2: + br label %return + +sw.bb3: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 10, %sw.default ], [ 2, %sw.bb3 ], [ 1, %sw.bb2 ], [ 2, %sw.bb1 ], [ 1, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @foo3_without_def(i32 %a) #0 { +; CHECK-LABEL: @foo3_without_def +; CHECK: select +entry: + %and = and i32 %a, 6 + switch i32 %and, label %sw.default [ + i32 0, label %sw.bb + i32 2, label %sw.bb1 + i32 4, label %sw.bb2 + i32 6, label %sw.bb3 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.bb2: + br label %return + +sw.bb3: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 10, %sw.default ], [ 2, %sw.bb3 ], [ 1, %sw.bb2 ], [ 2, %sw.bb1 ], [ 1, %sw.bb ] + ret i32 %retval.0 +} Index: test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectRange.ll =================================================================== --- /dev/null +++ test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectRange.ll @@ -0,0 +1,71 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +define i32 @foo2_with_def(i32 %a) #0 { +; CHECK-LABEL: @foo2_with_def +; CHECK-NOT: select +entry: + switch i32 %a, label %sw.default [ + i32 10, label %sw.bb + i32 11, label %sw.bb + i32 12, label %sw.bb + i32 13, label %sw.bb + i32 14, label %sw.bb + i32 15, label %sw.bb + i32 19, label %sw.bb1 + i32 20, label %sw.bb1 + i32 21, label %sw.bb1 + i32 22, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 30, %sw.default ], [ 20, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @foo2_without_def(i32 %a) #0 { +; CHECK-LABEL: @foo2_without_def +; CHECK: select +entry: + %shl = shl i32 %a, 1 + %and = and i32 %shl, 30 + switch i32 %and, label %sw.default [ + i32 0, label %sw.bb + i32 2, label %sw.bb + i32 4, label %sw.bb + i32 6, label %sw.bb + i32 8, label %sw.bb + i32 10, label %sw.bb + i32 12, label %sw.bb + i32 14, label %sw.bb + i32 16, label %sw.bb1 + i32 18, label %sw.bb1 + i32 20, label %sw.bb1 + i32 22, label %sw.bb1 + i32 24, label %sw.bb1 + i32 26, label %sw.bb1 + i32 28, label %sw.bb1 + i32 30, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.default: + br label %return + +return: + %retval.0 = phi i32 [ 30, %sw.default ], [ 20, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} Index: test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectTwoCase.ll =================================================================== --- /dev/null +++ test/Transforms/SimplifyCFG/2014-06-19-SwitchToSelectTwoCase.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; int foo1_with_def(int a) { +; switch(a) { +; case 10: +; return 10; +; case 20: +; return 2; +; } +; return 4; +; } +; +; int foo1_without_def(int a) { +; switch(a) { +; case 10: +; return 10; +; case 20: +; return 2; +; } +; __builtin_unreachable(); +; } + +define i32 @foo1_with_def(i32 %a) #0 { +; CHECK-LABEL: @foo1_with_def +; CHECK: icmp eq i32 +; CHECK-NEXT: select i1 +; CHECK-NEXT: icmp eq i32 +; CHECK-NEXT: select i1 +entry: + switch i32 %a, label %sw.epilog [ + i32 10, label %sw.bb + i32 20, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.epilog: + br label %return + +return: + %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @foo1_without_def(i32 %a) #0 { +; CHECK-LABEL: @foo1_without_def +; CHECK: icmp eq i32 +; CHECK-NEXT: select i1 +; CHECK-NOT: %switch.selectcmp1 +entry: + switch i32 %a, label %sw.epilog [ + i32 10, label %sw.bb + i32 20, label %sw.bb1 + ] + +sw.bb: + br label %return + +sw.bb1: + br label %return + +sw.epilog: + unreachable + +return: + %retval.0 = phi i32 [ 2, %sw.bb1 ], [ 10, %sw.bb ] + ret i32 %retval.0 +} Index: test/Transforms/SimplifyCFG/UnreachableEliminate.ll =================================================================== --- test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -48,11 +48,13 @@ ; PR9450 define i32 @test4(i32 %v) { +; CHECK-LABEL: @test4( ; CHECK: entry: -; CHECK-NEXT: switch i32 %v, label %T [ -; CHECK-NEXT: i32 3, label %V -; CHECK-NEXT: i32 2, label %U -; CHECK-NEXT: ] +; CHECK: %switch.selectcmp = icmp eq i32 %v, 3 +; CHECK-NEXT: %switch.select = select i1 %switch.selectcmp, i32 7, i32 2 +; CHECK-NEXT: %switch.selectcmp1 = icmp eq i32 %v, 2 +; CHECK-NEXT: %switch.select2 = select i1 %switch.selectcmp1, i32 1, i32 %switch.select +; CHECK-NEXT: ret i32 %switch.select2 entry: br label %SWITCH Index: test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll =================================================================== --- test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -915,8 +915,12 @@ %x = phi i32 [ 3, %sw.default ], [ 7, %sw.bb1 ], [ 9, %entry ] ret i32 %x ; CHECK-LABEL: @twocases( -; CHECK: switch i32 +; CHECK-NOT: switch i32 ; CHECK-NOT: @switch.table +; CHECK: %switch.selectcmp +; CHECK-NEXT: %switch.select +; CHECK-NEXT: %switch.selectcmp1 +; CHECK-NEXT: %switch.select2 } ; Don't build tables for switches with TLS variables. Index: test/Transforms/SimplifyCFG/switch-to-icmp.ll =================================================================== --- test/Transforms/SimplifyCFG/switch-to-icmp.ll +++ test/Transforms/SimplifyCFG/switch-to-icmp.ll @@ -16,8 +16,8 @@ ret i1 %0 ; CHECK-LABEL: @test1( -; CHECK: %x.off = add i32 %x, -1 -; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: %switch.off = add i32 %x, -1 +; CHECK: %switch.cmp = icmp ult i32 %switch.off, 3 } define zeroext i1 @test2(i32 %x) nounwind readnone ssp noredzone { @@ -35,7 +35,7 @@ ret i1 %0 ; CHECK-LABEL: @test2( -; CHECK: %switch = icmp ult i32 %x, 2 +; CHECK: %switch.cmp = icmp ult i32 %x, 2 } define i32 @test3(i1 %flag) { Index: test/Transforms/SimplifyCFG/switch_create.ll =================================================================== --- test/Transforms/SimplifyCFG/switch_create.ll +++ test/Transforms/SimplifyCFG/switch_create.ll @@ -180,8 +180,8 @@ ret i1 %UnifiedRetVal ; CHECK-LABEL: @test6( -; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14 -; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6 +; CHECK: %switch.off = add i32 %tmp.2.i, -14 +; CHECK: %switch.cmp = icmp ult i32 %switch.off, 6 } define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone { @@ -480,8 +480,8 @@ define zeroext i1 @test16(i32 %x) nounwind { entry: ; CHECK-LABEL: @test16( -; CHECK: %x.off = add i32 %x, -1 -; CHECK: %switch = icmp ult i32 %x.off, 3 +; CHECK: %switch.off = add i32 %x, -1 +; CHECK: %switch.cmp = icmp ult i32 %switch.off, 3 %cmp.i = icmp eq i32 %x, 1 br i1 %cmp.i, label %lor.end, label %lor.lhs.false