61#include "llvm/Support/Debug.h"
65#define GEN_PASS_DEF_OFFLOADTARGETVERIFIER
66#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
70#define DEBUG_TYPE "offload-target-verifier"
75class OffloadTargetVerifier
78 using OffloadTargetVerifierBase::OffloadTargetVerifierBase;
81 OffloadTargetVerifierBase::getDependentDialects(registry);
86 bool isHostTarget()
const {
87 return deviceType == acc::DeviceType::Host ||
88 deviceType == acc::DeviceType::Multicore;
95 auto isInvalid = [&](
Value val) ->
bool {
102 return illegalValues;
111 if (!symUses.has_value())
117 symUse.getSymbolRef(), &definingOp);
121 llvm::make_filter_range(symUses.value(), isInvalidSymbol);
123 return invalidSymsList;
130 names.reserve(values.size());
131 for (
Value value : values)
137 bool hasIllegalLiveInValues(
Operation *regionOp,
144 getIllegalLiveInValues(regionOp->
getRegion(0), liveness, accSupport);
146 bool hasIllegalValues = !invalidValues.empty();
148 if (hasIllegalValues) {
150 getVariableNames(invalidValues, accSupport);
155 << invalidValues.size() <<
" illegal live-in value(s)";
156 for (
auto [invalidValue, name] :
157 llvm::zip(invalidValues, invalidVarNames)) {
159 diag.attachNote(invalidValue.getLoc()) <<
"value: " << invalidValue;
161 diag.attachNote(invalidValue.getLoc())
162 <<
"value: " << invalidValue <<
", name: " << name;
166 std::string message =
"offload target verifier failed due to " +
167 std::to_string(invalidValues.size()) +
168 " illegal live-in value(s)";
170 for (
const std::string &name : invalidVarNames)
172 availableVarNames.push_back(name);
173 if (!availableVarNames.empty())
174 message +=
" including: " + llvm::join(availableVarNames,
", ");
179 return hasIllegalValues;
183 bool hasIllegalSymbolUses(
Operation *regionOp,
189 getIllegalUsedSymbols(regionOp->
getRegion(0), accSupport);
191 bool hasIllegalSymbols = !invalidSyms.empty();
193 if (hasIllegalSymbols) {
195 return symUse.getSymbolRef().getLeafReference().str();
197 std::string invalidString =
198 llvm::join(llvm::map_range(invalidSyms, getSymName),
", ");
202 regionOp->
emitWarning(
"offload target verifier: illegal symbol(s): ")
206 "offload target verifier failed due to illegal "
211 return hasIllegalSymbols;
214 void runOnOperation()
override {
215 LLVM_DEBUG(llvm::dbgs() <<
"Enter OffloadTargetVerifier()\n");
216 func::FuncOp
func = getOperation();
219 auto cachedAnalysis =
220 getCachedParentAnalysis<acc::OpenACCSupport>(
func->getParentOp());
222 ? cachedAnalysis->get()
223 : getAnalysis<acc::OpenACCSupport>();
225 bool hasErrors =
false;
229 if (!isa<acc::OffloadRegionOpInterface>(op))
234 if (isHostTarget() && isa<ACC_COMPUTE_CONSTRUCT_OPS>(op)) {
236 "host/multicore verification for ACC compute "
242 bool hasIllegalValues = hasIllegalLiveInValues(op, accSupport);
243 if (hasIllegalValues)
247 bool hasIllegalSyms = hasIllegalSymbolUses(op, accSupport);
251 if (!hasIllegalValues && !hasIllegalSyms && softCheck)
252 op->
emitRemark(
"offload target verifier: passed validity check");
257 if (hasErrors && !softCheck)
260 LLVM_DEBUG(llvm::dbgs() <<
"Exit OffloadTargetVerifier()\n");
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
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()
std::string getVariableName(Value v, VariableNameConfig config={})
Get the variable name for a given value.
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.
void registerAllExtensions(DialectRegistry ®istry)
Register the standard OpenACC models for GPU, LLVM and MemRef IR.
Include the generated interface declarations.