[llvm] [SimplifyCFG] Simplify switch with implicit default (PR #95665)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 15 12:29:16 PDT 2024


================
@@ -7104,6 +7104,47 @@ static bool simplifySwitchOfPowersOfTwo(SwitchInst *SI, IRBuilder<> &Builder,
   return true;
 }
 
+// Try to fold switch with manually selected default branch.
+// For example, for the switch
+//   switch (v) { case 0: case 1: case 2: ... case MaxC: default: }
+//     (continuous cases value from 0 to MaxC)
+//   and, v = select (x u<= MaxC), x, AnotherC.
+// so "AnotherC" is the de-facto default branch, and it will be folded to
+//   switch (x) { case 0: case 1: case 2: ... case MaxC:  default -> AnotherC: }
+static bool simplifySwitchWithImplicitDefault(SwitchInst *SI) {
+  Value *Cond;
+  ConstantInt *Bound, *DefaultCase;
+  ICmpInst::Predicate Pred;
+  if (!match(SI->getCondition(),
+             m_Select(m_ICmp(Pred, m_Value(Cond), m_ConstantInt(Bound)),
+                      m_Deferred(Cond), m_ConstantInt(DefaultCase))) ||
+      Pred != CmpInst::ICMP_ULT)
+    return false;
+
+  // In an ideal situation, the range of switch cases is continuous,
+  // and should match the range of ICmp. That is,
+  //   MaxCase (declared below) + 1 = SI->getNumCases() = OuterRange.Upper.
+  // Checking it partially here can be a fast-fail path
+  if (Bound->getValue() != SI->getNumCases())
+    return false;
+
+  SmallVector<APInt, 4> Values;
+  for (const auto &Case : SI->cases())
+    Values.push_back(Case.getCaseValue()->getValue());
+  llvm::sort(Values,
+             [](const APInt &lhs, const APInt &rhs) { return lhs.ult(rhs); });
+
+  // The cases should be continuous from 0 to some value
+  if (!Values.begin()->isZero() || *Values.rbegin() != SI->getNumCases() - 1)
+    return false;
----------------
dtcxzyw wrote:

```suggestion
  APInt Min = ...;
  APInt Max = ...;
  for (const auto &Case : SI->cases()) {
    auto &CaseVal = Case.getCaseValue()->getValue();
    if (CaseVal.ult(Min)) Min = CaseVal;
    else if (CaseVal.ugt(Max)) Max = CaseVal;
  }

  // The cases should be continuous from 0 to some value
  if (!Min.isZero() || Max != SI->getNumCases() - 1)
    return false;
```

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


More information about the llvm-commits mailing list