https://github.com/jofrn updated https://github.com/llvm/llvm-project/pull/123609
>From 210b6d80bcfbbcd216f98199df386280724561e2 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Mon, 20 Jan 2025 04:51:26 -0800 Subject: [PATCH 01/12] [TargetVerifier][AMDGPU] Add TargetVerifier. This pass verifies the IR for an individual backend. This is different than Lint because it consolidates all checks for a given backend in a single pass. A check for Lint may be undefined behavior across all targets, whereas a check in TargetVerifier would only pertain to the specified target but can check more than just undefined behavior such are IR validity. A use case of this would be to reject programs with invalid IR while fuzzing. --- llvm/include/llvm/IR/Module.h | 4 + llvm/include/llvm/Target/TargetVerifier.h | 82 +++++++ .../TargetVerify/AMDGPUTargetVerifier.h | 36 +++ llvm/lib/IR/Verifier.cpp | 18 +- .../Target/AMDGPU/AMDGPUTargetVerifier.cpp | 213 ++++++++++++++++++ llvm/lib/Target/AMDGPU/CMakeLists.txt | 1 + llvm/test/CodeGen/AMDGPU/tgt-verify.ll | 62 +++++ llvm/tools/llvm-tgt-verify/CMakeLists.txt | 34 +++ .../tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 172 ++++++++++++++ 9 files changed, 618 insertions(+), 4 deletions(-) create mode 100644 llvm/include/llvm/Target/TargetVerifier.h create mode 100644 llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h create mode 100644 llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp create mode 100644 llvm/test/CodeGen/AMDGPU/tgt-verify.ll create mode 100644 llvm/tools/llvm-tgt-verify/CMakeLists.txt create mode 100644 llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 91ccd76c41e07..03c0cf1cf0924 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -214,6 +214,10 @@ class LLVM_ABI Module { /// @name Constructors /// @{ public: + /// Is this Module valid as determined by one of the verification passes + /// i.e. Lint, Verifier, TargetVerifier. + bool IsValid = true; + /// Is this Module using intrinsics to record the position of debugging /// information, or non-intrinsic records? See IsNewDbgInfoFormat in /// \ref BasicBlock. diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h new file mode 100644 index 0000000000000..e00c6a7b260c9 --- /dev/null +++ b/llvm/include/llvm/Target/TargetVerifier.h @@ -0,0 +1,82 @@ +//===-- llvm/Target/TargetVerifier.h - LLVM IR Target Verifier ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines target verifier interfaces that can be used for some +// validation of input to the system, and for checking that transformations +// haven't done something bad. In contrast to the Verifier or Lint, the +// TargetVerifier looks for constructions invalid to a particular target +// machine. +// +// To see what specifically is checked, look at TargetVerifier.cpp or an +// individual backend's TargetVerifier. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_VERIFIER_H +#define LLVM_TARGET_VERIFIER_H + +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/TargetParser/Triple.h" + +namespace llvm { + +class Function; + +class TargetVerifierPass : public PassInfoMixin<TargetVerifierPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {} +}; + +class TargetVerify { +protected: + void WriteValues(ArrayRef<const Value *> Vs) { + for (const Value *V : Vs) { + if (!V) + continue; + if (isa<Instruction>(V)) { + MessagesStr << *V << '\n'; + } else { + V->printAsOperand(MessagesStr, true, Mod); + MessagesStr << '\n'; + } + } + } + + /// A check failed, so printout out the condition and the message. + /// + /// This provides a nice place to put a breakpoint if you want to see why + /// something is not correct. + void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; } + + /// A check failed (with values to print). + /// + /// This calls the Message-only version so that the above is easier to set + /// a breakpoint on. + template <typename T1, typename... Ts> + void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { + CheckFailed(Message); + WriteValues({V1, Vs...}); + } +public: + Module *Mod; + Triple TT; + + std::string Messages; + raw_string_ostream MessagesStr; + + TargetVerify(Module *Mod) + : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())), + MessagesStr(Messages) {} + + void run(Function &F) {}; +}; + +} // namespace llvm + +#endif // LLVM_TARGET_VERIFIER_H diff --git a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h new file mode 100644 index 0000000000000..e6ff57629b141 --- /dev/null +++ b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h @@ -0,0 +1,36 @@ +//===-- llvm/Target/TargetVerify/AMDGPUTargetVerifier.h - AMDGPU ---*- C++ -*-===// +//// +//// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +//// See https://llvm.org/LICENSE.txt for license information. +//// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//// +////===----------------------------------------------------------------------===// +//// +//// This file defines target verifier interfaces that can be used for some +//// validation of input to the system, and for checking that transformations +//// haven't done something bad. In contrast to the Verifier or Lint, the +//// TargetVerifier looks for constructions invalid to a particular target +//// machine. +//// +//// To see what specifically is checked, look at an individual backend's +//// TargetVerifier. +//// +////===----------------------------------------------------------------------===// + +#ifndef LLVM_AMDGPU_TARGET_VERIFIER_H +#define LLVM_AMDGPU_TARGET_VERIFIER_H + +#include "llvm/Target/TargetVerifier.h" + +namespace llvm { + +class Function; + +class AMDGPUTargetVerifierPass : public TargetVerifierPass { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // namespace llvm + +#endif // LLVM_AMDGPU_TARGET_VERIFIER_H diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 8afe360d088bc..9d21ca182ca13 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -135,6 +135,10 @@ static cl::opt<bool> VerifyNoAliasScopeDomination( cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical " "scopes are not dominating")); +static cl::opt<bool> + VerifyAbortOnError("verifier-abort-on-error", cl::init(false), + cl::desc("In the Verifier pass, abort on errors.")); + namespace llvm { struct VerifierSupport { @@ -7796,16 +7800,22 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F, PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { auto Res = AM.getResult<VerifierAnalysis>(M); - if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) - report_fatal_error("Broken module found, compilation aborted!"); + if (Res.IRBroken || Res.DebugInfoBroken) { + M.IsValid = false; + if (VerifyAbortOnError && FatalErrors) + report_fatal_error("Broken module found, compilation aborted!"); + } return PreservedAnalyses::all(); } PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { auto res = AM.getResult<VerifierAnalysis>(F); - if (res.IRBroken && FatalErrors) - report_fatal_error("Broken function found, compilation aborted!"); + if (res.IRBroken) { + F.getParent()->IsValid = false; + if (VerifyAbortOnError && FatalErrors) + report_fatal_error("Broken function found, compilation aborted!"); + } return PreservedAnalyses::all(); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp new file mode 100644 index 0000000000000..585b19065c142 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -0,0 +1,213 @@ +#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" + +#include "llvm/Analysis/UniformityAnalysis.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Support/Debug.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IntrinsicsAMDGPU.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt<bool> +MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(false)); + +// Check - We know that cond should be true, if not print an error message. +#define Check(C, ...) \ + do { \ + if (!(C)) { \ + TargetVerify::CheckFailed(__VA_ARGS__); \ + return; \ + } \ + } while (false) + +static bool isMFMA(unsigned IID) { + switch (IID) { + case Intrinsic::amdgcn_mfma_f32_4x4x1f32: + case Intrinsic::amdgcn_mfma_f32_4x4x4f16: + case Intrinsic::amdgcn_mfma_i32_4x4x4i8: + case Intrinsic::amdgcn_mfma_f32_4x4x2bf16: + + case Intrinsic::amdgcn_mfma_f32_16x16x1f32: + case Intrinsic::amdgcn_mfma_f32_16x16x4f32: + case Intrinsic::amdgcn_mfma_f32_16x16x4f16: + case Intrinsic::amdgcn_mfma_f32_16x16x16f16: + case Intrinsic::amdgcn_mfma_i32_16x16x4i8: + case Intrinsic::amdgcn_mfma_i32_16x16x16i8: + case Intrinsic::amdgcn_mfma_f32_16x16x2bf16: + case Intrinsic::amdgcn_mfma_f32_16x16x8bf16: + + case Intrinsic::amdgcn_mfma_f32_32x32x1f32: + case Intrinsic::amdgcn_mfma_f32_32x32x2f32: + case Intrinsic::amdgcn_mfma_f32_32x32x4f16: + case Intrinsic::amdgcn_mfma_f32_32x32x8f16: + case Intrinsic::amdgcn_mfma_i32_32x32x4i8: + case Intrinsic::amdgcn_mfma_i32_32x32x8i8: + case Intrinsic::amdgcn_mfma_f32_32x32x2bf16: + case Intrinsic::amdgcn_mfma_f32_32x32x4bf16: + + case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k: + case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k: + case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k: + case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k: + case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k: + + case Intrinsic::amdgcn_mfma_f64_16x16x4f64: + case Intrinsic::amdgcn_mfma_f64_4x4x4f64: + + case Intrinsic::amdgcn_mfma_i32_16x16x32_i8: + case Intrinsic::amdgcn_mfma_i32_32x32x16_i8: + case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32: + case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32: + + case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8: + case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8: + case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8: + case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8: + + case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8: + case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8: + case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8: + case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8: + return true; + default: + return false; + } +} + +namespace llvm { +class AMDGPUTargetVerify : public TargetVerify { +public: + Module *Mod; + + DominatorTree *DT; + PostDominatorTree *PDT; + UniformityInfo *UA; + + AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA) + : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {} + + void run(Function &F); +}; + +static bool IsValidInt(const Type *Ty) { + return Ty->isIntegerTy(1) || + Ty->isIntegerTy(8) || + Ty->isIntegerTy(16) || + Ty->isIntegerTy(32) || + Ty->isIntegerTy(64) || + Ty->isIntegerTy(128); +} + +static bool isShader(CallingConv::ID CC) { + switch(CC) { + case CallingConv::AMDGPU_VS: + case CallingConv::AMDGPU_LS: + case CallingConv::AMDGPU_HS: + case CallingConv::AMDGPU_ES: + case CallingConv::AMDGPU_GS: + case CallingConv::AMDGPU_PS: + case CallingConv::AMDGPU_CS_Chain: + case CallingConv::AMDGPU_CS_ChainPreserve: + case CallingConv::AMDGPU_CS: + return true; + default: + return false; + } +} + +void AMDGPUTargetVerify::run(Function &F) { + // Ensure shader calling convention returns void + if (isShader(F.getCallingConv())) + Check(F.getReturnType() == Type::getVoidTy(F.getContext()), "Shaders must return void"); + + for (auto &BB : F) { + + for (auto &I : BB) { + if (MarkUniform) + outs() << UA->isUniform(&I) << ' ' << I << '\n'; + + // Ensure integral types are valid: i8, i16, i32, i64, i128 + if (I.getType()->isIntegerTy()) + Check(IsValidInt(I.getType()), "Int type is invalid.", &I); + for (unsigned i = 0; i < I.getNumOperands(); ++i) + if (I.getOperand(i)->getType()->isIntegerTy()) + Check(IsValidInt(I.getOperand(i)->getType()), + "Int type is invalid.", I.getOperand(i)); + + // Ensure no store to const memory + if (auto *SI = dyn_cast<StoreInst>(&I)) + { + unsigned AS = SI->getPointerAddressSpace(); + Check(AS != 4, "Write to const memory", SI); + } + + // Ensure no kernel to kernel calls. + if (auto *CI = dyn_cast<CallInst>(&I)) + { + CallingConv::ID CalleeCC = CI->getCallingConv(); + if (CalleeCC == CallingConv::AMDGPU_KERNEL) + { + CallingConv::ID CallerCC = CI->getParent()->getParent()->getCallingConv(); + Check(CallerCC != CallingConv::AMDGPU_KERNEL, + "A kernel may not call a kernel", CI->getParent()->getParent()); + } + } + + // Ensure MFMA is not in control flow with diverging operands + if (auto *II = dyn_cast<IntrinsicInst>(&I)) { + if (isMFMA(II->getIntrinsicID())) { + bool InControlFlow = false; + for (const auto &P : predecessors(&BB)) + if (!PDT->dominates(&BB, P)) { + InControlFlow = true; + break; + } + for (const auto &S : successors(&BB)) + if (!DT->dominates(&BB, S)) { + InControlFlow = true; + break; + } + if (InControlFlow) { + // If operands to MFMA are not uniform, MFMA cannot be in control flow + bool hasUniformOperands = true; + for (unsigned i = 0; i < II->getNumOperands(); i++) { + if (!UA->isUniform(II->getOperand(i))) { + dbgs() << "Not uniform: " << *II->getOperand(i) << '\n'; + hasUniformOperands = false; + } + } + if (!hasUniformOperands) Check(false, "MFMA in control flow", II); + //else Check(false, "MFMA in control flow (uniform operands)", II); + } + //else Check(false, "MFMA not in control flow", II); + } + } + } + } +} + +PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { + + auto *Mod = F.getParent(); + + auto UA = &AM.getResult<UniformityInfoAnalysis>(F); + auto *DT = &AM.getResult<DominatorTreeAnalysis>(F); + auto *PDT = &AM.getResult<PostDominatorTreeAnalysis>(F); + + AMDGPUTargetVerify TV(Mod, DT, PDT, UA); + TV.run(F); + + dbgs() << TV.MessagesStr.str(); + if (!TV.MessagesStr.str().empty()) { + F.getParent()->IsValid = false; + } + + return PreservedAnalyses::all(); +} +} // namespace llvm diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt index 09a3096602fc3..bcfea0bf8ac94 100644 --- a/llvm/lib/Target/AMDGPU/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt @@ -110,6 +110,7 @@ add_llvm_target(AMDGPUCodeGen AMDGPUTargetMachine.cpp AMDGPUTargetObjectFile.cpp AMDGPUTargetTransformInfo.cpp + AMDGPUTargetVerifier.cpp AMDGPUWaitSGPRHazards.cpp AMDGPUUnifyDivergentExitNodes.cpp AMDGPUUnifyMetadata.cpp diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll new file mode 100644 index 0000000000000..f56ff992a56c2 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll @@ -0,0 +1,62 @@ +; RUN: not llvm-tgt-verify %s -mtriple=amdgcn |& FileCheck %s + +define amdgpu_kernel void @test_mfma_f32_32x32x1f32_vecarg(ptr addrspace(1) %arg) #0 { +; CHECK: Not uniform: %in.f32 = load <32 x float>, ptr addrspace(1) %gep, align 128 +; CHECK-NEXT: MFMA in control flow +; CHECK-NEXT: %mfma = tail call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float 1.000000e+00, float 2.000000e+00, <32 x float> %in.f32, i32 1, i32 2, i32 3) +s: + %tid = call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds <32 x float>, ptr addrspace(1) %arg, i32 %tid + %in.i32 = load <32 x i32>, ptr addrspace(1) %gep + %in.f32 = load <32 x float>, ptr addrspace(1) %gep + + %0 = icmp eq <32 x i32> %in.i32, zeroinitializer + %div.br = extractelement <32 x i1> %0, i32 0 + br i1 %div.br, label %if.3, label %else.0 + +if.3: + br label %join + +else.0: + %mfma = tail call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float 1.000000e+00, float 2.000000e+00, <32 x float> %in.f32, i32 1, i32 2, i32 3) + br label %join + +join: + ret void +} + +define amdgpu_cs i32 @shader() { +; CHECK: Shaders must return void + ret i32 0 +} + +define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) { +; CHECK: Undefined behavior: Write to memory in const addrspace +; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out, align 4 +; CHECK-NEXT: Write to const memory +; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out, align 4 + %r = add i32 %a, %b + store i32 %r, ptr addrspace(4) %out + ret void +} + +define amdgpu_kernel void @kernel_callee(ptr %x) { + ret void +} + +define amdgpu_kernel void @kernel_caller(ptr %x) { +; CHECK: A kernel may not call a kernel +; CHECK-NEXT: ptr @kernel_caller + call amdgpu_kernel void @kernel_callee(ptr %x) + ret void +} + + +; Function Attrs: nounwind +define i65 @invalid_type(i65 %x) #0 { +; CHECK: Int type is invalid. +; CHECK-NEXT: %tmp2 = ashr i65 %x, 64 +entry: + %tmp2 = ashr i65 %x, 64 + ret i65 %tmp2 +} diff --git a/llvm/tools/llvm-tgt-verify/CMakeLists.txt b/llvm/tools/llvm-tgt-verify/CMakeLists.txt new file mode 100644 index 0000000000000..fe47c85e6cdce --- /dev/null +++ b/llvm/tools/llvm-tgt-verify/CMakeLists.txt @@ -0,0 +1,34 @@ +set(LLVM_LINK_COMPONENTS + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos + Analysis + AsmPrinter + CodeGen + CodeGenTypes + Core + IRPrinter + IRReader + MC + MIRParser + Passes + Remarks + ScalarOpts + SelectionDAG + Support + Target + TargetParser + TransformUtils + Vectorize + ) + +add_llvm_tool(llvm-tgt-verify + llvm-tgt-verify.cpp + + DEPENDS + intrinsics_gen + SUPPORT_PLUGINS + ) + +export_executable_symbols_for_plugins(llc) diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp new file mode 100644 index 0000000000000..68422abd6f4cc --- /dev/null +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -0,0 +1,172 @@ +//===--- llvm-isel-fuzzer.cpp - Fuzzer for instruction selection ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Tool to fuzz instruction selection using libFuzzer. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/Lint.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/CodeGen/CommandFlags.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/StandardInstrumentations.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetVerifier.h" + +#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" + +#define DEBUG_TYPE "isel-fuzzer" + +using namespace llvm; + +static codegen::RegisterCodeGenFlags CGF; + +static cl::opt<std::string> +InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-")); + +static cl::opt<bool> + StacktraceAbort("stacktrace-abort", + cl::desc("Turn on stacktrace"), cl::init(false)); + +static cl::opt<bool> + NoLint("no-lint", + cl::desc("Turn off Lint"), cl::init(false)); + +static cl::opt<bool> + NoVerify("no-verifier", + cl::desc("Turn off Verifier"), cl::init(false)); + +static cl::opt<char> + OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, cl::init('2')); + +static cl::opt<std::string> + TargetTriple("mtriple", cl::desc("Override target triple for module")); + +static std::unique_ptr<TargetMachine> TM; + +static void handleLLVMFatalError(void *, const char *Message, bool) { + if (StacktraceAbort) { + dbgs() << "LLVM ERROR: " << Message << "\n" + << "Aborting.\n"; + abort(); + } +} + +int main(int argc, char **argv) { + StringRef ExecName = argv[0]; + InitLLVM X(argc, argv); + + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + PassRegistry *Registry = PassRegistry::getPassRegistry(); + initializeCore(*Registry); + initializeCodeGen(*Registry); + initializeAnalysis(*Registry); + initializeTarget(*Registry); + + cl::ParseCommandLineOptions(argc, argv); + + if (TargetTriple.empty()) { + errs() << ExecName << ": -mtriple must be specified\n"; + exit(1); + } + + CodeGenOptLevel OLvl; + if (auto Level = CodeGenOpt::parseLevel(OptLevel)) { + OLvl = *Level; + } else { + errs() << ExecName << ": invalid optimization level.\n"; + return 1; + } + ExitOnError ExitOnErr(std::string(ExecName) + ": error:"); + TM = ExitOnErr(codegen::createTargetMachineForTriple( + Triple::normalize(TargetTriple), OLvl)); + assert(TM && "Could not allocate target machine!"); + + // Make sure we print the summary and the current unit when LLVM errors out. + install_fatal_error_handler(handleLLVMFatalError, nullptr); + + LLVMContext Context; + SMDiagnostic Err; + std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); + if (!M) { + errs() << "Invalid mod\n"; + return 1; + } + auto S = Triple::normalize(TargetTriple); + M->setTargetTriple(S); + + PassInstrumentationCallbacks PIC; + StandardInstrumentations SI(Context, false/*debug PM*/, + false); + registerCodeGenCallback(PIC, *TM); + + ModulePassManager MPM; + FunctionPassManager FPM; + //TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple())); + + MachineFunctionAnalysisManager MFAM; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PassBuilder PB(TM.get(), PipelineTuningOptions(), std::nullopt, &PIC); + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.registerMachineFunctionAnalyses(MFAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); + + SI.registerCallbacks(PIC, &MAM); + + //FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); + + Triple TT(M->getTargetTriple()); + if (!NoLint) + FPM.addPass(LintPass()); + if (!NoVerify) + MPM.addPass(VerifierPass()); + if (TT.isAMDGPU()) + FPM.addPass(AMDGPUTargetVerifierPass()); + else if (false) {} // ... + else + FPM.addPass(TargetVerifierPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + + MPM.run(*M, MAM); + + if (!M->IsValid) + return 1; + + return 0; +} >From a808efce8d90524845a44ffa5b90adb6741e488d Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Mon, 3 Feb 2025 07:15:12 -0800 Subject: [PATCH 02/12] Add hook for target verifier in llc,opt --- .../llvm/Passes/StandardInstrumentations.h | 6 ++++-- llvm/include/llvm/Target/TargetVerifier.h | 1 + .../TargetVerify/AMDGPUTargetVerifier.h | 18 ++++++++++++++++++ llvm/lib/LTO/LTOBackend.cpp | 2 +- llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 2 +- llvm/lib/Passes/CMakeLists.txt | 1 + llvm/lib/Passes/PassBuilderBindings.cpp | 2 +- llvm/lib/Passes/StandardInstrumentations.cpp | 19 +++++++++++++++---- .../Target/AMDGPU/AMDGPUTargetVerifier.cpp | 12 ++++++------ llvm/lib/Target/CMakeLists.txt | 2 ++ .../CodeGen/AMDGPU/tgt-verify-llc-fail.ll | 6 ++++++ .../CodeGen/AMDGPU/tgt-verify-llc-pass.ll | 6 ++++++ llvm/tools/llc/NewPMDriver.cpp | 2 +- .../tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 2 +- llvm/tools/opt/NewPMDriver.cpp | 2 +- llvm/unittests/IR/PassManagerTest.cpp | 6 +++--- 16 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll create mode 100644 llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h index f7a65a88ecf5b..988fcb93b2357 100644 --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -476,7 +476,8 @@ class VerifyInstrumentation { public: VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} void registerCallbacks(PassInstrumentationCallbacks &PIC, - ModuleAnalysisManager *MAM); + ModuleAnalysisManager *MAM, + FunctionAnalysisManager *FAM); }; /// This class implements --time-trace functionality for new pass manager. @@ -621,7 +622,8 @@ class StandardInstrumentations { // Register all the standard instrumentation callbacks. If \p FAM is nullptr // then PreservedCFGChecker is not enabled. void registerCallbacks(PassInstrumentationCallbacks &PIC, - ModuleAnalysisManager *MAM = nullptr); + ModuleAnalysisManager *MAM, + FunctionAnalysisManager *FAM); TimePassesHandler &getTimePasses() { return TimePasses; } }; diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h index e00c6a7b260c9..ad5aeb895953d 100644 --- a/llvm/include/llvm/Target/TargetVerifier.h +++ b/llvm/include/llvm/Target/TargetVerifier.h @@ -75,6 +75,7 @@ class TargetVerify { MessagesStr(Messages) {} void run(Function &F) {}; + void run(Function &F, FunctionAnalysisManager &AM); }; } // namespace llvm diff --git a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h index e6ff57629b141..d8a3fda4f87dc 100644 --- a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h +++ b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h @@ -22,6 +22,10 @@ #include "llvm/Target/TargetVerifier.h" +#include "llvm/Analysis/UniformityAnalysis.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/Dominators.h" + namespace llvm { class Function; @@ -31,6 +35,20 @@ class AMDGPUTargetVerifierPass : public TargetVerifierPass { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; +class AMDGPUTargetVerify : public TargetVerify { +public: + Module *Mod; + + DominatorTree *DT; + PostDominatorTree *PDT; + UniformityInfo *UA; + + AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA) + : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {} + + void run(Function &F); +}; + } // namespace llvm #endif // LLVM_AMDGPU_TARGET_VERIFIER_H diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 1c764a0188eda..475e7cf45371b 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -275,7 +275,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM, PassInstrumentationCallbacks PIC; StandardInstrumentations SI(Mod.getContext(), Conf.DebugPassManager, Conf.VerifyEach); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC); RegisterPassPlugins(Conf.PassPlugins, PB); diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 9e7f8187fe49c..369b003df1364 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -245,7 +245,7 @@ static void optimizeModule(Module &TheModule, TargetMachine &TM, PassInstrumentationCallbacks PIC; StandardInstrumentations SI(TheModule.getContext(), DebugPassManager); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); PipelineTuningOptions PTO; PTO.LoopVectorization = true; PTO.SLPVectorization = true; diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt index 6425f4934b210..f171377a8b270 100644 --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -29,6 +29,7 @@ add_llvm_component_library(LLVMPasses Scalar Support Target + TargetParser TransformUtils Vectorize Instrumentation diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp index 933fe89e53a94..f0e1abb8cebc4 100644 --- a/llvm/lib/Passes/PassBuilderBindings.cpp +++ b/llvm/lib/Passes/PassBuilderBindings.cpp @@ -76,7 +76,7 @@ static LLVMErrorRef runPasses(Module *Mod, Function *Fun, const char *Passes, PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); // Run the pipeline. if (Fun) { diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp index dc1dd5d9c7f4c..7b15f89e361b8 100644 --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/xxhash.h" +#include "llvm/Target/TargetVerifier.h" #include <unordered_map> #include <unordered_set> #include <utility> @@ -1454,9 +1455,10 @@ void PreservedCFGCheckerInstrumentation::registerCallbacks( } void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC, - ModuleAnalysisManager *MAM) { + ModuleAnalysisManager *MAM, + FunctionAnalysisManager *FAM) { PIC.registerAfterPassCallback( - [this, MAM](StringRef P, Any IR, const PreservedAnalyses &PassPA) { + [this, MAM, FAM](StringRef P, Any IR, const PreservedAnalyses &PassPA) { if (isIgnored(P) || P == "VerifierPass") return; const auto *F = unwrapIR<Function>(IR); @@ -1473,6 +1475,15 @@ void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC, report_fatal_error(formatv("Broken function found after pass " "\"{0}\", compilation aborted!", P)); + + if (FAM) { + TargetVerify TV(const_cast<Module*>(F->getParent())); + TV.run(*const_cast<Function*>(F), *FAM); + if (!F->getParent()->IsValid) + report_fatal_error(formatv("Broken function found after pass " + "\"{0}\", compilation aborted!", + P)); + } } else { const auto *M = unwrapIR<Module>(IR); if (!M) { @@ -2512,7 +2523,7 @@ void PrintCrashIRInstrumentation::registerCallbacks( } void StandardInstrumentations::registerCallbacks( - PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) { + PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM, FunctionAnalysisManager *FAM) { PrintIR.registerCallbacks(PIC); PrintPass.registerCallbacks(PIC); TimePasses.registerCallbacks(PIC); @@ -2521,7 +2532,7 @@ void StandardInstrumentations::registerCallbacks( PrintChangedIR.registerCallbacks(PIC); PseudoProbeVerification.registerCallbacks(PIC); if (VerifyEach) - Verify.registerCallbacks(PIC, MAM); + Verify.registerCallbacks(PIC, MAM, FAM); PrintChangedDiff.registerCallbacks(PIC); WebsiteChangeReporter.registerCallbacks(PIC); ChangeTester.registerCallbacks(PIC); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index 585b19065c142..e6cdec7160229 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -14,8 +14,8 @@ using namespace llvm; -static cl::opt<bool> -MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(false)); +//static cl::opt<bool> +//MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(false)); // Check - We know that cond should be true, if not print an error message. #define Check(C, ...) \ @@ -81,7 +81,7 @@ static bool isMFMA(unsigned IID) { } namespace llvm { -class AMDGPUTargetVerify : public TargetVerify { +/*class AMDGPUTargetVerify : public TargetVerify { public: Module *Mod; @@ -93,7 +93,7 @@ class AMDGPUTargetVerify : public TargetVerify { : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {} void run(Function &F); -}; +};*/ static bool IsValidInt(const Type *Ty) { return Ty->isIntegerTy(1) || @@ -129,8 +129,8 @@ void AMDGPUTargetVerify::run(Function &F) { for (auto &BB : F) { for (auto &I : BB) { - if (MarkUniform) - outs() << UA->isUniform(&I) << ' ' << I << '\n'; + //if (MarkUniform) + //outs() << UA->isUniform(&I) << ' ' << I << '\n'; // Ensure integral types are valid: i8, i16, i32, i64, i128 if (I.getType()->isIntegerTy()) diff --git a/llvm/lib/Target/CMakeLists.txt b/llvm/lib/Target/CMakeLists.txt index 9472288229cac..f2a5d545ce84f 100644 --- a/llvm/lib/Target/CMakeLists.txt +++ b/llvm/lib/Target/CMakeLists.txt @@ -7,6 +7,8 @@ add_llvm_component_library(LLVMTarget TargetLoweringObjectFile.cpp TargetMachine.cpp TargetMachineC.cpp + TargetVerifier.cpp + AMDGPU/AMDGPUTargetVerifier.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Target diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll new file mode 100644 index 0000000000000..584097d7bc134 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll @@ -0,0 +1,6 @@ +; RUN: not not llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -enable-new-pm -verify-each -o - < %s 2>&1 | FileCheck %s + +define amdgpu_cs i32 @nonvoid_shader() { +; CHECK: LLVM ERROR + ret i32 0 +} diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll new file mode 100644 index 0000000000000..0c3a5fe5ac4a5 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll @@ -0,0 +1,6 @@ +; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -enable-new-pm -verify-each %s -o - 2>&1 | FileCheck %s + +define amdgpu_cs void @void_shader() { +; CHECK: ModuleToFunctionPassAdaptor + ret void +} diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp index fa82689ecf9ae..a060d16e74958 100644 --- a/llvm/tools/llc/NewPMDriver.cpp +++ b/llvm/tools/llc/NewPMDriver.cpp @@ -126,7 +126,7 @@ int llvm::compileModuleWithNewPM( PB.registerLoopAnalyses(LAM); PB.registerMachineFunctionAnalyses(MFAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index 68422abd6f4cc..3352d07deff2f 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -147,7 +147,7 @@ int main(int argc, char **argv) { PB.registerMachineFunctionAnalyses(MFAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); //FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index 7d168a6ceb17c..a8977d80bdf44 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -423,7 +423,7 @@ bool llvm::runPassPipeline( PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet; StandardInstrumentations SI(M.getContext(), DebugPM != DebugLogging::None, VK == VerifierKind::EachPass, PrintPassOpts); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); DebugifyEachInstrumentation Debugify; DebugifyStatsMap DIStatsMap; DebugInfoPerPass DebugInfoBeforePass; diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp index a6487169224c2..bb4db6120035f 100644 --- a/llvm/unittests/IR/PassManagerTest.cpp +++ b/llvm/unittests/IR/PassManagerTest.cpp @@ -828,7 +828,7 @@ TEST_F(PassManagerTest, FunctionPassCFGChecker) { FunctionPassManager FPM; PassInstrumentationCallbacks PIC; StandardInstrumentations SI(M->getContext(), /*DebugLogging*/ true); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); @@ -877,7 +877,7 @@ TEST_F(PassManagerTest, FunctionPassCFGCheckerInvalidateAnalysis) { FunctionPassManager FPM; PassInstrumentationCallbacks PIC; StandardInstrumentations SI(M->getContext(), /*DebugLogging*/ true); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); @@ -945,7 +945,7 @@ TEST_F(PassManagerTest, FunctionPassCFGCheckerWrapped) { FunctionPassManager FPM; PassInstrumentationCallbacks PIC; StandardInstrumentations SI(M->getContext(), /*DebugLogging*/ true); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); >From 64d001858efc994e965071cd319d268b934a6eb3 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Wed, 16 Apr 2025 10:19:00 -0400 Subject: [PATCH 03/12] Run AMDGPUTargetVerifier within AMDGPU pipeline. Move IsValid from Module to TargetVerify. --- clang/lib/CodeGen/BackendUtil.cpp | 2 +- llvm/include/llvm/IR/Module.h | 4 ---- llvm/include/llvm/Target/TargetVerifier.h | 2 ++ llvm/lib/IR/Verifier.cpp | 4 ++-- llvm/lib/Passes/StandardInstrumentations.cpp | 2 +- llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 5 +++++ llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp | 3 ++- llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 6 +++--- 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index f7eb853beb23c..9a1c922f5ddef 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -922,7 +922,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( TheModule->getContext(), (CodeGenOpts.DebugPassManager || DebugPassStructure), CodeGenOpts.VerifyEach, PrintPassOpts); - SI.registerCallbacks(PIC, &MAM); + SI.registerCallbacks(PIC, &MAM, &FAM); PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC); // Handle the assignment tracking feature options. diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 03c0cf1cf0924..91ccd76c41e07 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -214,10 +214,6 @@ class LLVM_ABI Module { /// @name Constructors /// @{ public: - /// Is this Module valid as determined by one of the verification passes - /// i.e. Lint, Verifier, TargetVerifier. - bool IsValid = true; - /// Is this Module using intrinsics to record the position of debugging /// information, or non-intrinsic records? See IsNewDbgInfoFormat in /// \ref BasicBlock. diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h index ad5aeb895953d..2d0c039132c35 100644 --- a/llvm/include/llvm/Target/TargetVerifier.h +++ b/llvm/include/llvm/Target/TargetVerifier.h @@ -70,6 +70,8 @@ class TargetVerify { std::string Messages; raw_string_ostream MessagesStr; + bool IsValid = true; + TargetVerify(Module *Mod) : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())), MessagesStr(Messages) {} diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 9d21ca182ca13..d7c514610b4ba 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -7801,7 +7801,7 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F, PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { auto Res = AM.getResult<VerifierAnalysis>(M); if (Res.IRBroken || Res.DebugInfoBroken) { - M.IsValid = false; + //M.IsValid = false; if (VerifyAbortOnError && FatalErrors) report_fatal_error("Broken module found, compilation aborted!"); } @@ -7812,7 +7812,7 @@ PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { auto res = AM.getResult<VerifierAnalysis>(F); if (res.IRBroken) { - F.getParent()->IsValid = false; + //F.getParent()->IsValid = false; if (VerifyAbortOnError && FatalErrors) report_fatal_error("Broken function found, compilation aborted!"); } diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp index 7b15f89e361b8..879d657c87695 100644 --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -1479,7 +1479,7 @@ void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC, if (FAM) { TargetVerify TV(const_cast<Module*>(F->getParent())); TV.run(*const_cast<Function*>(F), *FAM); - if (!F->getParent()->IsValid) + if (!TV.IsValid) report_fatal_error(formatv("Broken function found after pass " "\"{0}\", compilation aborted!", P)); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 90e3489ced923..6ec34d6a0fdbf 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -90,6 +90,7 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" #include "llvm/Transforms/HipStdPar/HipStdPar.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" @@ -1298,6 +1299,8 @@ void AMDGPUPassConfig::addIRPasses() { addPass(createLICMPass()); } + //addPass(AMDGPUTargetVerifierPass()); + TargetPassConfig::addIRPasses(); // EarlyCSE is not always strong enough to clean up what LSR produces. For @@ -2040,6 +2043,8 @@ void AMDGPUCodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const { // but EarlyCSE can do neither of them. if (isPassEnabled(EnableScalarIRPasses)) addEarlyCSEOrGVNPass(addPass); + + addPass(AMDGPUTargetVerifierPass()); } void AMDGPUCodeGenPassBuilder::addCodeGenPrepare(AddIRPass &addPass) const { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index e6cdec7160229..c70a6d1b6fa66 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -205,7 +205,8 @@ PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, FunctionAnalysisMan dbgs() << TV.MessagesStr.str(); if (!TV.MessagesStr.str().empty()) { - F.getParent()->IsValid = false; + TV.IsValid = false; + return PreservedAnalyses::none(); } return PreservedAnalyses::all(); diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index 3352d07deff2f..fbe7f6089ff18 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -163,9 +163,9 @@ int main(int argc, char **argv) { FPM.addPass(TargetVerifierPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - MPM.run(*M, MAM); - - if (!M->IsValid) + auto PA = MPM.run(*M, MAM); + auto PAC = PA.getChecker<VerifierAnalysis>(); + if (!PAC.preserved()) return 1; return 0; >From fdae3025942584d0085deb3442f40471548defe5 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Wed, 16 Apr 2025 11:08:20 -0400 Subject: [PATCH 04/12] Remove cmd line options that aren't required. Make error message explicit. --- llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll | 4 ++-- llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll index 584097d7bc134..c5e59d4a2369e 100644 --- a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll @@ -1,6 +1,6 @@ -; RUN: not not llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -enable-new-pm -verify-each -o - < %s 2>&1 | FileCheck %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -enable-new-pm -o - < %s 2>&1 | FileCheck %s define amdgpu_cs i32 @nonvoid_shader() { -; CHECK: LLVM ERROR +; CHECK: Shaders must return void ret i32 0 } diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll index 0c3a5fe5ac4a5..8a503b7624a73 100644 --- a/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll @@ -1,6 +1,6 @@ -; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -enable-new-pm -verify-each %s -o - 2>&1 | FileCheck %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -enable-new-pm %s -o - 2>&1 | FileCheck %s --allow-empty define amdgpu_cs void @void_shader() { -; CHECK: ModuleToFunctionPassAdaptor +; CHECK-NOT: Shaders must return void ret void } >From 5ceda58cc5b5d7372c6e43cbdf583f0dda87b956 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 19:36:34 -0400 Subject: [PATCH 05/12] Return Verifier none status through PreservedAnalyses on fail. --- llvm/lib/Analysis/Lint.cpp | 4 +++- llvm/lib/IR/Verifier.cpp | 2 ++ llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 8 +++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp index f05e36e2025d4..c8e38963e5974 100644 --- a/llvm/lib/Analysis/Lint.cpp +++ b/llvm/lib/Analysis/Lint.cpp @@ -742,9 +742,11 @@ PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) { Lint L(Mod, DL, AA, AC, DT, TLI); L.visit(F); dbgs() << L.MessagesStr.str(); - if (AbortOnError && !L.MessagesStr.str().empty()) + if (AbortOnError && !L.MessagesStr.str().empty()) { report_fatal_error( "linter found errors, aborting. (enabled by abort-on-error)", false); + return PreservedAnalyses::none(); + } return PreservedAnalyses::all(); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index d7c514610b4ba..51f6dec53b70f 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -7804,6 +7804,7 @@ PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { //M.IsValid = false; if (VerifyAbortOnError && FatalErrors) report_fatal_error("Broken module found, compilation aborted!"); + return PreservedAnalyses::none(); } return PreservedAnalyses::all(); @@ -7815,6 +7816,7 @@ PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { //F.getParent()->IsValid = false; if (VerifyAbortOnError && FatalErrors) report_fatal_error("Broken function found, compilation aborted!"); + return PreservedAnalyses::none(); } return PreservedAnalyses::all(); diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index fbe7f6089ff18..042824ac37fea 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -164,9 +164,11 @@ int main(int argc, char **argv) { MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); auto PA = MPM.run(*M, MAM); - auto PAC = PA.getChecker<VerifierAnalysis>(); - if (!PAC.preserved()) - return 1; + { + auto PAC = PA.getChecker<VerifierAnalysis>(); + if (!PAC.preserved()) + return 1; + } return 0; } >From 99c29069cdaf68c92ce7f25ca2f730bf738ca324 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 21:16:02 -0400 Subject: [PATCH 06/12] Rebase update. --- llvm/include/llvm/Target/TargetVerifier.h | 2 +- llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h index 2d0c039132c35..fe683311b901c 100644 --- a/llvm/include/llvm/Target/TargetVerifier.h +++ b/llvm/include/llvm/Target/TargetVerifier.h @@ -73,7 +73,7 @@ class TargetVerify { bool IsValid = true; TargetVerify(Module *Mod) - : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())), + : Mod(Mod), TT(Mod->getTargetTriple()), MessagesStr(Messages) {} void run(Function &F) {}; diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index 042824ac37fea..627bc51ef3a43 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -123,7 +123,7 @@ int main(int argc, char **argv) { return 1; } auto S = Triple::normalize(TargetTriple); - M->setTargetTriple(S); + M->setTargetTriple(Triple(S)); PassInstrumentationCallbacks PIC; StandardInstrumentations SI(Context, false/*debug PM*/, @@ -153,7 +153,7 @@ int main(int argc, char **argv) { Triple TT(M->getTargetTriple()); if (!NoLint) - FPM.addPass(LintPass()); + FPM.addPass(LintPass(false)); if (!NoVerify) MPM.addPass(VerifierPass()); if (TT.isAMDGPU()) >From 3ea7eae48a6addbf711716e7a819830dddc1b34a Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 22:49:52 -0400 Subject: [PATCH 07/12] Add generic TargetVerifier. --- llvm/lib/Target/TargetVerifier.cpp | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 llvm/lib/Target/TargetVerifier.cpp diff --git a/llvm/lib/Target/TargetVerifier.cpp b/llvm/lib/Target/TargetVerifier.cpp new file mode 100644 index 0000000000000..de3ff749e7c3c --- /dev/null +++ b/llvm/lib/Target/TargetVerifier.cpp @@ -0,0 +1,32 @@ +#include "llvm/Target/TargetVerifier.h" +#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" + +#include "llvm/Analysis/UniformityAnalysis.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Support/Debug.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IntrinsicsAMDGPU.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" + +namespace llvm { + +void TargetVerify::run(Function &F, FunctionAnalysisManager &AM) { + if (TT.isAMDGPU()) { + auto *UA = &AM.getResult<UniformityInfoAnalysis>(F); + auto *DT = &AM.getResult<DominatorTreeAnalysis>(F); + auto *PDT = &AM.getResult<PostDominatorTreeAnalysis>(F); + + AMDGPUTargetVerify TV(Mod, DT, PDT, UA); + TV.run(F); + + dbgs() << TV.MessagesStr.str(); + if (!TV.MessagesStr.str().empty()) { + TV.IsValid = false; + } + } +} + +} // namespace llvm >From f52c4dbc84952d97266f5f4158729e564de10240 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 23:13:14 -0400 Subject: [PATCH 08/12] Remove store to const check since it is in Lint already --- llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp | 8 -------- llvm/test/CodeGen/AMDGPU/tgt-verify.ll | 2 -- 2 files changed, 10 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index c70a6d1b6fa66..1cf2b277bee26 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -140,14 +140,6 @@ void AMDGPUTargetVerify::run(Function &F) { Check(IsValidInt(I.getOperand(i)->getType()), "Int type is invalid.", I.getOperand(i)); - // Ensure no store to const memory - if (auto *SI = dyn_cast<StoreInst>(&I)) - { - unsigned AS = SI->getPointerAddressSpace(); - Check(AS != 4, "Write to const memory", SI); - } - - // Ensure no kernel to kernel calls. if (auto *CI = dyn_cast<CallInst>(&I)) { CallingConv::ID CalleeCC = CI->getCallingConv(); diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll index f56ff992a56c2..c628abbde11d1 100644 --- a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll @@ -32,8 +32,6 @@ define amdgpu_cs i32 @shader() { define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) { ; CHECK: Undefined behavior: Write to memory in const addrspace -; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out, align 4 -; CHECK-NEXT: Write to const memory ; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out, align 4 %r = add i32 %a, %b store i32 %r, ptr addrspace(4) %out >From 5c9a4ab3895d6939b12386d1db2081ca388df01a Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 23:14:38 -0400 Subject: [PATCH 09/12] Add chain followed by unreachable check --- llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp | 6 ++++++ llvm/test/CodeGen/AMDGPU/tgt-verify.ll | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index 1cf2b277bee26..8ea773bc0e66f 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -142,6 +142,7 @@ void AMDGPUTargetVerify::run(Function &F) { if (auto *CI = dyn_cast<CallInst>(&I)) { + // Ensure no kernel to kernel calls. CallingConv::ID CalleeCC = CI->getCallingConv(); if (CalleeCC == CallingConv::AMDGPU_KERNEL) { @@ -149,6 +150,11 @@ void AMDGPUTargetVerify::run(Function &F) { Check(CallerCC != CallingConv::AMDGPU_KERNEL, "A kernel may not call a kernel", CI->getParent()->getParent()); } + + // Ensure chain intrinsics are followed by unreachables. + if (CI->getIntrinsicID() == Intrinsic::amdgcn_cs_chain) + Check(isa_and_present<UnreachableInst>(CI->getNextNode()), + "llvm.amdgcn.cs.chain must be followed by unreachable", CI); } // Ensure MFMA is not in control flow with diverging operands diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll index c628abbde11d1..e620df94ccde4 100644 --- a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll @@ -58,3 +58,13 @@ entry: %tmp2 = ashr i65 %x, 64 ret i65 %tmp2 } + +declare void @llvm.amdgcn.cs.chain.v3i32(ptr, i32, <3 x i32>, <3 x i32>, i32, ...) +declare amdgpu_cs_chain void @chain_callee(<3 x i32> inreg, <3 x i32>) + +define amdgpu_cs void @no_unreachable(<3 x i32> inreg %a, <3 x i32> %b) { +; CHECK: llvm.amdgcn.cs.chain must be followed by unreachable +; CHECK-NEXT: call void (ptr, i32, <3 x i32>, <3 x i32>, i32, ...) @llvm.amdgcn.cs.chain.p0.i32.v3i32.v3i32(ptr @chain_callee, i32 -1, <3 x i32> inreg %a, <3 x i32> %b, i32 0) + call void(ptr, i32, <3 x i32>, <3 x i32>, i32, ...) @llvm.amdgcn.cs.chain.v3i32(ptr @chain_callee, i32 -1, <3 x i32> inreg %a, <3 x i32> %b, i32 0) + ret void +} >From 0ff03f792c018e4fd0c11de9da4d3353617707f5 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Sat, 19 Apr 2025 23:26:19 -0400 Subject: [PATCH 10/12] Remove mfma check --- .../Target/AMDGPU/AMDGPUTargetVerifier.cpp | 89 ------------------- llvm/test/CodeGen/AMDGPU/tgt-verify.ll | 25 ------ 2 files changed, 114 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index 8ea773bc0e66f..684ced5bba574 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -14,9 +14,6 @@ using namespace llvm; -//static cl::opt<bool> -//MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(false)); - // Check - We know that cond should be true, if not print an error message. #define Check(C, ...) \ do { \ @@ -26,60 +23,6 @@ using namespace llvm; } \ } while (false) -static bool isMFMA(unsigned IID) { - switch (IID) { - case Intrinsic::amdgcn_mfma_f32_4x4x1f32: - case Intrinsic::amdgcn_mfma_f32_4x4x4f16: - case Intrinsic::amdgcn_mfma_i32_4x4x4i8: - case Intrinsic::amdgcn_mfma_f32_4x4x2bf16: - - case Intrinsic::amdgcn_mfma_f32_16x16x1f32: - case Intrinsic::amdgcn_mfma_f32_16x16x4f32: - case Intrinsic::amdgcn_mfma_f32_16x16x4f16: - case Intrinsic::amdgcn_mfma_f32_16x16x16f16: - case Intrinsic::amdgcn_mfma_i32_16x16x4i8: - case Intrinsic::amdgcn_mfma_i32_16x16x16i8: - case Intrinsic::amdgcn_mfma_f32_16x16x2bf16: - case Intrinsic::amdgcn_mfma_f32_16x16x8bf16: - - case Intrinsic::amdgcn_mfma_f32_32x32x1f32: - case Intrinsic::amdgcn_mfma_f32_32x32x2f32: - case Intrinsic::amdgcn_mfma_f32_32x32x4f16: - case Intrinsic::amdgcn_mfma_f32_32x32x8f16: - case Intrinsic::amdgcn_mfma_i32_32x32x4i8: - case Intrinsic::amdgcn_mfma_i32_32x32x8i8: - case Intrinsic::amdgcn_mfma_f32_32x32x2bf16: - case Intrinsic::amdgcn_mfma_f32_32x32x4bf16: - - case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k: - case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k: - case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k: - case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k: - case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k: - - case Intrinsic::amdgcn_mfma_f64_16x16x4f64: - case Intrinsic::amdgcn_mfma_f64_4x4x4f64: - - case Intrinsic::amdgcn_mfma_i32_16x16x32_i8: - case Intrinsic::amdgcn_mfma_i32_32x32x16_i8: - case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32: - case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32: - - case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8: - case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8: - case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8: - case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8: - - case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8: - case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8: - case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8: - case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8: - return true; - default: - return false; - } -} - namespace llvm { /*class AMDGPUTargetVerify : public TargetVerify { public: @@ -129,8 +72,6 @@ void AMDGPUTargetVerify::run(Function &F) { for (auto &BB : F) { for (auto &I : BB) { - //if (MarkUniform) - //outs() << UA->isUniform(&I) << ' ' << I << '\n'; // Ensure integral types are valid: i8, i16, i32, i64, i128 if (I.getType()->isIntegerTy()) @@ -156,36 +97,6 @@ void AMDGPUTargetVerify::run(Function &F) { Check(isa_and_present<UnreachableInst>(CI->getNextNode()), "llvm.amdgcn.cs.chain must be followed by unreachable", CI); } - - // Ensure MFMA is not in control flow with diverging operands - if (auto *II = dyn_cast<IntrinsicInst>(&I)) { - if (isMFMA(II->getIntrinsicID())) { - bool InControlFlow = false; - for (const auto &P : predecessors(&BB)) - if (!PDT->dominates(&BB, P)) { - InControlFlow = true; - break; - } - for (const auto &S : successors(&BB)) - if (!DT->dominates(&BB, S)) { - InControlFlow = true; - break; - } - if (InControlFlow) { - // If operands to MFMA are not uniform, MFMA cannot be in control flow - bool hasUniformOperands = true; - for (unsigned i = 0; i < II->getNumOperands(); i++) { - if (!UA->isUniform(II->getOperand(i))) { - dbgs() << "Not uniform: " << *II->getOperand(i) << '\n'; - hasUniformOperands = false; - } - } - if (!hasUniformOperands) Check(false, "MFMA in control flow", II); - //else Check(false, "MFMA in control flow (uniform operands)", II); - } - //else Check(false, "MFMA not in control flow", II); - } - } } } } diff --git a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll index e620df94ccde4..62b220d7d9f49 100644 --- a/llvm/test/CodeGen/AMDGPU/tgt-verify.ll +++ b/llvm/test/CodeGen/AMDGPU/tgt-verify.ll @@ -1,30 +1,5 @@ ; RUN: not llvm-tgt-verify %s -mtriple=amdgcn |& FileCheck %s -define amdgpu_kernel void @test_mfma_f32_32x32x1f32_vecarg(ptr addrspace(1) %arg) #0 { -; CHECK: Not uniform: %in.f32 = load <32 x float>, ptr addrspace(1) %gep, align 128 -; CHECK-NEXT: MFMA in control flow -; CHECK-NEXT: %mfma = tail call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float 1.000000e+00, float 2.000000e+00, <32 x float> %in.f32, i32 1, i32 2, i32 3) -s: - %tid = call i32 @llvm.amdgcn.workitem.id.x() - %gep = getelementptr inbounds <32 x float>, ptr addrspace(1) %arg, i32 %tid - %in.i32 = load <32 x i32>, ptr addrspace(1) %gep - %in.f32 = load <32 x float>, ptr addrspace(1) %gep - - %0 = icmp eq <32 x i32> %in.i32, zeroinitializer - %div.br = extractelement <32 x i1> %0, i32 0 - br i1 %div.br, label %if.3, label %else.0 - -if.3: - br label %join - -else.0: - %mfma = tail call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float 1.000000e+00, float 2.000000e+00, <32 x float> %in.f32, i32 1, i32 2, i32 3) - br label %join - -join: - ret void -} - define amdgpu_cs i32 @shader() { ; CHECK: Shaders must return void ret i32 0 >From 6b84c73a35a260d64ed45df90052f8212b0ee4e7 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Mon, 21 Apr 2025 20:54:10 -0400 Subject: [PATCH 11/12] Add registerVerifierPasses to PassBuilder and add the verifier passes to PassRegistry. --- llvm/include/llvm/InitializePasses.h | 1 + llvm/include/llvm/Passes/PassBuilder.h | 21 +++++++ .../llvm/Passes/TargetPassRegistry.inc | 12 ++++ .../TargetVerify/AMDGPUTargetVerifier.h | 11 ++-- llvm/lib/Passes/PassBuilder.cpp | 7 +++ llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def | 11 ++++ .../Target/AMDGPU/AMDGPUTargetVerifier.cpp | 56 ++++++++++++++++++- .../tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 1 + 8 files changed, 114 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 9bef8e496c57e..ae398db3dc1da 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -317,6 +317,7 @@ void initializeUnpackMachineBundlesPass(PassRegistry &); void initializeUnreachableBlockElimLegacyPassPass(PassRegistry &); void initializeUnreachableMachineBlockElimLegacyPass(PassRegistry &); void initializeVerifierLegacyPassPass(PassRegistry &); +void initializeAMDGPUTargetVerifierLegacyPassPass(PassRegistry &); void initializeVirtRegMapWrapperLegacyPass(PassRegistry &); void initializeVirtRegRewriterPass(PassRegistry &); void initializeWasmEHPreparePass(PassRegistry &); diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 51ccaa53447d7..6000769ce723b 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -172,6 +172,13 @@ class PassBuilder { /// additional analyses. void registerLoopAnalyses(LoopAnalysisManager &LAM); + /// Registers all available verifier passes. + /// + /// This is an interface that can be used to populate a + /// \c ModuleAnalysisManager with all registered loop analyses. Callers can + /// still manually register any additional analyses. + void registerVerifierPasses(ModulePassManager &PM, FunctionPassManager &); + /// Registers all available machine function analysis passes. /// /// This is an interface that can be used to populate a \c @@ -570,6 +577,15 @@ class PassBuilder { } /// @}} + /// Register a callback for parsing an Verifier Name to populate + /// the given managers. + void registerVerifierCallback( + const std::function<bool(ModulePassManager &MPM)> &C, + const std::function<bool(FunctionPassManager &MPM)> &CF) { + VerifierCallbacks.push_back(C); + FnVerifierCallbacks.push_back(CF); + } + /// {{@ Register pipeline parsing callbacks with this pass builder instance. /// Using these callbacks, callers can parse both a single pass name, as well /// as entire sub-pipelines, and populate the PassManager instance @@ -841,6 +857,11 @@ class PassBuilder { // Callbacks to parse `filter` parameter in register allocation passes SmallVector<std::function<RegAllocFilterFunc(StringRef)>, 2> RegClassFilterParsingCallbacks; + // Verifier callbacks + SmallVector<std::function<bool(ModulePassManager &)>, 2> + VerifierCallbacks; + SmallVector<std::function<bool(FunctionPassManager &)>, 2> + FnVerifierCallbacks; }; /// This utility template takes care of adding require<> and invalidate<> diff --git a/llvm/include/llvm/Passes/TargetPassRegistry.inc b/llvm/include/llvm/Passes/TargetPassRegistry.inc index 521913cb25a4a..2d04b874cf360 100644 --- a/llvm/include/llvm/Passes/TargetPassRegistry.inc +++ b/llvm/include/llvm/Passes/TargetPassRegistry.inc @@ -151,6 +151,18 @@ PB.registerPipelineParsingCallback([=](StringRef Name, FunctionPassManager &PM, return false; }); +PB.registerVerifierCallback([](ModulePassManager &PM) { +#define VERIFIER_MODULE_ANALYSIS(NAME, CREATE_PASS) PM.addPass(CREATE_PASS) +#include GET_PASS_REGISTRY +#undef VERIFIER_MODULE_ANALYSIS + return false; +}, [](FunctionPassManager &FPM) { +#define VERIFIER_FUNCTION_ANALYSIS(NAME, CREATE_PASS) FPM.addPass(CREATE_PASS) +#include GET_PASS_REGISTRY +#undef VERIFIER_FUNCTION_ANALYSIS + return false; +}); + #undef ADD_PASS #undef ADD_PASS_WITH_PARAMS diff --git a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h index d8a3fda4f87dc..b6a7412e8c1ef 100644 --- a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h +++ b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h @@ -39,14 +39,17 @@ class AMDGPUTargetVerify : public TargetVerify { public: Module *Mod; - DominatorTree *DT; - PostDominatorTree *PDT; - UniformityInfo *UA; + DominatorTree *DT = nullptr; + PostDominatorTree *PDT = nullptr; + UniformityInfo *UA = nullptr; + + AMDGPUTargetVerify(Module *Mod) + : TargetVerify(Mod), Mod(Mod) {} AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA) : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {} - void run(Function &F); + bool run(Function &F); }; } // namespace llvm diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e7057d9a6b625..e942fed8b6a72 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -582,6 +582,13 @@ void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) { C(LAM); } +void PassBuilder::registerVerifierPasses(ModulePassManager &MPM, FunctionPassManager &FPM) { + for (auto &C : VerifierCallbacks) + C(MPM); + for (auto &C : FnVerifierCallbacks) + C(FPM); +} + static std::optional<std::pair<bool, bool>> parseFunctionPipelineName(StringRef Name) { std::pair<bool, bool> Params; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def b/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def index 98a1147ef6d66..41e6a399c7239 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def +++ b/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def @@ -81,6 +81,17 @@ FUNCTION_ALIAS_ANALYSIS("amdgpu-aa", AMDGPUAA()) #undef FUNCTION_ALIAS_ANALYSIS #undef FUNCTION_ANALYSIS +#ifndef VERIFIER_MODULE_ANALYSIS +#define VERIFIER_MODULE_ANALYSIS(NAME, CREATE_PASS) +#endif +#ifndef VERIFIER_FUNCTION_ANALYSIS +#define VERIFIER_FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif +VERIFIER_MODULE_ANALYSIS("verifier", VerifierPass()) +VERIFIER_FUNCTION_ANALYSIS("amdgpu-tgtverifier", AMDGPUTargetVerifierPass()) +#undef VERIFIER_MODULE_ANALYSIS +#undef VERIFIER_FUNCTION_ANALYSIS + #ifndef FUNCTION_PASS_WITH_PARAMS #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) #endif diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index 684ced5bba574..63a7526b9abdc 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -5,6 +5,7 @@ #include "llvm/Support/Debug.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/InitializePasses.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/Module.h" @@ -19,7 +20,7 @@ using namespace llvm; do { \ if (!(C)) { \ TargetVerify::CheckFailed(__VA_ARGS__); \ - return; \ + return false; \ } \ } while (false) @@ -64,7 +65,7 @@ static bool isShader(CallingConv::ID CC) { } } -void AMDGPUTargetVerify::run(Function &F) { +bool AMDGPUTargetVerify::run(Function &F) { // Ensure shader calling convention returns void if (isShader(F.getCallingConv())) Check(F.getReturnType() == Type::getVoidTy(F.getContext()), "Shaders must return void"); @@ -99,6 +100,10 @@ void AMDGPUTargetVerify::run(Function &F) { } } } + + if (!MessagesStr.str().empty()) + return false; + return true; } PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { @@ -120,4 +125,51 @@ PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, FunctionAnalysisMan return PreservedAnalyses::all(); } + +struct AMDGPUTargetVerifierLegacyPass : public FunctionPass { + static char ID; + + std::unique_ptr<AMDGPUTargetVerify> TV; + bool FatalErrors = true; + + AMDGPUTargetVerifierLegacyPass() : FunctionPass(ID) { + initializeAMDGPUTargetVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); + } + AMDGPUTargetVerifierLegacyPass(bool FatalErrors) + : FunctionPass(ID), + FatalErrors(FatalErrors) { + initializeAMDGPUTargetVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool doInitialization(Module &M) override { + TV = std::make_unique<AMDGPUTargetVerify>(&M); + return false; + } + + bool runOnFunction(Function &F) override { + if (TV->run(F) && FatalErrors) { + errs() << "in function " << F.getName() << '\n'; + report_fatal_error("Broken function found, compilation aborted!"); + } + return false; + } + + bool doFinalization(Module &M) override { + bool IsValid = true; + for (Function &F : M) + if (F.isDeclaration()) + IsValid &= TV->run(F); + + //IsValid &= TV->run(); + if (FatalErrors && !IsValid) + report_fatal_error("Broken module found, compilation aborted!"); + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; +char AMDGPUTargetVerifierLegacyPass::ID = 0; } // namespace llvm +INITIALIZE_PASS(AMDGPUTargetVerifierLegacyPass, "amdgpu-tgtverify", "AMDGPU Target Verifier", false, false) diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index 627bc51ef3a43..503db7b1f8d18 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -144,6 +144,7 @@ int main(int argc, char **argv) { PB.registerCGSCCAnalyses(CGAM); PB.registerFunctionAnalyses(FAM); PB.registerLoopAnalyses(LAM); + //PB.registerVerifierPasses(MPM, FPM); PB.registerMachineFunctionAnalyses(MFAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); >From ec3276b182f3a758a24024291772efe435485857 Mon Sep 17 00:00:00 2001 From: jofernau <joe.fer...@amd.com> Date: Tue, 22 Apr 2025 14:57:31 -0400 Subject: [PATCH 12/12] Remove leftovers. Add titles. Add call to registerVerifierCallbacks in llc. --- llvm/lib/Passes/CMakeLists.txt | 2 +- .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 4 --- .../Target/AMDGPU/AMDGPUTargetVerifier.cpp | 35 +++++++++++-------- llvm/lib/Target/TargetVerifier.cpp | 19 ++++++++++ llvm/tools/llc/NewPMDriver.cpp | 6 ++-- .../tools/llvm-tgt-verify/llvm-tgt-verify.cpp | 7 ++-- 6 files changed, 45 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt index f171377a8b270..9c348cb89a8c5 100644 --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -29,7 +29,7 @@ add_llvm_component_library(LLVMPasses Scalar Support Target - TargetParser + #TargetParser TransformUtils Vectorize Instrumentation diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 6ec34d6a0fdbf..257cc724b3da9 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -1299,8 +1299,6 @@ void AMDGPUPassConfig::addIRPasses() { addPass(createLICMPass()); } - //addPass(AMDGPUTargetVerifierPass()); - TargetPassConfig::addIRPasses(); // EarlyCSE is not always strong enough to clean up what LSR produces. For @@ -2043,8 +2041,6 @@ void AMDGPUCodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const { // but EarlyCSE can do neither of them. if (isPassEnabled(EnableScalarIRPasses)) addEarlyCSEOrGVNPass(addPass); - - addPass(AMDGPUTargetVerifierPass()); } void AMDGPUCodeGenPassBuilder::addCodeGenPrepare(AddIRPass &addPass) const { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp index 63a7526b9abdc..0eecedaebc7ce 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp @@ -1,3 +1,22 @@ +//===-- AMDGPUTargetVerifier.cpp - AMDGPU -------------------------*- C++ -*-===// +//// +//// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +//// See https://llvm.org/LICENSE.txt for license information. +//// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//// +////===----------------------------------------------------------------------===// +//// +//// This file defines target verifier interfaces that can be used for some +//// validation of input to the system, and for checking that transformations +//// haven't done something bad. In contrast to the Verifier or Lint, the +//// TargetVerifier looks for constructions invalid to a particular target +//// machine. +//// +//// To see what specifically is checked, look at an individual backend's +//// TargetVerifier. +//// +////===----------------------------------------------------------------------===// + #include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" #include "llvm/Analysis/UniformityAnalysis.h" @@ -25,19 +44,6 @@ using namespace llvm; } while (false) namespace llvm { -/*class AMDGPUTargetVerify : public TargetVerify { -public: - Module *Mod; - - DominatorTree *DT; - PostDominatorTree *PDT; - UniformityInfo *UA; - - AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA) - : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {} - - void run(Function &F); -};*/ static bool IsValidInt(const Type *Ty) { return Ty->isIntegerTy(1) || @@ -147,7 +153,7 @@ struct AMDGPUTargetVerifierLegacyPass : public FunctionPass { } bool runOnFunction(Function &F) override { - if (TV->run(F) && FatalErrors) { + if (!TV->run(F) && FatalErrors) { errs() << "in function " << F.getName() << '\n'; report_fatal_error("Broken function found, compilation aborted!"); } @@ -160,7 +166,6 @@ struct AMDGPUTargetVerifierLegacyPass : public FunctionPass { if (F.isDeclaration()) IsValid &= TV->run(F); - //IsValid &= TV->run(); if (FatalErrors && !IsValid) report_fatal_error("Broken module found, compilation aborted!"); return false; diff --git a/llvm/lib/Target/TargetVerifier.cpp b/llvm/lib/Target/TargetVerifier.cpp index de3ff749e7c3c..992a0c91d93b1 100644 --- a/llvm/lib/Target/TargetVerifier.cpp +++ b/llvm/lib/Target/TargetVerifier.cpp @@ -1,3 +1,22 @@ +//===-- TargetVerifier.cpp - LLVM IR Target Verifier ----------------*- C++ -*-===// +//// +///// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +///// See https://llvm.org/LICENSE.txt for license information. +///// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +///// +/////===----------------------------------------------------------------------===// +///// +///// This file defines target verifier interfaces that can be used for some +///// validation of input to the system, and for checking that transformations +///// haven't done something bad. In contrast to the Verifier or Lint, the +///// TargetVerifier looks for constructions invalid to a particular target +///// machine. +///// +///// To see what specifically is checked, look at TargetVerifier.cpp or an +///// individual backend's TargetVerifier. +///// +/////===----------------------------------------------------------------------===// + #include "llvm/Target/TargetVerifier.h" #include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h" diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp index a060d16e74958..a8f6b999af06e 100644 --- a/llvm/tools/llc/NewPMDriver.cpp +++ b/llvm/tools/llc/NewPMDriver.cpp @@ -114,6 +114,8 @@ int llvm::compileModuleWithNewPM( VK == VerifierKind::EachPass); registerCodeGenCallback(PIC, *Target); + ModulePassManager MPM; + FunctionPassManager FPM; MachineFunctionAnalysisManager MFAM; LoopAnalysisManager LAM; FunctionAnalysisManager FAM; @@ -125,15 +127,13 @@ int llvm::compileModuleWithNewPM( PB.registerFunctionAnalyses(FAM); PB.registerLoopAnalyses(LAM); PB.registerMachineFunctionAnalyses(MFAM); + PB.registerVerifierPasses(MPM, FPM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); SI.registerCallbacks(PIC, &MAM, &FAM); FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); - ModulePassManager MPM; - FunctionPassManager FPM; - if (!PassPipeline.empty()) { // Construct a custom pass pipeline that starts after instruction // selection. diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp index 503db7b1f8d18..b00bab66c6c3e 100644 --- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp +++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp @@ -1,4 +1,4 @@ -//===--- llvm-isel-fuzzer.cpp - Fuzzer for instruction selection ----------===// +//===--- llvm-tgt-verify.cpp - Target Verifier ----------------- ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// Tool to fuzz instruction selection using libFuzzer. +// Tool to verify a target. // //===----------------------------------------------------------------------===// @@ -144,14 +144,11 @@ int main(int argc, char **argv) { PB.registerCGSCCAnalyses(CGAM); PB.registerFunctionAnalyses(FAM); PB.registerLoopAnalyses(LAM); - //PB.registerVerifierPasses(MPM, FPM); PB.registerMachineFunctionAnalyses(MFAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM); SI.registerCallbacks(PIC, &MAM, &FAM); - //FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); - Triple TT(M->getTargetTriple()); if (!NoLint) FPM.addPass(LintPass(false)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits