[llvm] [LV] Accept swapped operands in early-exit condition compare (PR #199989)

Madhur Amilkanthwar via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 22:06:07 PDT 2026


https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/199989

>From 9873bc29036feb818d8cac1ba2b45805e457effa Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Wed, 27 May 2026 00:42:29 -0700
Subject: [PATCH] [LV] Accept swapped operands in early-exit condition compare

Use m_c_ICmp so the load can be on either side of the icmp.
---
 .../Vectorize/LoopVectorizationLegality.cpp   |  6 ++---
 .../early_exit_store_legality.ll              | 25 +++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 214b5cff8a03a..0b81b657a4c07 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -1788,16 +1788,16 @@ bool LoopVectorizationLegality::canUncountableExitConditionLoadBeMoved(
   Instruction *L = nullptr;
   Value *Ptr = nullptr;
   Value *R = nullptr;
+  // The exit-condition load can appear on either side of the icmp.
   if (!match(Br->getCondition(),
-             m_OneUse(m_ICmp(m_OneUse(m_Instruction(L, m_Load(m_Value(Ptr)))),
-                             m_Value(R))))) {
+             m_OneUse(m_c_ICmp(m_OneUse(m_Instruction(L, m_Load(m_Value(Ptr)))),
+                               m_Value(R))))) {
     reportVectorizationFailure(
         "Early exit loop with store but no supported condition load",
         "NoConditionLoadForEarlyExitLoop", ORE, TheLoop);
     return false;
   }
 
-  // FIXME: Don't rely on operand ordering for the comparison.
   if (!TheLoop->isLoopInvariant(R)) {
     reportVectorizationFailure(
         "Early exit loop with store but no supported condition load",
diff --git a/llvm/test/Transforms/LoopVectorize/early_exit_store_legality.ll b/llvm/test/Transforms/LoopVectorize/early_exit_store_legality.ll
index 12065c01d47a4..dfa772887d73e 100644
--- a/llvm/test/Transforms/LoopVectorize/early_exit_store_legality.ll
+++ b/llvm/test/Transforms/LoopVectorize/early_exit_store_legality.ll
@@ -54,6 +54,31 @@ exit:
   ret void
 }
 
+;; Exit-condition load on the RHS of the icmp must still be accepted.
+define void @swapped_cmp_operands(ptr noalias %array, ptr %pred) {
+; CHECK-LABEL: LV: Checking a loop in 'swapped_cmp_operands'
+; CHECK:       LV: We can vectorize this loop!
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
+  %st.addr = getelementptr i16, ptr %array, i64 %iv
+  store i16 0, ptr %st.addr, align 2
+  %ee.addr = getelementptr i16, ptr %pred, i64 %iv
+  %ee.val = load i16, ptr %ee.addr, align 2
+  %ee.cond = icmp slt i16 500, %ee.val
+  br i1 %ee.cond, label %exit, label %latch
+
+latch:
+  %iv.next = add i64 %iv, 1
+  %latch.cond = icmp eq i64 %iv.next, 20
+  br i1 %latch.cond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
 ;; Avoid vectorization because we will either exit on the first iteration, or
 ;; never exit early.
 ;; We shouldn't see IR like this if LV-LICM has done its job.



More information about the llvm-commits mailing list