[llvm] [LV] Add initial legality checks for ee loops with stores (PR #145663)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 18 03:26:39 PDT 2025


================
@@ -1781,6 +1803,109 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
                        "backedge taken count: "
                     << *SymbolicMaxBTC << '\n');
   UncountableExitingBB = SingleUncountableExitingBlock;
+  UncountedExitWithSideEffects = HasSideEffects;
+  return true;
+}
+
+bool LoopVectorizationLegality::canUncountedExitConditionLoadBeMoved(
+    BasicBlock *ExitingBlock) {
+  SmallVector<const SCEVPredicate *, 4> Predicates;
+  LoadInst *CriticalUncountedExitConditionLoad = nullptr;
+
+  // Try to find a load in the critical path for the uncounted exit condition.
+  // This is currently matching about the simplest form we can, expecting
+  // only one in-loop load, the result of which is directly compared against
+  // a loop-invariant value.
+  // FIXME: We're insisting on a single use for now, because otherwise we will
+  // need to make PHI nodes for other users. That can be done once the initial
+  // transform code lands.
+  auto *Br = cast<BranchInst>(ExitingBlock->getTerminator());
+
+  // FIXME: Don't rely on operand ordering for the comparison.
+  ICmpInst *Cmp = dyn_cast<ICmpInst>(Br->getCondition());
+  if (Cmp && Cmp->hasOneUse() && TheLoop->isLoopInvariant(Cmp->getOperand(1))) {
+    LoadInst *Load = dyn_cast<LoadInst>(Cmp->getOperand(0));
+    if (Load && Load->hasOneUse()) {
+      // Make sure that the load address is not loop invariant; we want an
+      // address calculation that we can rotate to the next vector iteration.
+      const SCEV *PtrScev = PSE.getSE()->getSCEV(Load->getPointerOperand());
+      if (PSE.getSE()->isLoopInvariant(PtrScev, TheLoop)) {
+        reportVectorizationFailure(
+            "Uncounted exit condition depends on load from invariant address",
+            "EarlyExitLoadInvariantAddress", ORE, TheLoop);
+        return false;
+      }
+
+      // The following call also checks that the load address is either
+      // invariant (which we've just ruled out) or is an affine SCEVAddRecExpr
+      // with a constant step. In either case, we're not relying on another
+      // load within the loop.
+      // FIXME: Support gathers after first-faulting load support lands.
+      if (isDereferenceableAndAlignedInLoop(Load, TheLoop, *PSE.getSE(), *DT,
+                                            AC, &Predicates)) {
+        ICFLoopSafetyInfo SafetyInfo;
+        SafetyInfo.computeLoopSafetyInfo(TheLoop);
+        // We need to know that load will be executed before we can hoist a
+        // copy out to run just before the first iteration.
+        if (SafetyInfo.isGuaranteedToExecute(*Load, DT, TheLoop))
+          CriticalUncountedExitConditionLoad = Load;
+        else
+          reportVectorizationFailure(
+              "Early exit condition load not guaranteed to execute",
+              "EarlyExitLoadNotGuaranteed", ORE, TheLoop);
----------------
fhahn wrote:

should this return false here?

It also seems like this code-path isn't covered. Not sure if it would be possible to add a test?

https://github.com/llvm/llvm-project/pull/145663


More information about the llvm-commits mailing list