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;
125 names.reserve(values.size());
126 for (
Value value : values)
132 bool hasIllegalLiveInValues(
Operation *regionOp,
139 getIllegalLiveInValues(regionOp->
getRegion(0), liveness, accSupport);
141 bool hasIllegalValues = !invalidValues.empty();
143 if (hasIllegalValues) {
145 getVariableNames(invalidValues, accSupport);
150 << invalidValues.size() <<
" illegal live-in value(s)";
151 for (
auto [invalidValue, name] :
152 llvm::zip(invalidValues, invalidVarNames)) {
154 diag.attachNote(invalidValue.getLoc()) <<
"value: " << invalidValue;
156 diag.attachNote(invalidValue.getLoc())
157 <<
"value: " << invalidValue <<
", name: " << name;
161 std::string message =
"offload target verifier failed due to " +
162 std::to_string(invalidValues.size()) +
163 " illegal live-in value(s)";
165 for (
const std::string &name : invalidVarNames)
167 availableVarNames.push_back(name);
168 if (!availableVarNames.empty())
169 message +=
" including: " + llvm::join(availableVarNames,
", ");
174 return hasIllegalValues;
178 bool hasIllegalSymbolUses(
Operation *regionOp,
184 getIllegalUsedSymbols(regionOp->
getRegion(0), accSupport);
186 bool hasIllegalSymbols = !invalidSyms.empty();
188 if (hasIllegalSymbols) {
190 return symUse.getSymbolRef().getLeafReference().str();
192 std::string invalidString =
193 llvm::join(llvm::map_range(invalidSyms, getSymName),
", ");
197 regionOp->
emitWarning(
"offload target verifier: illegal symbol(s): ")
201 "offload target verifier failed due to illegal "
206 return hasIllegalSymbols;
209 void runOnOperation()
override {
210 LLVM_DEBUG(llvm::dbgs() <<
"Enter OffloadTargetVerifier()\n");
211 func::FuncOp
func = getOperation();
214 auto cachedAnalysis =
215 getCachedParentAnalysis<acc::OpenACCSupport>(
func->getParentOp());
217 ? cachedAnalysis->get()
218 : getAnalysis<acc::OpenACCSupport>();
220 bool hasErrors =
false;
224 if (!isa<acc::OffloadRegionOpInterface>(op))
229 if (isHostTarget() && isa<ACC_COMPUTE_CONSTRUCT_OPS>(op)) {
231 "host/multicore verification for ACC compute "
237 bool hasIllegalValues = hasIllegalLiveInValues(op, accSupport);
238 if (hasIllegalValues)
242 bool hasIllegalSyms = hasIllegalSymbolUses(op, accSupport);
246 if (!hasIllegalValues && !hasIllegalSyms && softCheck)
247 op->
emitRemark(
"offload target verifier: passed validity check");
252 if (hasErrors && !softCheck)
255 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.
std::string getVariableName(Value v)
Get the variable name for a given value.
Include the generated interface declarations.