[llvm] [InstCombine] Fold `(x < y) ? -1 : zext(x != y)` into `u/scmp(x,y)` (PR #101049)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 10 09:19:42 PDT 2024
================
@@ -3529,6 +3529,62 @@ static Instruction *foldBitCeil(SelectInst &SI, IRBuilderBase &Builder) {
Masked);
}
+// This function tries to fold the following operations:
+// (x < y) ? -1 : zext(x != y)
+// (x > y) ? 1 : sext(x != y)
+// (x >= y) ? zext(x != y) : -1
+// Into ucmp/scmp(x, y), where signedness is determined by the signedness
+// of the comparison in the original sequence
+Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) {
+ Value *TV = SI.getTrueValue();
+ Value *FV = SI.getFalseValue();
+
+ ICmpInst::Predicate Pred;
+ Value *LHS, *RHS;
+ if (!match(SI.getCondition(), m_ICmp(Pred, m_Value(LHS), m_Value(RHS))))
+ return nullptr;
+
+ if (!LHS->getType()->isIntOrIntVectorTy())
+ return nullptr;
+
+ // Try to swap operands and the predicate. We need to be careful when doing
+ // so because two of the patterns have opposite predicates, so use the
+ // constant inside select to determine if swapping operands would be
+ // beneficial to us.
+ if ((ICmpInst::isGT(Pred) && match(TV, m_AllOnes())) ||
+ (ICmpInst::isLT(Pred) && match(TV, m_One())) || ICmpInst::isLE(Pred)) {
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ std::swap(LHS, RHS);
+ }
+
+ Intrinsic::ID IID =
+ ICmpInst::isSigned(Pred) ? Intrinsic::scmp : Intrinsic::ucmp;
+
+ CallInst *Intrinsic = nullptr;
+ ICmpInst::Predicate NEPred;
+ // (x < y) ? -1 : zext(x != y)
+ if (ICmpInst::isLT(Pred) && match(TV, m_AllOnes()) &&
+ match(FV, m_ZExt(m_c_ICmp(NEPred, m_Specific(LHS), m_Specific(RHS)))) &&
----------------
nikic wrote:
```suggestion
match(FV, m_ZExt(m_c_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(LHS), m_Specific(RHS)))) &&
```
This helper was recently added.
https://github.com/llvm/llvm-project/pull/101049
More information about the llvm-commits
mailing list