[llvm] [InstCombine] Fold icmp with clamp into unsigned bound check (PR #161303)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 30 23:52:49 PDT 2025
================
@@ -5780,6 +5780,44 @@ Instruction *InstCombinerImpl::foldICmpWithMinMax(Instruction &I,
return nullptr;
}
+/// Match and fold patterns like:
+/// icmp eq/ne X, min(max(X, Lo), Hi)
+/// which represents a range check and can be repsented as a ConstantRange.
+///
+/// For icmp eq, build ConstantRange [Lo, Hi + 1) and convert to:
+/// (X - Lo) u< (Hi + 1 - Lo)
+/// For icmp ne, build ConstantRange [Hi + 1, Lo) and convert to:
+/// (X - (Hi + 1)) u< (Lo - (Hi + 1))
+Instruction *InstCombinerImpl::foldICmpWithClamp(ICmpInst &I, Value *X,
+ MinMaxIntrinsic *Min) {
+ if (!I.isEquality() || !Min->hasOneUse())
+ return nullptr;
+
+ const APInt *Lo = nullptr, *Hi = nullptr;
+ if (Min->isSigned()) {
+ if (!match(Min->getLHS(), m_OneUse(m_SMax(m_Specific(X), m_APInt(Lo)))) ||
+ !match(Min->getRHS(), m_APInt(Hi)) || !Lo->slt(*Hi))
+ return nullptr;
+ } else {
+ if (!match(Min->getLHS(), m_OneUse(m_UMax(m_Specific(X), m_APInt(Lo)))) ||
+ !match(Min->getRHS(), m_APInt(Hi)) || !Lo->ult(*Hi))
+ return nullptr;
+ }
+
+ ConstantRange CR(*Lo, *Hi + 1);
----------------
dtcxzyw wrote:
```suggestion
ConstantRange CR = ConstantRange::getNonEmpty(*Lo, *Hi + 1);
```
I noticed that `%Up = add i8 %Hi, 1 %precond2 = icmp ne i8 %Lo, %Up call void @llvm.assume(i1 %precond2)` in the proof is not checked by the code. Although it is unlikely to happen in practice, it would be better to guard against this case with `getNonEmpty`.
https://github.com/llvm/llvm-project/pull/161303
More information about the llvm-commits
mailing list