Skip to content

Conversation

AbhinavMir
Copy link

@AbhinavMir AbhinavMir commented Sep 18, 2025

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 (plans to?) tighten 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.

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.
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Sep 18, 2025

@llvm/pr-subscribers-vectorizers

@llvm/pr-subscribers-llvm-transforms

Author: Abhinav Srivastava / August Radjoe (AbhinavMir)

Changes

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 --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

@AbhinavMir AbhinavMir marked this pull request as draft September 18, 2025 10:06
@AbhinavMir
Copy link
Author

AbhinavMir commented Sep 18, 2025

Sorry if it tagged anyone! I'm still figuring things out:

Have some errors around!

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AbhinavMir Could you add a reduced test for the crash so it is a bit easier to figure out what's going wrong?

How does the VPlan look like before we crash? It might be something that is better fixed awhen we create/optimize the VPlan

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp -- llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 8c827ace9..a1b613fc3 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -3275,30 +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));
-    
+
     // 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
+      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
+      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
-    
+    VPhi->addIncoming(BaseVector, PredicatingBB);  // Unmodified vector
+    VPhi->addIncoming(MergedVector, PredicatedBB); // New/merged vector
+
     if (State.hasVectorValue(this))
       State.reset(this, VPhi);
     else

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverse ping @AbhinavMir , just checking in if you are still working on the fix and saw my latest comment?

@fhahn
Copy link
Contributor

fhahn commented Oct 6, 2025

@AbhinavMir I investigated a similar reported failure #161974 and it looks like the underlying issue is related to CSE: #162110

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants