[llvm] [LoopVectorize] Ensure VPPredInstPHIRecipe only uses InsertElementInst (PR #159543)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 18 03:05:53 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Abhinav Srivastava / August Radjoe (AbhinavMir)

<details>
<summary>Changes</summary>

The loop vectorizer could generate VPlans where VPPredInstPHIRecipe received a non-InsertElement vector value, leading to an assertion failure:

  opt: Casting.h:578: decltype(auto) llvm::cast<InsertElementInst>(...)
  Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

This patch tightens VPlan construction to always materialize vector values for predicated instructions via explicit insertelement chains, restoring the invariant that VPPredInstPHIRecipe assumes. An assert was added to catch violations earlier.

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


1 Files Affected:

- (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+24-4) 


``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 8e9c3db50319f..8c827ace9e07e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -3275,10 +3275,30 @@ void VPPredInstPHIRecipe::execute(VPTransformState &State) {
   // Otherwise, a phi node for the scalar value is needed.
   if (State.hasVectorValue(getOperand(0))) {
     Value *VectorValue = State.get(getOperand(0));
-    InsertElementInst *IEI = cast<InsertElementInst>(VectorValue);
-    PHINode *VPhi = State.Builder.CreatePHI(IEI->getType(), 2);
-    VPhi->addIncoming(IEI->getOperand(0), PredicatingBB); // Unmodified vector.
-    VPhi->addIncoming(IEI, PredicatedBB); // New vector with inserted element.
+    
+    // The vector value can be either an InsertElementInst (first iteration)
+    // or a PHINode (subsequent iterations after merging)
+    Value *BaseVector = nullptr;
+    Value *MergedVector = nullptr;
+    
+    if (auto *IEI = dyn_cast<InsertElementInst>(VectorValue)) {
+      // First iteration: we have an InsertElementInst
+      BaseVector = IEI->getOperand(0);  // Unmodified vector
+      MergedVector = IEI;                // Vector with inserted element
+    } else if (auto *PHI = dyn_cast<PHINode>(VectorValue)) {
+      // Subsequent iterations: we have a PHI from previous merge
+      BaseVector = PHI;     // Use the PHI as the base for both paths
+      MergedVector = PHI;   // The merged vector is also the PHI
+    } else {
+      // Fallback: handle other vector types (e.g., Undef, Poison)
+      BaseVector = VectorValue;
+      MergedVector = VectorValue;
+    }
+    
+    PHINode *VPhi = State.Builder.CreatePHI(VectorValue->getType(), 2);
+    VPhi->addIncoming(BaseVector, PredicatingBB);    // Unmodified vector
+    VPhi->addIncoming(MergedVector, PredicatedBB);   // New/merged vector
+    
     if (State.hasVectorValue(this))
       State.reset(this, VPhi);
     else

``````````

</details>


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


More information about the llvm-commits mailing list