aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp31
1 files changed, 27 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 147d206..a75f290 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6198,7 +6198,7 @@ static bool initializeUniqueCases(SwitchInst *SI, PHINode *&PHI,
// TODO: Handle switches with more than 2 cases that map to the same result.
static Value *foldSwitchToSelect(const SwitchCaseResultVectorTy &ResultVector,
Constant *DefaultResult, Value *Condition,
- IRBuilder<> &Builder) {
+ IRBuilder<> &Builder, const DataLayout &DL) {
// If we are selecting between only two cases transform into a simple
// select or a two-way select if default is possible.
// Example:
@@ -6234,10 +6234,33 @@ static Value *foldSwitchToSelect(const SwitchCaseResultVectorTy &ResultVector,
// case 0,2,8,10 -> Cond & 0b1..0101 == 0 ? result : default
if (isPowerOf2_32(CaseCount)) {
ConstantInt *MinCaseVal = CaseValues[0];
- // Find mininal value.
- for (auto *Case : CaseValues)
+ // If there are bits that are set exclusively by CaseValues, we
+ // can transform the switch into a select if the conjunction of
+ // all the values uniquely identify CaseValues.
+ APInt AndMask = APInt::getAllOnes(MinCaseVal->getBitWidth());
+
+ // Find the minimum value and compute the and of all the case values.
+ for (auto *Case : CaseValues) {
if (Case->getValue().slt(MinCaseVal->getValue()))
MinCaseVal = Case;
+ AndMask &= Case->getValue();
+ }
+ KnownBits Known = computeKnownBits(Condition, DL);
+
+ if (!AndMask.isZero() && Known.getMaxValue().uge(AndMask)) {
+ // Compute the number of bits that are free to vary.
+ unsigned FreeBits = Known.countMaxActiveBits() - AndMask.popcount();
+
+ // Check if the number of values covered by the mask is equal
+ // to the number of cases.
+ if (FreeBits == Log2_32(CaseCount)) {
+ Value *And = Builder.CreateAnd(Condition, AndMask);
+ Value *Cmp = Builder.CreateICmpEQ(
+ And, Constant::getIntegerValue(And->getType(), AndMask));
+ return Builder.CreateSelect(Cmp, ResultVector[0].first,
+ DefaultResult);
+ }
+ }
// Mark the bits case number touched.
APInt BitMask = APInt::getZero(MinCaseVal->getBitWidth());
@@ -6325,7 +6348,7 @@ static bool trySwitchToSelect(SwitchInst *SI, IRBuilder<> &Builder,
assert(PHI != nullptr && "PHI for value select not found");
Builder.SetInsertPoint(SI);
Value *SelectValue =
- foldSwitchToSelect(UniqueResults, DefaultResult, Cond, Builder);
+ foldSwitchToSelect(UniqueResults, DefaultResult, Cond, Builder, DL);
if (!SelectValue)
return false;