[llvm] [Vectorizer] Conversion of icmp eq to icmp ult to enable vectorization (PR #202368)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 08:32:30 PDT 2026
https://github.com/Bhuvan1527 created https://github.com/llvm/llvm-project/pull/202368
Resolves: https://github.com/llvm/llvm-project/issues/190505
The current slp-vectorizer donot recognize the following pattern
```
icmp eq %x, 0
icmp ult %y, ..
icmp ult
..
```
It will not convert icmp eq to icmp ult. Hence, full vectorization is skipped. Instead it performs altshuffle vectorization. Creating two vector instructions (one for only eq, other for ult) followed by shuffleVec instructions to combine the results.
In this pr, we are supporting this pattern by checking and canonicalizing the icmp eq to icmp ult before computing Legality.getInstructionsState().
>From 76bf9ff8c940186084dc38b12cd6d33b40039cc0 Mon Sep 17 00:00:00 2001
From: bhuvan1527 <balabhuvanvarma at gmail.com>
Date: Mon, 8 Jun 2026 20:52:39 +0530
Subject: [PATCH] [Vectorizer] Conversion of icmp eq to icmp ult to enable
vectorization
Resolves: https://github.com/llvm/llvm-project/issues/190505
The current slp-vectorizer donot recognize the following pattern
icmp eq %x, 0
icmp ult %y, ..
icmp ult
..
It will not convert icmp eq to icmp ult. Because of full vectorization
is skipped. Instead it performs alt shuffle approach. Creating
two vector instructions (one for only eq, other for ult) followed by
shuffleVec instructions.
In this pr, we are supporting this pattern by checking and canonicalizing
the icmp eq to icmp ult before computing Legality.getInstructionsState().
---
.../Transforms/Vectorize/SLPVectorizer.cpp | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index f9532a0bd0616..408ebbae1f614 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -12800,6 +12800,38 @@ void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
SmallVector<int> ReuseShuffleIndices;
SmallVector<Value *> VL(VLRef);
+ if (VL.size() > 1 && isa<ICmpInst>(VL[0])) {
+ // Changes icmp eq %x, 0 -> icmp ult %x, 1 when the rest of
+ // the instructions are icmp ult .. . This prevents to move
+ // towards altShuffle path.
+ bool HasEqZero = false;
+ bool AllUltOrEqZero = all_of(VL, [&HasEqZero](Value *V) {
+ auto *Cmp = dyn_cast<ICmpInst>(V);
+ if (!Cmp)
+ return isa<PoisonValue>(V);
+ if (Cmp->getPredicate() == ICmpInst::ICMP_ULT)
+ return true;
+ if (Cmp->getPredicate() == ICmpInst::ICMP_EQ)
+ if (auto *C = dyn_cast<ConstantInt>(Cmp->getOperand(1)))
+ if (C->isZero()) {
+ HasEqZero = true;
+ return true;
+ }
+ return false;
+ });
+
+ if (HasEqZero && AllUltOrEqZero) {
+ for (Value *V : VL) {
+ auto *Cmp = dyn_cast<ICmpInst>(V);
+ if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_EQ)
+ continue;
+ Cmp->setPredicate(ICmpInst::ICMP_ULT);
+ Cmp->setOperand(1, ConstantInt::get(Cmp->getOperand(1)->getType(), 1));
+ LLVM_DEBUG(dbgs() << "SLP: Canonicalized icmp eq 0 to ult 1: "
+ << *Cmp << "\n");
+ }
+ }
+}
// Tries to build split node.
auto TrySplitNode = [&](const InstructionsState &LocalState) {
SmallVector<Value *> Op1, Op2;
More information about the llvm-commits
mailing list