Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d9b0a5d
[TargetVerifier][AMDGPU] Add TargetVerifier.
jofrn Jan 20, 2025
3b69ade
Add hook for target verifier in llc,opt
jofrn Feb 3, 2025
a89ff83
Run AMDGPUTargetVerifier within AMDGPU pipeline. Move IsValid from
jofrn Apr 16, 2025
df507f9
Remove cmd line options that aren't required. Make error message expl…
jofrn Apr 16, 2025
942312d
Return Verifier none status through PreservedAnalyses on fail.
jofrn Apr 19, 2025
6216a10
Rebase update.
jofrn Apr 20, 2025
4b7068f
Add generic TargetVerifier.
jofrn Apr 20, 2025
86e8066
Remove store to const check since it is in Lint already
jofrn Apr 20, 2025
17fc5c6
Add chain followed by unreachable check
jofrn Apr 20, 2025
46e662c
Remove mfma check
jofrn Apr 20, 2025
7e471c9
Add registerVerifierPasses to PassBuilder and add the verifier passes…
jofrn Apr 22, 2025
1538985
Remove leftovers. Add titles. Add call to registerVerifierCallbacks i…
jofrn Apr 22, 2025
32b0c0d
Add pass to legacy PM.
jofrn Apr 24, 2025
387b2d5
Add fam in other projects.
jofrn Apr 26, 2025
d2c9425
Avoid fatal errors in llc.
jofrn Apr 26, 2025
31a79a5
Add tool to build/test.
jofrn Apr 26, 2025
b51b530
Cleanup of unrequired functions.
jofrn Apr 28, 2025
d41d5f9
Make virtual.
jofrn Apr 28, 2025
7ece5e2
Remove from legacy PM. Add to target dependent pipeline.
jofrn Apr 30, 2025
42b8982
Add back to legacy PM.
jofrn Apr 30, 2025
230f33b
Remove reference to FAM in registerCallbacks and VerifyEach for Targe…
jofrn Apr 30, 2025
c680041
Remove references to registry
jofrn Apr 30, 2025
3f5634a
Remove int check
jofrn Apr 30, 2025
6007895
Remove modifications to Lint/Verifier.
jofrn May 1, 2025
756c3eb
Remove llvm-tgt-verify tool.
jofrn May 1, 2025
3f1d72f
Remove TargetVerifier.cpp
jofrn May 1, 2025
1c721cf
clang-format
jofrn May 1, 2025
f59b0f2
Add VerifyTarget option
jofrn May 1, 2025
f0f12f5
Remove AMDGPUTargetVerifier.h
jofrn May 8, 2025
88a6d6b
Remove analyses.
jofrn May 8, 2025
0d99a65
function name style, TargetVerifier comment, option name generality
jofrn May 8, 2025
79215be
Fix after rebase
jofrn Jun 16, 2025
f25ecf1
Add back int check. These are invalid for AMDGPU.
jofrn Jul 8, 2025
cab7d2e
Merge branch 'main' into tgt-verifier
jofrn Jul 14, 2025
d2aa0dc
Fixups: style, format, test removal
jofrn Jul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions llvm/include/llvm/Target/TargetVerifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//===-- 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 an individual backend's
// TargetVerifier.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TARGET_VERIFIER_H
#define LLVM_TARGET_VERIFIER_H

#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/TargetParser/Triple.h"

namespace llvm {

class Function;

class TargetVerifierPass : public PassInfoMixin<TargetVerifierPass> {
public:
virtual PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) = 0;
};

class TargetVerify {
protected:
void writeValues(ArrayRef<const Value *> Vs) {
for (const Value *V : Vs) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rename this to something more accurate because currently I don't know where it writes to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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;

bool IsValid = true;

TargetVerify(Module *Mod)
: Mod(Mod), TT(Mod->getTargetTriple()), MessagesStr(Messages) {}

virtual bool run(Function &F) = 0;
};

} // namespace llvm

#endif // LLVM_TARGET_VERIFIER_H
7 changes: 7 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/Pass.h"
#include "llvm/Support/AMDGPUAddrSpace.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetVerifier.h"

namespace llvm {

Expand Down Expand Up @@ -538,6 +539,12 @@ extern char &GCNRewritePartialRegUsesID;
void initializeAMDGPUWaitSGPRHazardsLegacyPass(PassRegistry &);
extern char &AMDGPUWaitSGPRHazardsLegacyID;

FunctionPass *createAMDGPUTargetVerifierLegacyPass(bool FatalErrors);
void initializeAMDGPUTargetVerifierLegacyPassPass(PassRegistry &);
struct AMDGPUTargetVerifierPass : public TargetVerifierPass {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) override;
};

class AMDGPURewriteAGPRCopyMFMAPass
: public PassInfoMixin<AMDGPURewriteAGPRCopyMFMAPass> {
public:
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,9 @@ static cl::opt<bool> HasClosedWorldAssumption(
cl::desc("Whether has closed-world assumption at link time"),
cl::init(false), cl::Hidden);

static cl::opt<bool> VerifyTarget("amdgpu-verify-tgt",
cl::desc("Enable the target verifier"));

extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUTarget() {
// Register the target
RegisterTargetMachine<R600TargetMachine> X(getTheR600Target());
Expand Down Expand Up @@ -1410,6 +1413,8 @@ bool AMDGPUPassConfig::addGCPasses() {
//===----------------------------------------------------------------------===//

bool GCNPassConfig::addPreISel() {
if (VerifyTarget)
addPass(createAMDGPUTargetVerifierLegacyPass(false));
AMDGPUPassConfig::addPreISel();

if (TM->getOptLevel() > CodeGenOptLevel::None)
Expand Down Expand Up @@ -2011,6 +2016,9 @@ AMDGPUCodeGenPassBuilder::AMDGPUCodeGenPassBuilder(
}

void AMDGPUCodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const {
if (VerifyTarget)
addPass(AMDGPUTargetVerifierPass());

if (RemoveIncompatibleFunctions && TM.getTargetTriple().isAMDGCN())
addPass(AMDGPURemoveIncompatibleFunctionsPass(TM));

Expand Down
146 changes: 146 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
//===-- 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 "AMDGPU.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/Debug.h"

#include "llvm/Support/raw_ostream.h"

using namespace llvm;

// Check - We know that cond should be true, if not print an error message.
#define Check(C, ...) \
do { \
if (!(C)) { \
TargetVerify::checkFailed(__VA_ARGS__); \
} \
} while (false)

namespace llvm {

class AMDGPUTargetVerify : public TargetVerify {
public:
AMDGPUTargetVerify(Module *Mod) : TargetVerify(Mod) {}
bool run(Function &F) override;
};

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);
}

bool AMDGPUTargetVerify::run(Function &F) {

for (auto &BB : F) {

for (auto &I : BB) {

// 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));
}
}

dbgs() << MessagesStr.str();
if (!MessagesStr.str().empty()) {
IsValid = false;
return false;
}
return true;
}

PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F,
FunctionAnalysisManager &AM) {
auto *Mod = F.getParent();

AMDGPUTargetVerify TV(Mod);
TV.run(F);

dbgs() << TV.MessagesStr.str();
if (!TV.MessagesStr.str().empty()) {
TV.IsValid = false;
return PreservedAnalyses::none();
}
return PreservedAnalyses::all();
}

struct AMDGPUTargetVerifierLegacyPass : public FunctionPass {
static char ID;

std::unique_ptr<AMDGPUTargetVerify> TV;
bool FatalErrors = false;

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)) {
errs() << "in function " << F.getName() << '\n';
if (FatalErrors)
report_fatal_error("broken function found, compilation aborted!");
else
errs() << "broken function found, compilation aborted!\n";
}
return false;
}

bool doFinalization(Module &M) override {
bool IsValid = true;
for (Function &F : M)
if (F.isDeclaration())
IsValid &= TV->run(F);

if (!IsValid) {
if (FatalErrors)
report_fatal_error("broken module found, compilation aborted!");
else
errs() << "broken module found, compilation aborted!\n";
}
return false;
}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
char AMDGPUTargetVerifierLegacyPass::ID = 0;
FunctionPass *createAMDGPUTargetVerifierLegacyPass(bool FatalErrors) {
return new AMDGPUTargetVerifierLegacyPass(FatalErrors);
}
} // namespace llvm
INITIALIZE_PASS(AMDGPUTargetVerifierLegacyPass, "amdgpu-tgtverifier",
"AMDGPU Target Verifier", false, false)
1 change: 1 addition & 0 deletions llvm/lib/Target/AMDGPU/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ add_llvm_target(AMDGPUCodeGen
AMDGPUTargetMachine.cpp
AMDGPUTargetObjectFile.cpp
AMDGPUTargetTransformInfo.cpp
AMDGPUTargetVerifier.cpp
AMDGPUWaitSGPRHazards.cpp
AMDGPUUnifyDivergentExitNodes.cpp
AMDGPUUnifyMetadata.cpp
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/Verifier/AMDGPU/tgt-verify-int-type.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -amdgpu-verify-tgt -o - < %s 2>&1 | FileCheck %s

define amdgpu_cs i65 @invalid_int() {
; CHECK: int type is invalid.
ret i65 0
}