[llvm] [SimplifyCFG] Add optimization for switches of powers of two (PR #70977)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 12 09:26:03 PST 2023


================
@@ -6839,6 +6837,73 @@ static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder,
   return true;
 }
 
+static bool isSwitchOfPowersOfTwo(ArrayRef<APInt> Values) {
+  for (auto &Value : Values) {
+    if (!Value.isPowerOf2())
+      return false;
+  }
+
+  return true;
+}
+
+static bool simplifySwitchOfPowersOfTwo(SwitchInst *SI, IRBuilder<> &Builder,
+                                        const DataLayout &DL,
+                                        const TargetTransformInfo &TTI) {
+
+  auto *Condition = SI->getCondition();
+  auto &Context = SI->getContext();
+  auto *CondTy = cast<IntegerType>(Condition->getType());
+
+  if (CondTy->getIntegerBitWidth() > 64 ||
+      !DL.fitsInLegalInteger(CondTy->getIntegerBitWidth()))
+    return false;
+
+  const auto &CttzIntrinsicCost = TTI.getIntrinsicInstrCost(
+      IntrinsicCostAttributes(Intrinsic::cttz, CondTy,
+                              {Condition, ConstantInt::getTrue(Context)}),
+      TTI::TCK_SizeAndLatency);
+
+  if (CttzIntrinsicCost > TTI::TargetCostConstants::TCC_Basic) {
+    // Inserting intrinsic is too expensive
+    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.
+  if (SI->getNumCases() < 4)
+    return false;
+
+  SmallVector<APInt, 4> Values;
+  for (const auto &Case : SI->cases())
+    Values.push_back(Case.getCaseValue()->getValue());
+
+  // We perform this optimization only for switches with
+  // unreachable default case.
+  // This assumtion will save us from checking if `Condition` is a power of two
+  bool HasDefault =
+      !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
+
+  if (HasDefault || !isSwitchOfPowersOfTwo(Values))
+    return false;
+
+  Builder.SetInsertPoint(SI);
+
+  auto *ConditionTrailingZeros =
+      Builder.CreateIntrinsic(Intrinsic::cttz, {Condition->getType()},
----------------
dtcxzyw wrote:

```suggestion
      Builder.CreateIntrinsic(Intrinsic::cttz, {CondTy},
```

https://github.com/llvm/llvm-project/pull/70977


More information about the llvm-commits mailing list