[llvm] [LV] Added verification of EVL recipes (PR #107630)
Kolya Panchenko via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 6 12:00:24 PDT 2024
https://github.com/nikolaypanchenko created https://github.com/llvm/llvm-project/pull/107630
None
>From e83895e71ccbadc23906b0a3c52853b35b95d303 Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <kolya.panchenko at sifive.com>
Date: Fri, 6 Sep 2024 10:10:50 -0700
Subject: [PATCH] [LV] Added verification of EVL recipes
---
.../Transforms/Vectorize/VPlanVerifier.cpp | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
index 765dc983cab4fb..afdea0b9f93030 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
@@ -18,6 +18,7 @@
#include "VPlanDominatorTree.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
#define DEBUG_TYPE "loop-vectorize"
@@ -35,6 +36,11 @@ 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;
+
bool verifyVPBasicBlock(const VPBasicBlock *VPBB);
bool verifyBlock(const VPBlockBase *VPB);
@@ -114,6 +120,67 @@ 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;
+ }
+ return true;
+ };
+ for (const VPUser *U : EVL.users()) {
+ if (!TypeSwitch<const VPUser *, bool>(U)
+ .Case<VPWidenStoreEVLRecipe>([&](const VPWidenStoreEVLRecipe *S) {
+ return VerifyEVLUse(*S, 2);
+ })
+ .Case<VPWidenLoadEVLRecipe>([&](const VPWidenLoadEVLRecipe *L) {
+ return VerifyEVLUse(*L, 1);
+ })
+ .Case<VPWidenEVLRecipe>([&](const VPWidenEVLRecipe *W) {
+ return VerifyEVLUse(
+ *W, Instruction::isUnaryOp(W->getOpcode()) ? 1 : 2);
+ })
+ .Case<VPReductionEVLRecipe>([&](const VPReductionEVLRecipe *R) {
+ return VerifyEVLUse(*R, 2);
+ })
+ .Case<VPScalarCastRecipe>(
+ [&](const VPScalarCastRecipe *S) { return true; })
+ .Case<VPInstruction>([&](const VPInstruction *I) {
+ if (I->getOpcode() != Instruction::Add) {
+ errs()
+ << "EVL is used as an operand in non-VPInstruction::Add\n";
+ return false;
+ }
+ if (I->getNumUsers() != 1) {
+ errs() << "EVL is used in VPInstruction:Add with multiple "
+ "users\n";
+ return false;
+ }
+ if (!isa<VPEVLBasedIVPHIRecipe>(*I->users().begin())) {
+ errs() << "Result of VPInstruction::Add with EVL operand is "
+ "not used by VPEVLBasedIVPHIRecipe\n";
+ return false;
+ }
+ return true;
+ })
+ .Default([&](const VPUser *U) {
+ errs() << "EVL has unexpected user\n";
+ return false;
+ })) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
if (!verifyPhiRecipes(VPBB))
return false;
@@ -150,6 +217,13 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
}
}
}
+ if (const auto *EVL = dyn_cast<VPInstruction>(&R)) {
+ if (EVL->getOpcode() == VPInstruction::ExplicitVectorLength &&
+ !verifyEVLRecipe(*EVL)) {
+ errs() << "EVL VPValue is not used correctly\n";
+ return false;
+ }
+ }
}
auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
More information about the llvm-commits
mailing list