[llvm] [SimplifyCFG] Transform switch to select when common bits uniquely identify one case (PR #145233)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 1 01:30:36 PDT 2025
================
@@ -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)
+ // In case, there are bits, that can only be present in the CaseValues we
+ // can transform the switch into a select if the conjunction of
+ // all the values uniquely identify the CaseValues.
+ APInt AndMask = APInt::getAllOnes(MinCaseVal->getBitWidth());
+
+ for (auto *Case : CaseValues) {
if (Case->getValue().slt(MinCaseVal->getValue()))
MinCaseVal = Case;
+ AndMask &= Case->getValue();
+ }
+
+ KnownBits Known = computeKnownBits(Condition, DL);
+ unsigned int ConditionWidth = Condition->getType()->getIntegerBitWidth();
+ APInt ActiveBits =
+ APInt(ConditionWidth, Known.countMaxActiveBits(), false);
+
+ APInt One(ConditionWidth, 1, false);
+ // To make sure, that the representation of the accepted values is
+ // actually unique we check, wheter the conjucted bits and the another
+ // conjuction with the input value will only be true for exactly CaseCount
+ // number times.
+ if ((One << (ActiveBits - AndMask.popcount())) == CaseCount) {
----------------
antoniofrighetto wrote:
I feel like there are too unnecessary APInts here, what about the following? I think this should be safe from wrap-arounds too (should never have the number of bit sets in AndMask greater than the active bits).
```cpp
KnownBits Known = computeKnownBits(Condition, DL);
unsigned ConditionWidth = Condition->getType()->getIntegerBitWidth();
// To make sure that the representation of the accepted values is
// actually unique, we check whether the conjuction bits and the other
// conjuction with the input value will only be true for exactly CaseCount
// number times.
// Compute the number of bits that are free to vary.
unsigned FreeBits = Known.countMaxActiveBits() - AndMask.popcount();
// Compute 2^FreeBits in order to check whether all the possible
// combination of the free bits matches the number of cases.
APInt TopBit = APInt::getOneBitSet(ConditionWidth, FreeBits);
if (TopBit == CaseCount) {
// ...
}
```
https://github.com/llvm/llvm-project/pull/145233
More information about the llvm-commits
mailing list