1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2023-2024 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
//===----------------------------------------------------------------------===//
// GenXVerify
//===----------------------------------------------------------------------===//
//
// This pass contains GenX-specific IR validity checks.
//
#include "GenXVerify.h"
bool GenXVerify::doInitialization(Module &M) {
Ctx = &M.getContext();
return false;
}
StringRef GenXVerify::getPassName() const {
return "GenX IR verification pass.";
}
void GenXVerify::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
bool GenXVerify::ensure(const bool Cond, const Twine &Msg, const Value &V,
const IsFatal IsFatal_) {
if (LLVM_LIKELY(Cond))
return true;
if (IsFatal_ == IsFatal::Yes || OptAllFatal || !OptQuietNonFatal)
vc::diagnose(V.getContext(),
DbgPrefix + "[stage:" +
OptStage.getParser().getOption(
static_cast<int>(OptStage.getValue())) +
"]" +
(IsFatal_ == IsFatal::No
? " (non-fatal, spec review required)"
: ""),
Msg, DS_Warning, vc::WarningName::Generic, &V);
if (IsFatal_ == IsFatal::Yes || OptAllFatal) {
IsBroken = true;
if (OptTerminationPolicy == Terminate::OnFirstError)
terminate();
}
return false;
}
[[noreturn]] void GenXVerify::terminate() {
llvm::report_fatal_error(DbgPrefix + "failed, check log for details.");
}
bool GenXVerify::runOnModule(Module &M) {
visit(M);
if (Stage == GenXVerifyStage::PostIrAdaptors)
for (const auto &GV : M.globals())
visitGlobalVariable(GV);
if (OptTerminationPolicy != Terminate::No && IsBroken)
terminate();
return false;
}
void GenXVerify::visitGlobalVariable(const GlobalVariable &GV){
if (!GV.hasAttribute(genx::FunctionMD::GenXVolatile))
return;
ensure(GV.getAddressSpace() == vc::AddrSpace::Private,
"a volatile variable must reside in private address space", GV);
auto InvalidUser = llvm::find_if(GV.users(), [](const User *U) {
const auto *I = dyn_cast<Instruction>(genx::peelBitCastsWhileSingleUserChain(U));
return !I || !(genx::isAVStore(I) || genx::isAVLoad(I));
});
if (InvalidUser == GV.user_end())
return;
ensure(false,
"a volatile variable may only be used in genx.vload/genx.vstore "
"intrinsics and volatile loads/stores instructions",
**InvalidUser);
};
void GenXVerify::visitCallInst(const CallInst &CI) {
const unsigned IntrinsicId = vc::getAnyIntrinsicID(&CI);
switch (IntrinsicId) {
case GenXIntrinsic::genx_rdregionf:
case GenXIntrinsic::genx_rdregioni:
case GenXIntrinsic::genx_rdpredregion:
case GenXIntrinsic::genx_wrregionf:
case GenXIntrinsic::genx_wrregioni:
case GenXIntrinsic::genx_wrpredregion:
case GenXIntrinsic::genx_wrconstregion:
case GenXIntrinsic::genx_wrpredpredregion:
verifyRegioning(CI, IntrinsicId);
break;
};
}
namespace llvm {
void initializeGenXVerifyPass(PassRegistry &);
} // namespace llvm
INITIALIZE_PASS_BEGIN(GenXVerify, "GenXVerify", "GenX IR verification", false,
false)
INITIALIZE_PASS_END(GenXVerify, "GenXVerify", "GenX IR verification", false,
false)
ModulePass *llvm::createGenXVerifyPass(GenXVerifyStage ValidityInvariantsSet) {
initializeGenXVerifyPass(*PassRegistry::getPassRegistry());
return new GenXVerify(ValidityInvariantsSet);
}
|