[llvm] Introduce check-first vectorization for early-exit loops. (PR #227201)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 28 23:56:42 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-vectorizers

Author: Arjun H Kumar (arjun-harikumar-amd)

<details>
<summary>Changes</summary>

Check-first is a new strategy for vectorizing loops that have
uncountable early exits and also store to memory. The existing
strategies either require the loop to be read-only, or speculate the
whole body and mask its side effects. Check-first instead evaluates the
exit conditions for an entire vector chunk up front and executes the
body only when no lane exits. When an exit fires, the chunk is abandoned
and replayed by the scalar loop, which resumes from the start of that
chunk rather than from the exiting lane.

The vector loop is restructured into a cascade:

-   vector.check       
-   vector.check1..N-1 
-   vector.body        
-   vector.check.exit 

  
 Example:
 IR before:
```
 loop:
    %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
    %x.ptr = getelementptr inbounds [1024 x i32], ptr @<!-- -->x, i64 0, i64 %iv
    %x.val = load i32, ptr %x.ptr, align 4
    %found = icmp ne i32 %x.val, 0
    br i1 %found, label %exit, label %latch

  latch:
    %a.ptr = getelementptr inbounds [1024 x i32], ptr @<!-- -->a, i64 0, i64 %iv
    store i32 1, ptr %a.ptr, align 4
    %iv.next = add nuw nsw i64 %iv, 1
    %done = icmp eq i64 %iv.next, 1024
    br i1 %done, label %exit, label %loop
```

With this patch the vectorized code is emitted as:

  ```
vector.check:               ; preds = %vector.body, %vector.ph
    %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
    %0 = add i64 %index, 1
    %1 = add i64 %index, 2
    %2 = add i64 %index, 3
    %3 = getelementptr inbounds [1024 x i32], ptr @<!-- -->x, i64 0, i64 %index
    %wide.load = load <4 x i32>, ptr %3, align 4
    %4 = icmp ne <4 x i32> %wide.load, zeroinitializer
    %5 = freeze <4 x i1> %4
    %6 = call i1 @<!-- -->llvm.vector.reduce.or.v4i1(<4 x i1> %5)
    br i1 %6, label %vector.check.exit, label %vector.body

  vector.body:                ; preds = %vector.check
    %7 = getelementptr inbounds [1024 x i32], ptr @<!-- -->a, i64 0, i64 %index
    %8 = getelementptr inbounds [1024 x i32], ptr @<!-- -->a, i64 0, i64 %0
    %9 = getelementptr inbounds [1024 x i32], ptr @<!-- -->a, i64 0, i64 %1
    %10 = getelementptr inbounds [1024 x i32], ptr @<!-- -->a, i64 0, i64 %2
    store i32 1, ptr %7, align 4
    store i32 1, ptr %8, align 4
    store i32 1, ptr %9, align 4
    store i32 1, ptr %10, align 4
    %index.next = add nuw i64 %index, 4
    %11 = icmp eq i64 %index.next, 1024
    br i1 %11, label %middle.block, label %vector.check

  vector.check.exit:          ; preds = %vector.check
    br label %scalar.ph

  scalar.ph:                  ; preds = %vector.check.exit
    br label %loop

  loop:                       ; preds = %scalar.ph, %latch
    %iv = phi i64 [ %index, %scalar.ph ], [ %iv.next, %latch ]
```

---
Full diff: https://github.com/llvm/llvm-project/pull/227201.diff


17 Files Affected:

- (modified) llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h (+23) 
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp (+222-3) 
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h (+2) 
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+82-12) 
- (modified) llvm/lib/Transforms/Vectorize/VPlan.cpp (+31) 
- (modified) llvm/lib/Transforms/Vectorize/VPlan.h (+69) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp (+15-2) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanLowering.cpp (+3) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp (+2) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+12-1) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp (+433-1) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.h (+3) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp (+6) 
- (added) llvm/test/Transforms/LoopVectorize/check-first-instruction-reorder.ll (+196) 
- (added) llvm/test/Transforms/LoopVectorize/check-first-multi-exit-cascade.ll (+133) 
- (added) llvm/test/Transforms/LoopVectorize/check-first-single-exit.ll (+136) 
- (added) llvm/test/Transforms/LoopVectorize/check-first-state-update.ll (+109) 


``````````diff
The server is unavailable at this time. Please wait a few minutes before you try again.
``````````

</details>


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


More information about the llvm-commits mailing list