Skip to content

[VPlan] Assert vplan-verify-each result and fix LastActiveLane verification#182254

Merged
lukel97 merged 12 commits intollvm:mainfrom
lukel97:loop-vectorize/vplan-verify-assert
Feb 25, 2026
Merged

[VPlan] Assert vplan-verify-each result and fix LastActiveLane verification#182254
lukel97 merged 12 commits intollvm:mainfrom
lukel97:loop-vectorize/vplan-verify-assert

Conversation

@lukel97
Copy link
Copy Markdown
Contributor

@lukel97 lukel97 commented Feb 19, 2026

Currently if -vplan-verify-each is enabled and a pass fails the verifier, it will output the failure to stderr but will still finish with a zero exit code.

This adds an assert that the verification fails so that e.g. lit will pick up verifier failures in the in-tree tests with an EXPENSIVE_CHECKS build.

Currently the LastActiveLane verification fails in several tests, so this also includes a fix to handle more prefix masks. All of the prefix masks that the verifier encounters are of the form icmp ult/ule monotonically-increasing-sequence, uniform, which always generate a prefix mask.

Tested that llvm-test-suite + SPEC CPU 2017 now pass with -vplan-verify-each enabled for RISC-V.

Currently if -vplan-verify-each is enabled and a pass fails the verifier, it will output the failure to stderr but will still finish with a zero exit code.

This adds an assert that the verification fails so that e.g. lit will pick up verifier failures in the in-tree tests with an EXPENSIVE_CHECKS build. However currently the verifier fails in several tests, so this also includes several fixes:

1. Remove the EVL verifier checks. The EVL is used in quite a few more places than when the verification was originally added, and nowadays it gets used in a variety of VPInstructions, all of which need to be handled by the verifier. There are a few passes that fail today because we haven't updated the EVL verification. Now that the EVL transform has been split up into a variable stepping transform and an optimization pass it's generally less fragile, so there is less value in this verification.
2. Extend the LastActiveLane verification to handle more prefix masks. All of the prefix masks that the verifier encounters are of the form `icmp ult/ule monotonically-increasing-sequence, uniform`, which always generate a prefix mask.
3. Allow multiple VPActiveLaneMaskPHIRecipe recipes after unrolling. This also allows us to remove the verifyLate argument

Tested that llvm-test-suite + SPEC CPU 2017 now pass with -vplan-verify-each enabled for RISC-V.
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 19, 2026

@llvm/pr-subscribers-vectorizers

Author: Luke Lau (lukel97)

Changes

Currently if -vplan-verify-each is enabled and a pass fails the verifier, it will output the failure to stderr but will still finish with a zero exit code.

This adds an assert that the verification fails so that e.g. lit will pick up verifier failures in the in-tree tests with an EXPENSIVE_CHECKS build. However currently the verifier fails in several tests, so this also includes several fixes:

  1. Remove the EVL verifier checks. The EVL is used in quite a few more places than when the verification was originally added, and nowadays it gets used in a variety of VPInstructions, all of which need to be handled by the verifier. There are a few passes that fail today because we haven't updated the EVL verification. Now that the EVL transform has been split up into a variable stepping transform and an optimization pass it's generally less fragile, so there is less value in this verification.
  2. Extend the LastActiveLane verification to handle more prefix masks. All of the prefix masks that the verifier encounters are of the form icmp ult/ule monotonically-increasing-sequence, uniform, which always generate a prefix mask.
  3. Allow multiple VPActiveLaneMaskPHIRecipe recipes after unrolling. This also allows us to remove the verifyLate argument

Tested that llvm-test-suite + SPEC CPU 2017 now pass with -vplan-verify-each enabled for RISC-V.


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

4 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+2-3)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.h (+4-2)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp (+26-125)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanVerifier.h (+2-4)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 01433fe4c4ba7..68bdb9f4ba23f 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -364,7 +364,7 @@ cl::opt<bool>
                           cl::init(false),
 #endif
                           cl::Hidden,
-                          cl::desc("Verfiy VPlans after VPlan transforms."));
+                          cl::desc("Verify VPlans after VPlan transforms."));
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 cl::opt<bool> llvm::VPlanPrintAfterAll(
@@ -7512,8 +7512,7 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
                         State.CFG.PrevBB->getSingleSuccessor(), &BestVPlan);
   VPlanTransforms::removeDeadRecipes(BestVPlan);
 
-  assert(verifyVPlanIsValid(BestVPlan, true /*VerifyLate*/) &&
-         "final VPlan is invalid");
+  assert(verifyVPlanIsValid(BestVPlan) && "final VPlan is invalid");
 
   // After vectorization, the exit blocks of the original loop will have
   // additional predecessors. Invalidate SCEVs for the exit phis in case SE
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index f2dfc166cecc9..e35872bbdff37 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -72,8 +72,10 @@ struct VPlanTransforms {
           dbgs() << Plan << '\n';
       }
 #endif
-      if (VerifyEachVPlan && EnableVerify)
-        verifyVPlanIsValid(Plan);
+      if (VerifyEachVPlan && EnableVerify) {
+        [[maybe_unused]] bool IsValid = verifyVPlanIsValid(Plan);
+        assert(IsValid && "VPlan is invalid");
+      }
     }};
 
     return std::forward<PassTy>(Pass)(Plan, std::forward<ArgsTy>(Args)...);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
index e4b334c3eba49..2db7287d494f6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
@@ -31,7 +31,6 @@ namespace {
 class VPlanVerifier {
   const VPDominatorTree &VPDT;
   VPTypeAnalysis &TypeInfo;
-  bool VerifyLate;
 
   SmallPtrSet<BasicBlock *, 8> WrappedIRBBs;
 
@@ -40,11 +39,6 @@ class VPlanVerifier {
   // VPHeaderPHIRecipes.
   bool verifyPhiRecipes(const VPBasicBlock *VPBB);
 
-  /// Verify that \p EVL is used correctly. The user must be either in
-  /// EVL-based recipes as a last operand or VPInstruction::Add which is
-  /// incoming value into EVL's recipe.
-  bool verifyEVLRecipe(const VPInstruction &EVL) const;
-
   /// Verify that \p LastActiveLane's operand is guaranteed to be a prefix-mask.
   bool verifyLastActiveLaneRecipe(const VPInstruction &LastActiveLane) const;
 
@@ -67,9 +61,8 @@ class VPlanVerifier {
   bool verifyRegionRec(const VPRegionBlock *Region);
 
 public:
-  VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo,
-                bool VerifyLate)
-      : VPDT(VPDT), TypeInfo(TypeInfo), VerifyLate(VerifyLate) {}
+  VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo)
+      : VPDT(VPDT), TypeInfo(TypeInfo) {}
 
   bool verify(const VPlan &Plan);
 };
@@ -124,7 +117,7 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
     RecipeI++;
   }
 
-  if (!VerifyLate && NumActiveLaneMaskPhiRecipes > 1) {
+  if (!VPBB->getPlan()->isUnrolled() && NumActiveLaneMaskPhiRecipes > 1) {
     errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
     return false;
   }
@@ -146,106 +139,19 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
   return true;
 }
 
-bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
-  if (EVL.getOpcode() != VPInstruction::ExplicitVectorLength) {
-    errs() << "verifyEVLRecipe should only be called on "
-              "VPInstruction::ExplicitVectorLength\n";
-    return false;
-  }
-  auto VerifyEVLUse = [&](const VPRecipeBase &R,
-                          const unsigned ExpectedIdx) -> bool {
-    SmallVector<const VPValue *> Ops(R.operands());
-    unsigned UseCount = count(Ops, &EVL);
-    if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
-      errs() << "EVL is used as non-last operand in EVL-based recipe\n";
-      return false;
-    }
+static bool isKnownMonotonic(VPValue *V) {
+  VPValue *X, *Y;
+  if (match(V, m_Add(m_VPValue(X), m_VPValue(Y))))
+    return isKnownMonotonic(X) && isKnownMonotonic(Y);
+  if (match(V, m_StepVector()))
     return true;
-  };
-  auto VerifyEVLUseInVecEndPtr = [&EVL](auto &VEPRs) {
-    if (all_of(VEPRs, [&EVL](VPUser *U) {
-          auto *VEPR = cast<VPVectorEndPointerRecipe>(U);
-          return match(VEPR->getOffset(),
-                       m_c_Mul(m_SpecificSInt(VEPR->getStride()),
-                               m_Sub(m_Specific(&EVL), m_One())));
-        }))
-      return true;
-    errs() << "Expected VectorEndPointer with EVL operand\n";
-    return false;
-  };
-  return all_of(EVL.users(), [&](VPUser *U) {
-    return TypeSwitch<const VPUser *, bool>(U)
-        .Case([&](const VPWidenIntrinsicRecipe *S) {
-          return VerifyEVLUse(*S, S->getNumOperands() - 1);
-        })
-        .Case<VPWidenStoreEVLRecipe, VPReductionEVLRecipe,
-              VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe>(
-            [&](const VPRecipeBase *S) { return VerifyEVLUse(*S, 2); })
-        .Case([&](const VPScalarIVStepsRecipe *R) {
-          if (R->getNumOperands() != 3) {
-            errs() << "Unrolling with EVL tail folding not yet supported\n";
-            return false;
-          }
-          return VerifyEVLUse(*R, 2);
-        })
-        .Case<VPWidenLoadEVLRecipe, VPVectorEndPointerRecipe,
-              VPInterleaveEVLRecipe>(
-            [&](const VPRecipeBase *R) { return VerifyEVLUse(*R, 1); })
-        .Case(
-            [&](const VPInstructionWithType *S) { return VerifyEVLUse(*S, 0); })
-        .Case([&](const VPInstruction *I) {
-          if (I->getOpcode() == Instruction::PHI ||
-              I->getOpcode() == Instruction::ICmp)
-            return VerifyEVLUse(*I, 1);
-          if (I->getOpcode() == Instruction::Sub) {
-            // If Sub has a single user that's a SingleDefRecipe (which is
-            // expected to be a Mul), filter its users, in turn, to get
-            // VectorEndPointerRecipes, and verify that all the offsets match
-            // (EVL - 1) * Stride.
-            if (auto *Def = dyn_cast_if_present<VPSingleDefRecipe>(
-                    I->getSingleUser())) {
-              auto VEPRs = make_filter_range(Def->users(),
-                                             IsaPred<VPVectorEndPointerRecipe>);
-              if (!VEPRs.empty())
-                return VerifyEVLUseInVecEndPtr(VEPRs);
-            }
-            return VerifyEVLUse(*I, 1);
-          }
-          switch (I->getOpcode()) {
-          case Instruction::Add:
-            break;
-          case Instruction::UIToFP:
-          case Instruction::Trunc:
-          case Instruction::ZExt:
-          case Instruction::Mul:
-          case Instruction::Shl:
-          case Instruction::FMul:
-          case VPInstruction::Broadcast:
-          case VPInstruction::PtrAdd:
-            // Opcodes above can only use EVL after wide inductions have been
-            // expanded.
-            if (!VerifyLate) {
-              errs() << "EVL used by unexpected VPInstruction\n";
-              return false;
-            }
-            break;
-          default:
-            errs() << "EVL used by unexpected VPInstruction\n";
-            return false;
-          }
-          if (!VerifyLate &&
-              !isa<VPCurrentIterationPHIRecipe>(*I->users().begin())) {
-            errs() << "Result of VPInstruction::Add with EVL operand is "
-                      "not used by VPCurrentIterationPHIRecipe\n";
-            return false;
-          }
-          return true;
-        })
-        .Default([&](const VPUser *U) {
-          errs() << "EVL has unexpected user\n";
-          return false;
-        });
-  });
+  if (auto *WidenIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(V))
+    return match(WidenIV->getStepValue(), m_One());
+  if (auto *WidenIV = dyn_cast<VPScalarIVStepsRecipe>(V))
+    return match(WidenIV->getStepValue(), m_One());
+  if (isa<VPWidenCanonicalIVRecipe>(V))
+    return true;
+  return vputils::isUniformAcrossVFsAndUFs(V);
 }
 
 bool VPlanVerifier::verifyLastActiveLaneRecipe(
@@ -259,18 +165,19 @@ bool VPlanVerifier::verifyLastActiveLaneRecipe(
   }
 
   const VPlan &Plan = *LastActiveLane.getParent()->getPlan();
-  // All operands must be prefix-mask. Currently we check for header masks or
-  // EVL-derived masks, as those are currently the only operands in practice,
-  // but this may need updating in the future.
+  // All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
+  // the LHS is monotonically increasing and RHS is uniform.
   for (VPValue *Op : LastActiveLane.operands()) {
     if (vputils::isHeaderMask(Op, Plan))
       continue;
 
-    // Masks derived from EVL are also fine.
-    auto BroadcastOrEVL =
-        m_CombineOr(m_Broadcast(m_EVL(m_VPValue())), m_EVL(m_VPValue()));
-    if (match(Op, m_CombineOr(m_ICmp(m_StepVector(), BroadcastOrEVL),
-                              m_ICmp(BroadcastOrEVL, m_StepVector()))))
+    CmpPredicate Pred;
+    VPValue *LHS, *RHS;
+    if (match(Op, m_ICmp(Pred, m_VPValue(LHS), m_VPValue(RHS))) &&
+        (Pred == CmpInst::ICMP_ULE || Pred == CmpInst::ICMP_ULT) &&
+        isKnownMonotonic(LHS) &&
+        (vputils::isUniformAcrossVFsAndUFs(RHS) ||
+         vputils::isSingleScalar(RHS)))
       continue;
 
     errs() << "LastActiveLane operand ";
@@ -372,12 +279,6 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
     }
     if (const auto *VPI = dyn_cast<VPInstruction>(&R)) {
       switch (VPI->getOpcode()) {
-      case VPInstruction::ExplicitVectorLength:
-        if (!verifyEVLRecipe(*VPI)) {
-          errs() << "EVL VPValue is not used correctly\n";
-          return false;
-        }
-        break;
       case VPInstruction::LastActiveLane:
         if (!verifyLastActiveLaneRecipe(*VPI))
           return false;
@@ -569,9 +470,9 @@ bool VPlanVerifier::verify(const VPlan &Plan) {
   return true;
 }
 
-bool llvm::verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate) {
+bool llvm::verifyVPlanIsValid(const VPlan &Plan) {
   VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
   VPTypeAnalysis TypeInfo(Plan);
-  VPlanVerifier Verifier(VPDT, TypeInfo, VerifyLate);
+  VPlanVerifier Verifier(VPDT, TypeInfo);
   return Verifier.verify(Plan);
 }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.h b/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
index ccf79e8e5c985..642b25b0635c0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
@@ -29,16 +29,14 @@
 namespace llvm {
 class VPlan;
 
-/// Verify invariants for general VPlans. If \p VerifyLate is passed, skip some
-/// checks that are not applicable at later stages of the transform pipeline.
+/// Verify invariants for general VPlans.
 /// Currently it checks the following:
 /// 1. Region/Block verification: Check the Region/Block verification
 /// invariants for every region in the H-CFG.
 /// 2. all phi-like recipes must be at the beginning of a block, with no other
 /// recipes in between. Note that currently there is still an exception for
 /// VPBlendRecipes.
-LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan,
-                                          bool VerifyLate = false);
+LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan);
 
 } // namespace llvm
 

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 19, 2026

@llvm/pr-subscribers-llvm-transforms

Author: Luke Lau (lukel97)

Changes

Currently if -vplan-verify-each is enabled and a pass fails the verifier, it will output the failure to stderr but will still finish with a zero exit code.

This adds an assert that the verification fails so that e.g. lit will pick up verifier failures in the in-tree tests with an EXPENSIVE_CHECKS build. However currently the verifier fails in several tests, so this also includes several fixes:

  1. Remove the EVL verifier checks. The EVL is used in quite a few more places than when the verification was originally added, and nowadays it gets used in a variety of VPInstructions, all of which need to be handled by the verifier. There are a few passes that fail today because we haven't updated the EVL verification. Now that the EVL transform has been split up into a variable stepping transform and an optimization pass it's generally less fragile, so there is less value in this verification.
  2. Extend the LastActiveLane verification to handle more prefix masks. All of the prefix masks that the verifier encounters are of the form icmp ult/ule monotonically-increasing-sequence, uniform, which always generate a prefix mask.
  3. Allow multiple VPActiveLaneMaskPHIRecipe recipes after unrolling. This also allows us to remove the verifyLate argument

Tested that llvm-test-suite + SPEC CPU 2017 now pass with -vplan-verify-each enabled for RISC-V.


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

4 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+2-3)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.h (+4-2)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp (+26-125)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanVerifier.h (+2-4)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 01433fe4c4ba7..68bdb9f4ba23f 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -364,7 +364,7 @@ cl::opt<bool>
                           cl::init(false),
 #endif
                           cl::Hidden,
-                          cl::desc("Verfiy VPlans after VPlan transforms."));
+                          cl::desc("Verify VPlans after VPlan transforms."));
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 cl::opt<bool> llvm::VPlanPrintAfterAll(
@@ -7512,8 +7512,7 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
                         State.CFG.PrevBB->getSingleSuccessor(), &BestVPlan);
   VPlanTransforms::removeDeadRecipes(BestVPlan);
 
-  assert(verifyVPlanIsValid(BestVPlan, true /*VerifyLate*/) &&
-         "final VPlan is invalid");
+  assert(verifyVPlanIsValid(BestVPlan) && "final VPlan is invalid");
 
   // After vectorization, the exit blocks of the original loop will have
   // additional predecessors. Invalidate SCEVs for the exit phis in case SE
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index f2dfc166cecc9..e35872bbdff37 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -72,8 +72,10 @@ struct VPlanTransforms {
           dbgs() << Plan << '\n';
       }
 #endif
-      if (VerifyEachVPlan && EnableVerify)
-        verifyVPlanIsValid(Plan);
+      if (VerifyEachVPlan && EnableVerify) {
+        [[maybe_unused]] bool IsValid = verifyVPlanIsValid(Plan);
+        assert(IsValid && "VPlan is invalid");
+      }
     }};
 
     return std::forward<PassTy>(Pass)(Plan, std::forward<ArgsTy>(Args)...);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
index e4b334c3eba49..2db7287d494f6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
@@ -31,7 +31,6 @@ namespace {
 class VPlanVerifier {
   const VPDominatorTree &VPDT;
   VPTypeAnalysis &TypeInfo;
-  bool VerifyLate;
 
   SmallPtrSet<BasicBlock *, 8> WrappedIRBBs;
 
@@ -40,11 +39,6 @@ class VPlanVerifier {
   // VPHeaderPHIRecipes.
   bool verifyPhiRecipes(const VPBasicBlock *VPBB);
 
-  /// Verify that \p EVL is used correctly. The user must be either in
-  /// EVL-based recipes as a last operand or VPInstruction::Add which is
-  /// incoming value into EVL's recipe.
-  bool verifyEVLRecipe(const VPInstruction &EVL) const;
-
   /// Verify that \p LastActiveLane's operand is guaranteed to be a prefix-mask.
   bool verifyLastActiveLaneRecipe(const VPInstruction &LastActiveLane) const;
 
@@ -67,9 +61,8 @@ class VPlanVerifier {
   bool verifyRegionRec(const VPRegionBlock *Region);
 
 public:
-  VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo,
-                bool VerifyLate)
-      : VPDT(VPDT), TypeInfo(TypeInfo), VerifyLate(VerifyLate) {}
+  VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo)
+      : VPDT(VPDT), TypeInfo(TypeInfo) {}
 
   bool verify(const VPlan &Plan);
 };
@@ -124,7 +117,7 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
     RecipeI++;
   }
 
-  if (!VerifyLate && NumActiveLaneMaskPhiRecipes > 1) {
+  if (!VPBB->getPlan()->isUnrolled() && NumActiveLaneMaskPhiRecipes > 1) {
     errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
     return false;
   }
@@ -146,106 +139,19 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
   return true;
 }
 
-bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
-  if (EVL.getOpcode() != VPInstruction::ExplicitVectorLength) {
-    errs() << "verifyEVLRecipe should only be called on "
-              "VPInstruction::ExplicitVectorLength\n";
-    return false;
-  }
-  auto VerifyEVLUse = [&](const VPRecipeBase &R,
-                          const unsigned ExpectedIdx) -> bool {
-    SmallVector<const VPValue *> Ops(R.operands());
-    unsigned UseCount = count(Ops, &EVL);
-    if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
-      errs() << "EVL is used as non-last operand in EVL-based recipe\n";
-      return false;
-    }
+static bool isKnownMonotonic(VPValue *V) {
+  VPValue *X, *Y;
+  if (match(V, m_Add(m_VPValue(X), m_VPValue(Y))))
+    return isKnownMonotonic(X) && isKnownMonotonic(Y);
+  if (match(V, m_StepVector()))
     return true;
-  };
-  auto VerifyEVLUseInVecEndPtr = [&EVL](auto &VEPRs) {
-    if (all_of(VEPRs, [&EVL](VPUser *U) {
-          auto *VEPR = cast<VPVectorEndPointerRecipe>(U);
-          return match(VEPR->getOffset(),
-                       m_c_Mul(m_SpecificSInt(VEPR->getStride()),
-                               m_Sub(m_Specific(&EVL), m_One())));
-        }))
-      return true;
-    errs() << "Expected VectorEndPointer with EVL operand\n";
-    return false;
-  };
-  return all_of(EVL.users(), [&](VPUser *U) {
-    return TypeSwitch<const VPUser *, bool>(U)
-        .Case([&](const VPWidenIntrinsicRecipe *S) {
-          return VerifyEVLUse(*S, S->getNumOperands() - 1);
-        })
-        .Case<VPWidenStoreEVLRecipe, VPReductionEVLRecipe,
-              VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe>(
-            [&](const VPRecipeBase *S) { return VerifyEVLUse(*S, 2); })
-        .Case([&](const VPScalarIVStepsRecipe *R) {
-          if (R->getNumOperands() != 3) {
-            errs() << "Unrolling with EVL tail folding not yet supported\n";
-            return false;
-          }
-          return VerifyEVLUse(*R, 2);
-        })
-        .Case<VPWidenLoadEVLRecipe, VPVectorEndPointerRecipe,
-              VPInterleaveEVLRecipe>(
-            [&](const VPRecipeBase *R) { return VerifyEVLUse(*R, 1); })
-        .Case(
-            [&](const VPInstructionWithType *S) { return VerifyEVLUse(*S, 0); })
-        .Case([&](const VPInstruction *I) {
-          if (I->getOpcode() == Instruction::PHI ||
-              I->getOpcode() == Instruction::ICmp)
-            return VerifyEVLUse(*I, 1);
-          if (I->getOpcode() == Instruction::Sub) {
-            // If Sub has a single user that's a SingleDefRecipe (which is
-            // expected to be a Mul), filter its users, in turn, to get
-            // VectorEndPointerRecipes, and verify that all the offsets match
-            // (EVL - 1) * Stride.
-            if (auto *Def = dyn_cast_if_present<VPSingleDefRecipe>(
-                    I->getSingleUser())) {
-              auto VEPRs = make_filter_range(Def->users(),
-                                             IsaPred<VPVectorEndPointerRecipe>);
-              if (!VEPRs.empty())
-                return VerifyEVLUseInVecEndPtr(VEPRs);
-            }
-            return VerifyEVLUse(*I, 1);
-          }
-          switch (I->getOpcode()) {
-          case Instruction::Add:
-            break;
-          case Instruction::UIToFP:
-          case Instruction::Trunc:
-          case Instruction::ZExt:
-          case Instruction::Mul:
-          case Instruction::Shl:
-          case Instruction::FMul:
-          case VPInstruction::Broadcast:
-          case VPInstruction::PtrAdd:
-            // Opcodes above can only use EVL after wide inductions have been
-            // expanded.
-            if (!VerifyLate) {
-              errs() << "EVL used by unexpected VPInstruction\n";
-              return false;
-            }
-            break;
-          default:
-            errs() << "EVL used by unexpected VPInstruction\n";
-            return false;
-          }
-          if (!VerifyLate &&
-              !isa<VPCurrentIterationPHIRecipe>(*I->users().begin())) {
-            errs() << "Result of VPInstruction::Add with EVL operand is "
-                      "not used by VPCurrentIterationPHIRecipe\n";
-            return false;
-          }
-          return true;
-        })
-        .Default([&](const VPUser *U) {
-          errs() << "EVL has unexpected user\n";
-          return false;
-        });
-  });
+  if (auto *WidenIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(V))
+    return match(WidenIV->getStepValue(), m_One());
+  if (auto *WidenIV = dyn_cast<VPScalarIVStepsRecipe>(V))
+    return match(WidenIV->getStepValue(), m_One());
+  if (isa<VPWidenCanonicalIVRecipe>(V))
+    return true;
+  return vputils::isUniformAcrossVFsAndUFs(V);
 }
 
 bool VPlanVerifier::verifyLastActiveLaneRecipe(
@@ -259,18 +165,19 @@ bool VPlanVerifier::verifyLastActiveLaneRecipe(
   }
 
   const VPlan &Plan = *LastActiveLane.getParent()->getPlan();
-  // All operands must be prefix-mask. Currently we check for header masks or
-  // EVL-derived masks, as those are currently the only operands in practice,
-  // but this may need updating in the future.
+  // All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
+  // the LHS is monotonically increasing and RHS is uniform.
   for (VPValue *Op : LastActiveLane.operands()) {
     if (vputils::isHeaderMask(Op, Plan))
       continue;
 
-    // Masks derived from EVL are also fine.
-    auto BroadcastOrEVL =
-        m_CombineOr(m_Broadcast(m_EVL(m_VPValue())), m_EVL(m_VPValue()));
-    if (match(Op, m_CombineOr(m_ICmp(m_StepVector(), BroadcastOrEVL),
-                              m_ICmp(BroadcastOrEVL, m_StepVector()))))
+    CmpPredicate Pred;
+    VPValue *LHS, *RHS;
+    if (match(Op, m_ICmp(Pred, m_VPValue(LHS), m_VPValue(RHS))) &&
+        (Pred == CmpInst::ICMP_ULE || Pred == CmpInst::ICMP_ULT) &&
+        isKnownMonotonic(LHS) &&
+        (vputils::isUniformAcrossVFsAndUFs(RHS) ||
+         vputils::isSingleScalar(RHS)))
       continue;
 
     errs() << "LastActiveLane operand ";
@@ -372,12 +279,6 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
     }
     if (const auto *VPI = dyn_cast<VPInstruction>(&R)) {
       switch (VPI->getOpcode()) {
-      case VPInstruction::ExplicitVectorLength:
-        if (!verifyEVLRecipe(*VPI)) {
-          errs() << "EVL VPValue is not used correctly\n";
-          return false;
-        }
-        break;
       case VPInstruction::LastActiveLane:
         if (!verifyLastActiveLaneRecipe(*VPI))
           return false;
@@ -569,9 +470,9 @@ bool VPlanVerifier::verify(const VPlan &Plan) {
   return true;
 }
 
-bool llvm::verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate) {
+bool llvm::verifyVPlanIsValid(const VPlan &Plan) {
   VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
   VPTypeAnalysis TypeInfo(Plan);
-  VPlanVerifier Verifier(VPDT, TypeInfo, VerifyLate);
+  VPlanVerifier Verifier(VPDT, TypeInfo);
   return Verifier.verify(Plan);
 }
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.h b/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
index ccf79e8e5c985..642b25b0635c0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.h
@@ -29,16 +29,14 @@
 namespace llvm {
 class VPlan;
 
-/// Verify invariants for general VPlans. If \p VerifyLate is passed, skip some
-/// checks that are not applicable at later stages of the transform pipeline.
+/// Verify invariants for general VPlans.
 /// Currently it checks the following:
 /// 1. Region/Block verification: Check the Region/Block verification
 /// invariants for every region in the H-CFG.
 /// 2. all phi-like recipes must be at the beginning of a block, with no other
 /// recipes in between. Note that currently there is still an exception for
 /// VPBlendRecipes.
-LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan,
-                                          bool VerifyLate = false);
+LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan);
 
 } // namespace llvm
 

Comment on lines +75 to +77
if (VerifyEachVPlan && EnableVerify) {
[[maybe_unused]] bool IsValid = verifyVPlanIsValid(Plan);
assert(IsValid && "VPlan is invalid");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the verifier also works in release builds, can we just always exit on failure?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched to report_fatal_error in 9401b48. I copied the same error format from the IR verifier.

Copy link
Copy Markdown
Contributor

@eas eas left a comment

Choose a reason for hiding this comment

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

Nothing else from me, thanks!

Comment on lines +144 to +145
if (match(V, m_Add(m_VPValue(X), m_VPValue(Y))))
return isKnownMonotonic(X) && isKnownMonotonic(Y);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this would also need to check that the Add is NUW, if it would wrap it would not be monotonic, even if both operands are

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in db8dbb3

Copy link
Copy Markdown
Contributor Author

@lukel97 lukel97 Feb 24, 2026

Choose a reason for hiding this comment

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

Looks like this actually causes verifier failures in test/Transforms/LoopVectorize/first-order-recurrence-tail-folding.ll, %10 is used as a prefix mask in a lastactivelane but %step.add doesn't have unsigned wrap:

# | VPlan 'Initial VPlan for VF={2},UF={2}' {
# | Live-in vp<%0> = VF
# | Live-in vp<%1> = VF * UF
# | Live-in vp<%2> = vector-trip-count
# | Live-in vp<%3> = backedge-taken count
# | Live-in ir<%n> = original trip-count
# | 
# | ir-bb<entry>:
# |   EMIT branch-on-cond ir<false>
# | Successor(s): scalar.ph, vector.ph
# | 
# | vector.ph:
# |   EMIT vp<%5> = wide-iv-step vp<%0>, ir<1>
# | Successor(s): vector loop
# | 
# | <x1> vector loop: {
# |   vector.body:
# |     EMIT vp<%6> = CANONICAL-INDUCTION ir<0>, vp<%index.next>
# |     ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<%0>, vp<%5>, vp<%step.add>
# |     EMIT vp<%step.add> = add ir<%iv>, vp<%5>
# |     EMIT vp<%10> = icmp ule vp<%step.add>, vp<%3>

Will take a look to see if we're missing a nuw on the step.add from unrolling.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

would be good to add a test case; in general, if the wide IV had nuw, I * think* that should also be preserve-able for the steps, and if it was canonical

Copy link
Copy Markdown
Contributor Author

@lukel97 lukel97 Feb 24, 2026

Choose a reason for hiding this comment

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

I think so too. However I'm noticing we actually drop the nuw on the wide IV after #163538. I believe the original reasoning was that with tail folding we might end up with poison lanes because the VTC > TC. But I don't think those lanes are ever used anyway. They're used for computing the header mask, which can't have any poison lanes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went down a bit of a rabbit hole here. IIUC we check for the canonical IV overflowing with tail folding because vscale can be a non-power-of-2.

AFAIK the plan is to remove non-power-of-2 vscales in #145098, and if that lands we can remove all the overflow checks so the increments will always have NUW.

Until then I think it's quite tricky to infer NUW. Can we relax the NUW check here and add a TODO to add it back if/when #145098 lands?


assert(verifyVPlanIsValid(BestVPlan, true /*VerifyLate*/) &&
"final VPlan is invalid");
assert(verifyVPlanIsValid(BestVPlan) && "final VPlan is invalid");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How come this isn't also guarded by EnableVerify like in the vplan code? I was expecting something similar here:

  bool VPlanIsValid = verifyVPlanIsValid(BestVPlan);
  if (EnableVerify && !VPlanIsValid)
    report_fatal_error("Broken VPlan found, compilation aborted!");
  else
    assert(VPlanIsValid && "final VPlan is invalid");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is just an assert that verifies that the plan is valid at this specific point, independent of running the verifier after all transforms. This should mirror how verification is handled for LLVM IR verification

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But in a release build does the IR verifier report a fatal error for unverified IR? If so, then if we mirror that behaviour this should also be a fatal error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, verifyFunction for IR similarly just returns a boolean, instead of reporting a fatal error:

bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {

It is used in asserts so those won't raise a fatal error in release builds (e.g. the assert used in LV). If the verifier is enabled to run after each pass, that raises a fatal error.

// All operands must be prefix-mask. Currently we check for header masks or
// EVL-derived masks, as those are currently the only operands in practice,
// but this may need updating in the future.
// All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can the changes in this function be done in a separate PR or are they explicitly tied to the removal of the 'VerifyLate' parameter?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The VerifyLate parameter bit was split off and landed in #182799

lukel97 added a commit to lukel97/llvm-project that referenced this pull request Feb 23, 2026
In llvm#182254 we want to start aborting compilation when the verifier fails between passes, but currently we run into various EVL related failures.

The EVL is used in quite a few more places than when the verification was originally added, all of which need to be handled by the verifier. I think this is also exacerbated by the fact that many recipes nowadays are converted to concrete recipes later in the pipeline which duplicates the number of patterns we need to match.

The EVL transform itself has also changed much since its original implementation, i.e. non-trapping recipes don't use EVL (llvm#127180) and VP recipes are generated via pattern matching instead of unconditionally (llvm#155394), so I'm not sure if the verification is as relevant today.

Rather than try to add more patterns this PR removes the verification to reduce the maintainence cost. Split off from llvm#182254
lukel97 added a commit that referenced this pull request Feb 23, 2026
In #182254 we want to start aborting compilation when the verifier fails
between passes, but currently we run into various EVL related failures.

The EVL is used in quite a few more places than when the verification
was originally added, all of which need to be handled by the verifier. I
think this is also exacerbated by the fact that many recipes nowadays
are converted to concrete recipes later in the pipeline which duplicates
the number of patterns we need to match.

The EVL transform itself has also changed much since its original
implementation, i.e. non-trapping recipes don't use EVL (#127180) and VP
recipes are generated via pattern matching instead of unconditionally
(#155394), so I'm not sure if the verification is as relevant today.

Rather than try to add more patterns this PR removes the verification to
reduce the maintainence cost. Split off from #182254
@lukel97
Copy link
Copy Markdown
Contributor Author

lukel97 commented Feb 23, 2026

Rebased on the split off parts so now should only contain the report_fatal_error bit and the LastActiveLane fixes

@lukel97 lukel97 changed the title [VPlan] Assert vplan-verify-each result and get verifier passing [VPlan] Assert vplan-verify-each result and fix LastActiveLane verification Feb 23, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 23, 2026

🐧 Linux x64 Test Results

  • 170114 tests passed
  • 3085 tests skipped
  • 1 test failed

Failed Tests

(click on a test name to see its output)

lldb-api

lldb-api.tools/lldb-dap/progress/TestDAP_Progress.py
Script:
--
/usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --libcxx-include-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/c++/v1 --libcxx-include-target-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/x86_64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/x86_64-unknown-linux-gnu --arch x86_64 --build-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex --lldb-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lldb --compiler /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang --dsymutil /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/progress -p TestDAP_Progress.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 23.0.0git (https://github.com/llvm/llvm-project revision 78424159af1f97ae930bc4574ccb422becec5703)
  clang revision 78424159af1f97ae930bc4574ccb422becec5703
  llvm revision 78424159af1f97ae930bc4574ccb422becec5703
Skipping the following test categories: msvcstl, dsym, pdb, gmodules, debugserver, objc

--
Command Output (stderr):
--
FAIL: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test (TestDAP_Progress.TestDAP_progress.test)
========= DEBUG ADAPTER PROTOCOL LOGS =========
[15:10:51.305] (stdio) --> {"command":"initialize","type":"request","arguments":{"adapterID":"lldb-native","clientID":"vscode","columnsStartAt1":true,"linesStartAt1":true,"locale":"en-us","pathFormat":"path","supportsRunInTerminalRequest":true,"supportsVariablePaging":true,"supportsVariableType":true,"supportsStartDebuggingRequest":true,"supportsProgressReporting":true,"supportsInvalidatedEvent":true,"supportsMemoryEvent":true,"$__lldb_sourceInitFile":false},"seq":1}
[15:10:51.305] DAP.cpp:986 (stdio) queued (command=initialize seq=1)
[15:10:51.305] (stdio) <-- {"body":{"$__lldb_version":"lldb version 23.0.0git (https://github.com/llvm/llvm-project revision 78424159af1f97ae930bc4574ccb422becec5703)\n  clang revision 78424159af1f97ae930bc4574ccb422becec5703\n  llvm revision 78424159af1f97ae930bc4574ccb422becec5703","completionTriggerCharacters":["."," ","\t"],"exceptionBreakpointFilters":[{"description":"C++ Catch","filter":"cpp_catch","label":"C++ Catch","supportsCondition":true},{"description":"C++ Throw","filter":"cpp_throw","label":"C++ Throw","supportsCondition":true},{"description":"Objective-C Catch","filter":"objc_catch","label":"Objective-C Catch","supportsCondition":true},{"description":"Objective-C Throw","filter":"objc_throw","label":"Objective-C Throw","supportsCondition":true}],"supportTerminateDebuggee":true,"supportsBreakpointLocationsRequest":true,"supportsCancelRequest":true,"supportsClipboardContext":true,"supportsCompletionsRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsDataBreakpointBytes":true,"supportsDataBreakpoints":true,"supportsDelayedStackTraceLoading":true,"supportsDisassembleRequest":true,"supportsEvaluateForHovers":true,"supportsExceptionFilterOptions":true,"supportsExceptionInfoRequest":true,"supportsFunctionBreakpoints":true,"supportsHitConditionalBreakpoints":true,"supportsInstructionBreakpoints":true,"supportsLogPoints":true,"supportsModuleSymbolsRequest":true,"supportsModulesRequest":true,"supportsReadMemoryRequest":true,"supportsSetVariable":true,"supportsSteppingGranularity":true,"supportsValueFormattingOptions":true,"supportsWriteMemoryRequest":true},"command":"initialize","request_seq":1,"seq":1,"success":true,"type":"response"}
[15:10:51.306] (stdio) --> {"seq":2,"command":"launch","type":"request","arguments":{"program":"/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/tools/lldb-dap/progress/TestDAP_Progress/a.out","stopOnEntry":true,"initCommands":["settings clear --all","settings set symbols.enable-external-lookup false","settings set target.inherit-tcc true","settings set target.disable-aslr false","settings set target.detach-on-error false","settings set target.auto-apply-fixits false","settings set plugin.process.gdb-remote.packet-timeout 60","settings set symbols.clang-modules-cache-path \"/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"","settings set use-color false","settings set show-statusline false"],"disableASLR":false,"enableAutoVariableSummaries":false,"enableSyntheticChildDebugging":false,"displayExtendedBacktrace":false}}
[15:10:51.306] DAP.cpp:986 (stdio) queued (command=launch seq=2)
[15:10:51.308] (stdio) <-- {"body":{"category":"console","output":"To get started with the debug console try \"<variable>\", \"<lldb-cmd>\" or \"help [<lldb-cmd>]\"\r\n"},"event":"output","seq":2,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"For more information visit https://lldb.llvm.org/use/lldbdap.html#debug-console.\r\n"},"event":"output","seq":3,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"Running initCommands:\n"},"event":"output","seq":4,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings clear --all\n"},"event":"output","seq":5,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set symbols.enable-external-lookup false\n"},"event":"output","seq":6,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set target.inherit-tcc true\n"},"event":"output","seq":7,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set target.disable-aslr false\n"},"event":"output","seq":8,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set target.detach-on-error false\n"},"event":"output","seq":9,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set target.auto-apply-fixits false\n"},"event":"output","seq":10,"type":"event"}
[15:10:51.309] (stdio) --> {"command":"threads","type":"request","arguments":{},"seq":3}
[15:10:51.309] DAP.cpp:986 (stdio) queued (command=threads seq=3)
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set plugin.process.gdb-remote.packet-timeout 60\n"},"event":"output","seq":11,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set symbols.clang-modules-cache-path \"/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"\n"},"event":"output","seq":12,"type":"event"}
[15:10:51.309] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set use-color false\n"},"event":"output","seq":13,"type":"event"}
[15:10:51.310] (stdio) <-- {"body":{"category":"console","output":"(lldb) settings set show-statusline false\n"},"event":"output","seq":14,"type":"event"}
[15:10:51.387] (stdio) <-- {"body":{"module":{"addressRange":"0x786c40842000","id":"520E0587-8220-FB2F-C6D2-8FF46B63B3FD-5D48E763","name":"ld-linux-x86-64.so.2","path":"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2","symbolStatus":"Symbols not found."},"reason":"new"},"event":"module","seq":15,"type":"event"}
[15:10:51.388] (stdio) <-- {"body":{"module":{"addressRange":"0x7ffcffb4a000","id":"91F0FB93-74C4-4772-3EAC-08FF58577788-4B129CA7","name":"[vdso]","path":"[vdso]","symbolStatus":"Symbols not found."},"reason":"new"},"event":"module","seq":16,"type":"event"}
[15:10:51.388] (stdio) <-- {"body":{"module":{"addressRange":"0x5837e85fc000","debugInfoSize":"1.1KB","id":"E2FD2B30","name":"a.out","path":"/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/tools/lldb-dap/progress/TestDAP_Progress/a.out","symbolFilePath":"/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/tools/lldb-dap/progress/TestDAP_Progress/a.out","symbolStatus":"Symbols loaded."},"reason":"new"},"event":"module","seq":17,"type":"event"}
[15:10:51.394] (stdio) <-- {"body":{"$__lldb_statistics":{"commands":"{\"settings clear\":1}","memory":"{\"strings\":{\"bytesTotal\":1048576,\"bytesUnused\":791227,\"bytesUsed\":257349}}","plugins":"{\"abi\":[{\"enabled\":true,\"name\":\"SysV-arm64\"},{\"enabled\":true,\"name\":\"ABIMacOSX_arm64\"},{\"enabled\":true,\"name\":\"SysV-arm\"},{\"enabled\":true,\"name\":\"macosx-arm\"},{\"enabled\":true,\"name\":\"sysv-hexagon\"},{\"enabled\":true,\"name\":\"sysv-loongarch\"},{\"enabled\":true,\"name\":\"sysv-mips\"},{\"enabled\":true,\"name\":\"sysv-mips64\"},{\"enabled\":true,\"name\":\"sysv-msp430\"},{\"enabled\":true,\"name\":\"sysv-ppc\"},{\"enabled\":true,\"name\":\"sysv-ppc64\"},{\"enabled\":true,\"name\":\"sysv-riscv\"},{\"enabled\":true,\"name\":\"sysv-s390x\"},{\"enabled\":true,\"name\":\"abi.macosx-i386\"},{\"enabled\":true,\"name\":\"sysv-i386\"},{\"enabled\":true,\"name\":\"sysv-x86_64\"},{\"enabled\":true,\"name\":\"windows-x86_64\"}],\"architecture\":[{\"enabled\":true,\"name\":\"arm\"},{\"enabled\":true,\"name\":\"mips\"},{\"enabled\":true,\"name\":\"ppc64\"},{\"enabled\":true,\"name\":\"aarch64\"}],\"disassembler\":[{\"enabled\":true,\"name\":\"llvm-mc\"}],\"dynamic-loader\":[{\"enabled\":true,\"name\":\"darwin-kernel\"},{\"enabled\":true,\"name\":\"freebsd-kernel\"},{\"enabled\":true,\"name\":\"macosx-dyld\"},{\"enabled\":true,\"name\":\"macos-dyld\"},{\"enabled\":true,\"name\":\"posix-dyld\"},{\"enabled\":true,\"name\":\"static\"},{\"enabled\":true,\"name\":\"hexagon-dyld\"},{\"enabled\":true,\"name\":\"windows-dyld\"},{\"enabled\":true,\"name\":\"wasm-dyld\"}],\"emulate-instruction\":[{\"enabled\":true,\"name\":\"arm\"},{\"enabled\":true,\"name\":\"arm64\"},{\"enabled\":true,\"name\":\"LoongArch\"},{\"enabled\":true,\"name\":\"mips32\"},{\"enabled\":true,\"name\":\"mips64\"},{\"enabled\":true,\"name\":\"ppc64\"},{\"enabled\":true,\"name\":\"riscv\"}],\"instrumentation-runtime\":[{\"enabled\":true,\"name\":\"AddressSanitizer\"},{\"enabled\":true,\"name\":\"Libsanitizers-ASan\"},{\"enabled\":true,\"name\":\"BoundsSafety\"},{\"enabled\":true,\"name\":\"MainThreadChecker\"},{\"enabled\":true,\"name\":\"ThreadSanitizer\"},{\"enabled\":true,\"name\":\"UndefinedBehaviorSanitizer\"}],\"jit-loader\":[{\"enabled\":true,\"name\":\"gdb\"}],\"language\":[{\"enabled\":true,\"name\":\"cplusplus\"},{\"enabled\":true,\"name\":\"objc\"},{\"enabled\":true,\"name\":\"objcplusplus\"}],\"language-runtime\":[{\"enabled\":true,\"name\":\"itanium\"},{\"enabled\":true,\"name\":\"apple-objc-v2\"},{\"enabled\":true,\"name\":\"apple-objc-v1\"},{\"enabled\":true,\"name\":\"gnustep-objc-libobjc2\"}],\"memory-history\":[{\"enabled\":true,\"name\":\"asan\"}],\"object-container\":[{\"enabled\":true,\"name\":\"bsd-archive\"},{\"enabled\":true,\"name\":\"big-archive\"},{\"enabled\":true,\"name\":\"mach-o\"},{\"enabled\":true,\"name\":\"mach-o-fileset\"}],\"object-file\":[{\"enabled\":true,\"name\":\"breakpad\"},{\"enabled\":true,\"name\":\"COFF\"},{\"enabled\":true,\"name\":\"elf\"},{\"enabled\":true,\"name\":\"JSON\"},{\"enabled\":true,\"name\":\"mach-o\"},{\"enabled\":true,\"name\":\"minidump\"},{\"enabled\":true,\"name\":\"pdb\"},{\"enabled\":true,\"name\":\"pe-coff\"},{\"enabled\":true,\"name\":\"xcoff\"},{\"enabled\":true,\"name\":\"wasm\"}],\"operating-system\":[{\"enabled\":true,\"name\":\"python\"}],\"platform\":[{\"enabled\":true,\"name\":\"remote-AIX\"},{\"enabled\":true,\"name\":\"remote-linux\"},{\"enabled\":true,\"name\":\"remote-android\"},{\"enabled\":true,\"name\":\"remote-freebsd\"},{\"enabled\":true,\"name\":\"remote-gdb-server\"},{\"enabled\":true,\"name\":\"darwin\"},{\"enabled\":true,\"name\":\"remote-ios\"},{\"enabled\":true,\"name\":\"remote-macosx\"},{\"enabled\":true,\"name\":\"host\"},{\"enabled\":true,\"name\":\"remote-netbsd\"},{\"enabled\":true,\"name\":\"remote-openbsd\"},{\"enabled\":true,\"name\":\"qemu-user\"},{\"enabled\":true,\"name\":\"wasm\"},{\"enabled\":true,\"name\":\"remote-windows\"}],\"process\":[{\"enabled\":true,\"name\":\"ScriptedProcess\"},{\"enabled\":true,\"name\":\"elf-core\"},{\"enabled\":true,\"name\":\"mach-o-core\"},{\"enabled\":true,\"name\":\"minidump\"},{\"enabled\":true,\"name\":\"wasm\"},{\"enabled\":true,\"name\":\"gdb-remote\"}],\"register-type-builder\":[{\"enabled\":true,\"name\":\"register-types-clang\"}],\"repl\":[{\"enabled\":true,\"name\":\"ClangREPL\"}],\"script-interpreter\":[{\"enabled\":true,\"name\":\"script-none\"},{\"enabled\":true,\"name\":\"script-python\"}],\"scripted-interface\":[{\"enabled\":true,\"name\":\"OperatingSystemPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedPlatformPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedProcessPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedStopHookPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedBreakpointPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedThreadPlanPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedFrameProviderPythonInterface\"}],\"structured-data\":[{\"enabled\":true,\"name\":\"darwin-log\"}],\"symbol-file\":[{\"enabled\":true,\"name\":\"breakpad\"},{\"enabled\":true,\"name\":\"CTF\"},{\"enabled\":true,\"name\":\"dwarf\"},{\"enabled\":true,\"name\":\"dwarf-debugmap\"},{\"enabled\":true,\"name\":\"JSON\"},{\"enabled\":true,\"name\":\"native-pdb\"},{\"enabled\":true,\"name\":\"pdb\"},{\"enabled\":true,\"name\":\"symtab\"}],\"symbol-locator\":[{\"enabled\":true,\"name\":\"debuginfod\"},{\"enabled\":true,\"name\":\"Default\"}],\"symbol-vendor\":[{\"enabled\":true,\"name\":\"ELF\"},{\"enabled\":true,\"name\":\"PE-COFF\"},{\"enabled\":true,\"name\":\"WASM\"}],\"system-runtime\":[{\"enabled\":true,\"name\":\"systemruntime-macosx\"}],\"trace-exporter\":[{\"enabled\":true,\"name\":\"ctf\"}],\"type-system\":[{\"enabled\":true,\"name\":\"clang\"}],\"unwind-assembly\":[{\"enabled\":true,\"name\":\"inst-emulation\"},{\"enabled\":true,\"name\":\"x86\"}]}","targets":"[{\"breakpoints\":[{\"details\":{\"Breakpoint\":{\"BKPTOptions\":{\"AutoContinue\":false,\"ConditionText\":\"\",\"EnabledState\":true,\"IgnoreCount\":0,\"OneShotState\":false},\"BKPTResolver\":{\"Options\":{\"Language\":\"c\",\"NameMask\":[4,4,4,4,4,4],\"Offset\":0,\"SkipPrologue\":false,\"SymbolNames\":[\"_dl_debug_state\",\"rtld_db_dlactivity\",\"__dl_rtld_db_dlactivity\",\"r_debug_state\",\"_r_debug_state\",\"_rtld_debug_state\"]},\"Type\":\"SymbolName\"},\"Hardware\":false,\"SearchFilter\":{\"Options\":{\"ModuleList\":[\"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2\"]},\"Type\":\"Modules\"}}},\"hitCount\":0,\"id\":-1,\"internal\":true,\"kindDescription\":\"shared-library-event\",\"numLocations\":1,\"numResolvedLocations\":1,\"resolveTime\":0.000193}],\"dyldPluginName\":\"posix-dyld\",\"expressionEvaluation\":{\"failures\":0,\"successes\":0},\"firstStopTime\":0.054963007000000001,\"frameVariable\":{\"failures\":0,\"successes\":0},\"launchOrAttachTime\":0.045623991000000003,\"moduleIdentifiers\":[572814848,569528896,570285120],\"signals\":[{\"SIGSTOP\":1}],\"sourceMapDeduceCount\":0,\"sourceRealpathAttemptCount\":0,\"sourceRealpathCompatibleCount\":0,\"stopCount\":1,\"summaryProviderStatistics\":[],\"targetCreateTime\":0.020844000000000001,\"totalBreakpointResolveTime\":0.000193,\"totalSharedLibraryEventHitCount\":0}]","totalDebugInfoByteSize":1078,"totalDebugInfoEnabled":1,"totalDebugInfoIndexLoadedFromCache":0,"totalDebugInfoIndexSavedToCache":0,"totalDebugInfoIndexTime":0.017958999999999999,"totalDebugInfoParseTime":4.5000000000000003e-05,"totalDwoErrorCount":0,"totalDwoFileCount":0,"totalLoadedDwoFileCount":0,"totalModuleCount":3,"totalModuleCountHasDebugInfo":1,"totalModuleCountWithIncompleteTypes":0,"totalModuleCountWithVariableErrors":0,"totalSymbolLocatorTime":"{\"Default\":0.0051790000000000004,\"debuginfod\":1.9999999999999999e-06}","totalSymbolTableIndexTime":7.1000000000000005e-05,"totalSymbolTableParseTime":0.0014239999999999999,"totalSymbolTableStripped":0,"totalSymbolTableSymbolCount":356,"totalSymbolTablesLoaded":3,"totalSymbolTablesLoadedFromCache":0,"totalSymbolTablesSavedToCache":0}},"event":"initialized","seq":18,"type":"event"}
[15:10:51.394] (stdio) <-- {"body":{"threads":[{"id":1576288,"name":"a.out"}]},"command":"threads","request_seq":3,"seq":19,"success":true,"type":"response"}
[15:10:51.394] (stdio) --> {"command":"stackTrace","type":"request","arguments":{"threadId":1576288,"startFrame":0,"levels":1},"seq":4}
[15:10:51.394] DAP.cpp:986 (stdio) queued (command=stackTrace seq=4)
[15:10:51.398] (stdio) <-- {"body":{"stackFrames":[{"column":1,"id":524288,"instructionPointerReference":"0x786C40861540","line":163,"moduleId":"520E0587-8220-FB2F-C6D2-8FF46B63B3FD-5D48E763","name":"___lldb_unnamed_symbol_1f270","source":{"name":"___lldb_unnamed_symbol_1f270","path":"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2`___lldb_unnamed_symbol_1f270","presentationHint":"deemphasize","sourceReference":1}}],"totalFrames":21},"command":"stackTrace","request_seq":4,"seq":20,"success":true,"type":"response"}
[15:10:51.399] (stdio) --> {"command":"evaluate","type":"request","arguments":{"expression":"`command script import /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py","frameId":524288,"context":"repl"},"seq":5}
[15:10:51.399] DAP.cpp:986 (stdio) queued (command=evaluate seq=5)
[15:10:51.459] (stdio) <-- {"body":{"category":"console","output":"The \"test-progress\" command has been installed, type \"help test-progress\" or \"test-progress --help\" for detailed help.\n"},"event":"output","seq":21,"type":"event"}
[15:10:51.460] (stdio) <-- {"body":{"result":"","variablesReference":0},"command":"evaluate","request_seq":5,"seq":22,"success":true,"type":"response"}
[15:10:51.460] (stdio) --> {"command":"stackTrace","type":"request","arguments":{"threadId":1576288,"startFrame":0,"levels":1},"seq":6}
[15:10:51.460] DAP.cpp:986 (stdio) queued (command=stackTrace seq=6)
[15:10:51.460] (stdio) <-- {"body":{"stackFrames":[{"column":1,"id":524288,"instructionPointerReference":"0x786C40861540","line":163,"moduleId":"520E0587-8220-FB2F-C6D2-8FF46B63B3FD-5D48E763","name":"___lldb_unnamed_symbol_1f270","source":{"name":"___lldb_unnamed_symbol_1f270","path":"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2`___lldb_unnamed_symbol_1f270","presentationHint":"deemphasize","sourceReference":1}}],"totalFrames":21},"command":"stackTrace","request_seq":6,"seq":23,"success":true,"type":"response"}
[15:10:51.460] (stdio) --> {"command":"evaluate","type":"request","arguments":{"expression":"`test-progress --total 3 --seconds 1","frameId":524288,"context":"repl"},"seq":7}
[15:10:51.461] DAP.cpp:986 (stdio) queued (command=evaluate seq=7)
[15:10:51.554] (stdio) <-- {"body":{"progressId":"1","timestamp":"1772032251.311965942"},"event":"progressEnd","seq":24,"type":"event"}
[15:10:52.461] (stdio) <-- {"body":{"cancellable":false,"percentage":0,"progressId":"11","timestamp":"1772032251.461582899","title":"Progress tester"},"event":"progressStart","seq":25,"type":"event"}
[15:10:52.461] (stdio) <-- {"body":{"message":"Step 2","percentage":66,"progressId":"11","timestamp":"1772032252.461742401"},"event":"progressUpdate","seq":26,"type":"event"}
[15:10:53.461] (stdio) <-- {"body":{"percentage":100,"progressId":"11","timestamp":"1772032253.461928368"},"event":"progressEnd","seq":27,"type":"event"}
[15:10:53.462] (stdio) <-- {"body":{"result":"","variablesReference":0},"command":"evaluate","request_seq":7,"seq":28,"success":true,"type":"response"}
[15:10:53.462] (stdio) --> {"command":"stackTrace","type":"request","arguments":{"threadId":1576288,"startFrame":0,"levels":1},"seq":8}
[15:10:53.462] DAP.cpp:986 (stdio) queued (command=stackTrace seq=8)
[15:10:53.463] (stdio) <-- {"body":{"stackFrames":[{"column":1,"id":524288,"instructionPointerReference":"0x786C40861540","line":163,"moduleId":"520E0587-8220-FB2F-C6D2-8FF46B63B3FD-5D48E763","name":"___lldb_unnamed_symbol_1f270","source":{"name":"___lldb_unnamed_symbol_1f270","path":"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2`___lldb_unnamed_symbol_1f270","presentationHint":"deemphasize","sourceReference":1}}],"totalFrames":21},"command":"stackTrace","request_seq":8,"seq":29,"success":true,"type":"response"}
[15:10:53.463] (stdio) --> {"command":"evaluate","type":"request","arguments":{"expression":"`test-progress --total 3 --seconds 1 --no-details","frameId":524288,"context":"repl"},"seq":9}
[15:10:53.463] DAP.cpp:986 (stdio) queued (command=evaluate seq=9)
[15:10:54.464] (stdio) <-- {"body":{"cancellable":false,"percentage":0,"progressId":"12","timestamp":"1772032253.464137554","title":"Progress tester"},"event":"progressStart","seq":30,"type":"event"}
[15:10:54.464] (stdio) <-- {"body":{"message":"Initial Detail","percentage":66,"progressId":"12","timestamp":"1772032254.464332581"},"event":"progressUpdate","seq":31,"type":"event"}
[15:10:55.464] (stdio) <-- {"body":{"percentage":100,"progressId":"12","timestamp":"1772032255.464534760"},"event":"progressEnd","seq":32,"type":"event"}
[15:10:55.464] (stdio) <-- {"body":{"result":"","variablesReference":0},"command":"evaluate","request_seq":9,"seq":33,"success":true,"type":"response"}
[15:10:55.465] (stdio) --> {"command":"stackTrace","type":"request","arguments":{"threadId":1576288,"startFrame":0,"levels":1},"seq":10}
[15:10:55.465] DAP.cpp:986 (stdio) queued (command=stackTrace seq=10)
[15:10:55.465] (stdio) <-- {"body":{"stackFrames":[{"column":1,"id":524288,"instructionPointerReference":"0x786C40861540","line":163,"moduleId":"520E0587-8220-FB2F-C6D2-8FF46B63B3FD-5D48E763","name":"___lldb_unnamed_symbol_1f270","source":{"name":"___lldb_unnamed_symbol_1f270","path":"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2`___lldb_unnamed_symbol_1f270","presentationHint":"deemphasize","sourceReference":1}}],"totalFrames":21},"command":"stackTrace","request_seq":10,"seq":34,"success":true,"type":"response"}
[15:10:55.466] (stdio) --> {"command":"evaluate","type":"request","arguments":{"expression":"`test-progress --seconds 1","frameId":524288,"context":"repl"},"seq":11}
[15:10:55.466] DAP.cpp:986 (stdio) queued (command=evaluate seq=11)
[15:10:56.466] (stdio) <-- {"body":{"cancellable":false,"progressId":"13","timestamp":"1772032255.466711998","title":"Progress tester: Initial Indeterminate Detail"},"event":"progressStart","seq":35,"type":"event"}
[15:10:56.467] (stdio) <-- {"body":{"message":"Step 2","percentage":0,"progressId":"13","timestamp":"1772032256.466901779"},"event":"progressUpdate","seq":36,"type":"event"}
[15:10:57.467] (stdio) <-- {"body":{"result":"","variablesReference":0},"command":"evaluate","request_seq":11,"seq":37,"success":true,"type":"response"}
[15:10:57.468] (stdio) <-- {"body":{"progressId":"13","timestamp":"1772032257.468180180"},"event":"progressEnd","seq":38,"type":"event"}
[15:10:57.479] (stdio) --> {"command":"disconnect","type":"request","arguments":{"terminateDebuggee":true},"seq":12}
[15:10:57.479] DAP.cpp:986 (stdio) queued (command=disconnect seq=12)
[15:10:57.484] (stdio) <-- {"body":{"category":"console","output":"Process 1576288 exited with status = 9 (0x00000009) killed\n"},"event":"output","seq":39,"type":"event"}
[15:10:57.486] (stdio) <-- {"body":{"$__lldb_statistics":{"commands":"{\"command script add\":1,\"command script import\":1,\"settings clear\":1}","memory":"{\"strings\":{\"bytesTotal\":1053544,\"bytesUnused\":786930,\"bytesUsed\":266614}}","plugins":"{\"abi\":[{\"enabled\":true,\"name\":\"SysV-arm64\"},{\"enabled\":true,\"name\":\"ABIMacOSX_arm64\"},{\"enabled\":true,\"name\":\"SysV-arm\"},{\"enabled\":true,\"name\":\"macosx-arm\"},{\"enabled\":true,\"name\":\"sysv-hexagon\"},{\"enabled\":true,\"name\":\"sysv-loongarch\"},{\"enabled\":true,\"name\":\"sysv-mips\"},{\"enabled\":true,\"name\":\"sysv-mips64\"},{\"enabled\":true,\"name\":\"sysv-msp430\"},{\"enabled\":true,\"name\":\"sysv-ppc\"},{\"enabled\":true,\"name\":\"sysv-ppc64\"},{\"enabled\":true,\"name\":\"sysv-riscv\"},{\"enabled\":true,\"name\":\"sysv-s390x\"},{\"enabled\":true,\"name\":\"abi.macosx-i386\"},{\"enabled\":true,\"name\":\"sysv-i386\"},{\"enabled\":true,\"name\":\"sysv-x86_64\"},{\"enabled\":true,\"name\":\"windows-x86_64\"}],\"architecture\":[{\"enabled\":true,\"name\":\"arm\"},{\"enabled\":true,\"name\":\"mips\"},{\"enabled\":true,\"name\":\"ppc64\"},{\"enabled\":true,\"name\":\"aarch64\"}],\"disassembler\":[{\"enabled\":true,\"name\":\"llvm-mc\"}],\"dynamic-loader\":[{\"enabled\":true,\"name\":\"darwin-kernel\"},{\"enabled\":true,\"name\":\"freebsd-kernel\"},{\"enabled\":true,\"name\":\"macosx-dyld\"},{\"enabled\":true,\"name\":\"macos-dyld\"},{\"enabled\":true,\"name\":\"posix-dyld\"},{\"enabled\":true,\"name\":\"static\"},{\"enabled\":true,\"name\":\"hexagon-dyld\"},{\"enabled\":true,\"name\":\"windows-dyld\"},{\"enabled\":true,\"name\":\"wasm-dyld\"}],\"emulate-instruction\":[{\"enabled\":true,\"name\":\"arm\"},{\"enabled\":true,\"name\":\"arm64\"},{\"enabled\":true,\"name\":\"LoongArch\"},{\"enabled\":true,\"name\":\"mips32\"},{\"enabled\":true,\"name\":\"mips64\"},{\"enabled\":true,\"name\":\"ppc64\"},{\"enabled\":true,\"name\":\"riscv\"}],\"instrumentation-runtime\":[{\"enabled\":true,\"name\":\"AddressSanitizer\"},{\"enabled\":true,\"name\":\"Libsanitizers-ASan\"},{\"enabled\":true,\"name\":\"BoundsSafety\"},{\"enabled\":true,\"name\":\"MainThreadChecker\"},{\"enabled\":true,\"name\":\"ThreadSanitizer\"},{\"enabled\":true,\"name\":\"UndefinedBehaviorSanitizer\"}],\"jit-loader\":[{\"enabled\":true,\"name\":\"gdb\"}],\"language\":[{\"enabled\":true,\"name\":\"cplusplus\"},{\"enabled\":true,\"name\":\"objc\"},{\"enabled\":true,\"name\":\"objcplusplus\"}],\"language-runtime\":[{\"enabled\":true,\"name\":\"itanium\"},{\"enabled\":true,\"name\":\"apple-objc-v2\"},{\"enabled\":true,\"name\":\"apple-objc-v1\"},{\"enabled\":true,\"name\":\"gnustep-objc-libobjc2\"}],\"memory-history\":[{\"enabled\":true,\"name\":\"asan\"}],\"object-container\":[{\"enabled\":true,\"name\":\"bsd-archive\"},{\"enabled\":true,\"name\":\"big-archive\"},{\"enabled\":true,\"name\":\"mach-o\"},{\"enabled\":true,\"name\":\"mach-o-fileset\"}],\"object-file\":[{\"enabled\":true,\"name\":\"breakpad\"},{\"enabled\":true,\"name\":\"COFF\"},{\"enabled\":true,\"name\":\"elf\"},{\"enabled\":true,\"name\":\"JSON\"},{\"enabled\":true,\"name\":\"mach-o\"},{\"enabled\":true,\"name\":\"minidump\"},{\"enabled\":true,\"name\":\"pdb\"},{\"enabled\":true,\"name\":\"pe-coff\"},{\"enabled\":true,\"name\":\"xcoff\"},{\"enabled\":true,\"name\":\"wasm\"}],\"operating-system\":[{\"enabled\":true,\"name\":\"python\"}],\"platform\":[{\"enabled\":true,\"name\":\"remote-AIX\"},{\"enabled\":true,\"name\":\"remote-linux\"},{\"enabled\":true,\"name\":\"remote-android\"},{\"enabled\":true,\"name\":\"remote-freebsd\"},{\"enabled\":true,\"name\":\"remote-gdb-server\"},{\"enabled\":true,\"name\":\"darwin\"},{\"enabled\":true,\"name\":\"remote-ios\"},{\"enabled\":true,\"name\":\"remote-macosx\"},{\"enabled\":true,\"name\":\"host\"},{\"enabled\":true,\"name\":\"remote-netbsd\"},{\"enabled\":true,\"name\":\"remote-openbsd\"},{\"enabled\":true,\"name\":\"qemu-user\"},{\"enabled\":true,\"name\":\"wasm\"},{\"enabled\":true,\"name\":\"remote-windows\"}],\"process\":[{\"enabled\":true,\"name\":\"ScriptedProcess\"},{\"enabled\":true,\"name\":\"elf-core\"},{\"enabled\":true,\"name\":\"mach-o-core\"},{\"enabled\":true,\"name\":\"minidump\"},{\"enabled\":true,\"name\":\"wasm\"},{\"enabled\":true,\"name\":\"gdb-remote\"}],\"register-type-builder\":[{\"enabled\":true,\"name\":\"register-types-clang\"}],\"repl\":[{\"enabled\":true,\"name\":\"ClangREPL\"}],\"script-interpreter\":[{\"enabled\":true,\"name\":\"script-none\"},{\"enabled\":true,\"name\":\"script-python\"}],\"scripted-interface\":[{\"enabled\":true,\"name\":\"OperatingSystemPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedPlatformPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedProcessPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedStopHookPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedBreakpointPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedThreadPlanPythonInterface\"},{\"enabled\":true,\"name\":\"ScriptedFrameProviderPythonInterface\"}],\"structured-data\":[{\"enabled\":true,\"name\":\"darwin-log\"}],\"symbol-file\":[{\"enabled\":true,\"name\":\"breakpad\"},{\"enabled\":true,\"name\":\"CTF\"},{\"enabled\":true,\"name\":\"dwarf\"},{\"enabled\":true,\"name\":\"dwarf-debugmap\"},{\"enabled\":true,\"name\":\"JSON\"},{\"enabled\":true,\"name\":\"native-pdb\"},{\"enabled\":true,\"name\":\"pdb\"},{\"enabled\":true,\"name\":\"symtab\"}],\"symbol-locator\":[{\"enabled\":true,\"name\":\"debuginfod\"},{\"enabled\":true,\"name\":\"Default\"}],\"symbol-vendor\":[{\"enabled\":true,\"name\":\"ELF\"},{\"enabled\":true,\"name\":\"PE-COFF\"},{\"enabled\":true,\"name\":\"WASM\"}],\"system-runtime\":[{\"enabled\":true,\"name\":\"systemruntime-macosx\"}],\"trace-exporter\":[{\"enabled\":true,\"name\":\"ctf\"}],\"type-system\":[{\"enabled\":true,\"name\":\"clang\"}],\"unwind-assembly\":[{\"enabled\":true,\"name\":\"inst-emulation\"},{\"enabled\":true,\"name\":\"x86\"}]}","targets":"[{\"breakpoints\":[{\"details\":{\"Breakpoint\":{\"BKPTOptions\":{\"AutoContinue\":false,\"ConditionText\":\"\",\"EnabledState\":true,\"IgnoreCount\":0,\"OneShotState\":false},\"BKPTResolver\":{\"Options\":{\"Language\":\"c\",\"NameMask\":[4,4,4,4,4,4],\"Offset\":0,\"SkipPrologue\":false,\"SymbolNames\":[\"_dl_debug_state\",\"rtld_db_dlactivity\",\"__dl_rtld_db_dlactivity\",\"r_debug_state\",\"_r_debug_state\",\"_rtld_debug_state\"]},\"Type\":\"SymbolName\"},\"Hardware\":false,\"SearchFilter\":{\"Options\":{\"ModuleList\":[\"/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2\"]},\"Type\":\"Modules\"}}},\"hitCount\":0,\"id\":-1,\"internal\":true,\"kindDescription\":\"shared-library-event\",\"numLocations\":1,\"numResolvedLocations\":1,\"resolveTime\":0.000193}],\"dyldPluginName\":\"posix-dyld\",\"expressionEvaluation\":{\"failures\":0,\"successes\":0},\"firstStopTime\":0.054963007000000001,\"frameVariable\":{\"failures\":0,\"successes\":0},\"launchOrAttachTime\":0.045623991000000003,\"moduleIdentifiers\":[572814848,569528896,570285120],\"signals\":[{\"SIGSTOP\":1}],\"sourceMapDeduceCount\":0,\"sourceRealpathAttemptCount\":0,\"sourceRealpathCompatibleCount\":0,\"stopCount\":2,\"summaryProviderStatistics\":[],\"targetCreateTime\":0.020844000000000001,\"totalBreakpointResolveTime\":0.000193,\"totalSharedLibraryEventHitCount\":0}]","totalDebugInfoByteSize":1078,"totalDebugInfoEnabled":1,"totalDebugInfoIndexLoadedFromCache":0,"totalDebugInfoIndexSavedToCache":0,"totalDebugInfoIndexTime":0.017958999999999999,"totalDebugInfoParseTime":4.5000000000000003e-05,"totalDwoErrorCount":0,"totalDwoFileCount":0,"totalLoadedDwoFileCount":0,"totalModuleCount":3,"totalModuleCountHasDebugInfo":1,"totalModuleCountWithIncompleteTypes":0,"totalModuleCountWithVariableErrors":0,"totalSymbolLocatorTime":"{\"Default\":0.0051790000000000004,\"debuginfod\":1.9999999999999999e-06}","totalSymbolTableIndexTime":7.1000000000000005e-05,"totalSymbolTableParseTime":0.0014239999999999999,"totalSymbolTableStripped":0,"totalSymbolTableSymbolCount":356,"totalSymbolTablesLoaded":3,"totalSymbolTablesLoadedFromCache":0,"totalSymbolTablesSavedToCache":0}},"event":"terminated","seq":40,"type":"event"}
[15:10:57.486] (stdio) <-- {"command":"disconnect","request_seq":12,"seq":41,"success":true,"type":"response"}
[15:10:57.486] DAP.cpp:1005 (stdio) transport closed
[15:10:57.486] (stdio) <-- {"body":{"exitCode":9},"event":"exited","seq":42,"type":"event"}

========= END =========
======================================================================
FAIL: test (TestDAP_Progress.TestDAP_progress.test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py", line 86, in test
    self.verify_progress_events(
  File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py", line 51, in verify_progress_events
    self.assertTrue(end_found)
AssertionError: False is not true
Config=x86_64-/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang
----------------------------------------------------------------------
Ran 1 test in 6.753s

FAILED (failures=1)

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

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

Thanks for splitting the changes off! I'll run this on some large test cases overnight to double-check there are no other verification issues this would highlight.

if (match(Op, m_ICmp(Pred, m_VPValue(LHS), m_VPValue(RHS))) &&
(Pred == CmpInst::ICMP_ULE || Pred == CmpInst::ICMP_ULT) &&
isKnownMonotonic(LHS) &&
(vputils::isUniformAcrossVFsAndUFs(RHS) ||
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the only case that it missing from vputils::isUniformAcrossVFsAndUFs(RHS) EVL? Should EVL be considered uniform-across-VF-and-UFs? Currently we never unroll with EVL so that should be fine I think

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah it's just EVL. I think it would be nice to avoid having the UF = 1 invariant in isUniformAcrossVFsAndUFs for EVL though. I just restricted the isSingleScalar to EVL in the verifier instead in b503231 if that works for you

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

LGTM, thanks

// EVL-derived masks, as those are currently the only operands in practice,
// but this may need updating in the future.
// All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
// the LHS is monotonically increasing and RHS is uniform.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// the LHS is monotonically increasing and RHS is uniform.
// the LHS is monotonically increasing and RHS is uniform across VF and UF.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 0f62428

Comment on lines +76 to +77
if (!verifyVPlanIsValid(Plan))
report_fatal_error("Broken VPlan found, compilation aborted!");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If possible, it may be good to add a C++ unit test that passes an invalid VPlan to a transform invoked via the macro, to add test coverage for the reporting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 0f62428

@lukel97 lukel97 enabled auto-merge (squash) February 25, 2026 14:55
@lukel97 lukel97 disabled auto-merge February 25, 2026 17:49
@lukel97 lukel97 merged commit a8f5f4a into llvm:main Feb 25, 2026
9 of 10 checks passed
sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
…cation (llvm#182254)

Currently if -vplan-verify-each is enabled and a pass fails the
verifier, it will output the failure to stderr but will still finish
with a zero exit code.

This adds an assert that the verification fails so that e.g. lit will
pick up verifier failures in the in-tree tests with an EXPENSIVE_CHECKS
build.

Currently the LastActiveLane verification fails in several tests, so
this also includes a fix to handle more prefix masks. All of the prefix
masks that the verifier encounters are of the form `icmp ult/ule
monotonically-increasing-sequence, uniform`, which always generate a
prefix mask.

Tested that llvm-test-suite + SPEC CPU 2017 now pass with
-vplan-verify-each enabled for RISC-V.
HendrikHuebner pushed a commit to HendrikHuebner/llvm-project that referenced this pull request Mar 10, 2026
In llvm#182254 we want to start aborting compilation when the verifier fails
between passes, but currently we run into various EVL related failures.

The EVL is used in quite a few more places than when the verification
was originally added, all of which need to be handled by the verifier. I
think this is also exacerbated by the fact that many recipes nowadays
are converted to concrete recipes later in the pipeline which duplicates
the number of patterns we need to match.

The EVL transform itself has also changed much since its original
implementation, i.e. non-trapping recipes don't use EVL (llvm#127180) and VP
recipes are generated via pattern matching instead of unconditionally
(llvm#155394), so I'm not sure if the verification is as relevant today.

Rather than try to add more patterns this PR removes the verification to
reduce the maintainence cost. Split off from llvm#182254
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.

5 participants