[llvm] [SimplifyCFG] Simplify switch with implicit default (PR #95665)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 16 02:33:07 PDT 2024
================
@@ -7104,6 +7104,61 @@ 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))))
+ return false;
+
+ ConstantRange OuterRange =
+ ConstantRange::makeExactICmpRegion(Pred, Bound->getValue());
+ if (!OuterRange.getLower().isZero())
+ return false;
+
+ bool HasDefault =
+ !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
+
+ // In an ideal situation, if default is reachable, the range of switch cases
+ // should be 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 (HasDefault && OuterRange.getUpper() != SI->getNumCases())
+ return false;
+
+ APInt Min = SI->case_begin()->getCaseValue()->getValue(), Max = Min;
+ for (const auto &Case : SI->cases()) {
----------------
dtcxzyw wrote:
Can we use `drop_front` here?
https://github.com/llvm/llvm-project/pull/95665
More information about the llvm-commits
mailing list