60#include "llvm/Support/Debug.h"
64#define GEN_PASS_DEF_OFFLOADTARGETVERIFIER
65#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
69#define DEBUG_TYPE "offload-target-verifier"
75class OffloadTargetVerifier
78 using OffloadTargetVerifierBase::OffloadTargetVerifierBase;
81 bool isHostTarget()
const {
82 return deviceType == acc::DeviceType::Host ||
83 deviceType == acc::DeviceType::Multicore;
90 auto isInvalid = [&](
Value val) ->
bool {
106 if (!symUses.has_value())
112 symUse.getSymbolRef(), &definingOp);
116 llvm::make_filter_range(symUses.value(), isInvalidSymbol);
118 return invalidSymsList;
122 bool hasIllegalLiveInValues(
Operation *regionOp,
129 getIllegalLiveInValues(regionOp->
getRegion(0), liveness, accSupport);
131 bool hasIllegalValues = !invalidValues.empty();
133 if (hasIllegalValues) {
137 << invalidValues.size() <<
" illegal live-in value(s)";
138 for (
auto [idx, invalidValue] : llvm::enumerate(invalidValues)) {
139 diag.attachNote(invalidValue.getLoc()) <<
"value: " << invalidValue;
143 "offload target verifier failed due to " +
144 Twine(invalidValues.size()) +
145 " illegal live-in value(s)");
149 return hasIllegalValues;
153 bool hasIllegalSymbolUses(
Operation *regionOp,
159 getIllegalUsedSymbols(regionOp->
getRegion(0), accSupport);
161 bool hasIllegalSymbols = !invalidSyms.empty();
163 if (hasIllegalSymbols) {
165 return symUse.getSymbolRef().getLeafReference().str();
167 std::string invalidString =
168 llvm::join(llvm::map_range(invalidSyms, getSymName),
", ");
172 regionOp->
emitWarning(
"offload target verifier: illegal symbol(s): ")
176 "offload target verifier failed due to illegal "
181 return hasIllegalSymbols;
184 void runOnOperation()
override {
185 LLVM_DEBUG(llvm::dbgs() <<
"Enter OffloadTargetVerifier()\n");
186 func::FuncOp
func = getOperation();
189 auto cachedAnalysis =
190 getCachedParentAnalysis<acc::OpenACCSupport>(
func->getParentOp());
192 ? cachedAnalysis->get()
193 : getAnalysis<acc::OpenACCSupport>();
195 bool hasErrors =
false;
199 if (!isa<acc::OffloadRegionOpInterface>(op))
204 if (isHostTarget() && isa<ACC_COMPUTE_CONSTRUCT_OPS>(op)) {
206 "host/multicore verification for ACC compute "
212 bool hasIllegalValues = hasIllegalLiveInValues(op, accSupport);
213 if (hasIllegalValues)
217 bool hasIllegalSyms = hasIllegalSymbolUses(op, accSupport);
221 if (!hasIllegalValues && !hasIllegalSyms && softCheck)
222 op->
emitRemark(
"offload target verifier: passed validity check");
227 if (hasErrors && !softCheck)
230 LLVM_DEBUG(llvm::dbgs() <<
"Exit OffloadTargetVerifier()\n");
static std::string diag(const llvm::Value &value)
Represents an analysis for computing liveness information from a given top-level operation.
const ValueSetT & getLiveIn(Block *block) const
Returns a reference to a set containing live-in values (unordered).
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class represents a specific symbol use.
static std::optional< UseRange > getSymbolUses(Operation *from)
Get an iterator range for all of the uses, for any symbol, that are nested within the given operation...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
static WalkResult advance()
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
bool isValidValueUse(Value v, Region ®ion)
Check if a value use is legal in an OpenACC region.
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr=nullptr)
Check if a symbol use is valid for use in an OpenACC region.
Include the generated interface declarations.