From 1021a0ea618306a42e2b8b22e863692f1506d1e2 Mon Sep 17 00:00:00 2001 From: Vasileios Porpodas Date: Tue, 14 Jan 2025 13:43:37 -0800 Subject: [PATCH] [SandboxVec][Utils] Implement Utils::verifyFunction() This patch implements a wrapper function for the LLVM IR verifier for functions, and calls it (flag-guarded) within the bottom-up-vectorizer for finding IR bugs as soon as they happen. --- llvm/include/llvm/SandboxIR/Utils.h | 9 +++++++++ .../SandboxVectorizer/Passes/BottomUpVec.cpp | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h index d58fe52214395..5c6f0d9edd618 100644 --- a/llvm/include/llvm/SandboxIR/Utils.h +++ b/llvm/include/llvm/SandboxIR/Utils.h @@ -17,6 +17,8 @@ #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Verifier.h" +#include "llvm/SandboxIR/Function.h" #include "llvm/SandboxIR/Instruction.h" #include @@ -122,6 +124,13 @@ class Utils { const std::optional &OptLoc) { return BatchAA.getModRefInfo(cast(I->Val), OptLoc); } + + /// Equivalent to llvm::verifyFunction(). + /// \Returns true if the IR is broken. + static bool verifyFunction(const Function *F, raw_ostream &OS) { + const auto &LLVMF = *cast(F->Val); + return llvm::verifyFunction(LLVMF, &OS); + } }; } // namespace llvm::sandboxir diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp index 7cebde335cb4e..b3a477c64a5cc 100644 --- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp +++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp @@ -27,6 +27,13 @@ static cl::opt AllowNonPow2("sbvec-allow-non-pow2", cl::init(false), cl::Hidden, cl::desc("Allow non-power-of-2 vectorization.")); +#ifndef NDEBUG +static cl::opt + AlwaysVerify("sbvec-always-verify", cl::init(false), cl::Hidden, + cl::desc("Helps find bugs by verifying the IR whenever we " + "emit new instructions (*very* expensive).")); +#endif // NDEBUG + namespace sandboxir { BottomUpVec::BottomUpVec(StringRef Pipeline) @@ -365,6 +372,17 @@ Value *BottomUpVec::vectorizeRec(ArrayRef Bndl, break; } } +#ifndef NDEBUG + if (AlwaysVerify) { + // This helps find broken IR by constantly verifying the function. Note that + // this is very expensive and should only be used for debugging. + Instruction *I0 = isa(Bndl[0]) + ? cast(Bndl[0]) + : cast(UserBndl[0]); + assert(!Utils::verifyFunction(I0->getParent()->getParent(), dbgs()) && + "Broken function!"); + } +#endif return NewVec; }