[clang] [llvm] [TargetVerifier][AMDGPU] Add TargetVerifier. (PR #123609)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 22 12:00:43 PDT 2025


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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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.Fernau at 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 485f05c9cec652de56c72ee110a5187490d09199 Mon Sep 17 00:00:00 2001
From: jofernau <Joe.Fernau at 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.

---
 .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp |  4 ---
 .../Target/AMDGPU/AMDGPUTargetVerifier.cpp    | 32 +++++++++++--------
 llvm/lib/Target/TargetVerifier.cpp            | 19 +++++++++++
 llvm/tools/llc/NewPMDriver.cpp                |  1 +
 .../tools/llvm-tgt-verify/llvm-tgt-verify.cpp |  7 ++--
 5 files changed, 41 insertions(+), 22 deletions(-)

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..34cc41d111747 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) ||
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..0c6352d1925ed 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -125,6 +125,7 @@ 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);
 
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));



More information about the llvm-commits mailing list