22#define GEN_PASS_DEF_HOSTOPFILTERINGPASS
23#include "mlir/Dialect/OpenMP/Transforms/Passes.h.inc"
49 for (
Value member : mapOp.getMembers())
50 collectRewrite(cast<omp::MapInfoOp>(member.getDefiningOp()), rewrites);
52 rewrites.insert(mapOp);
62 if ((isa<BlockArgument>(value) &&
63 isa<FunctionOpInterface>(
64 cast<BlockArgument>(value).getOwner()->getParentOp())) ||
65 rewrites.contains(value))
73 rewrites.insert(value);
78static std::optional<omp::DeclareTargetDeviceType>
80 auto declareTargetOp = dyn_cast<omp::DeclareTargetInterface>(op);
81 if (declareTargetOp && declareTargetOp.isDeclareTarget())
82 return declareTargetOp.getDeclareTargetDeviceType();
87class HostOpFilteringPass
90 HostOpFilteringPass() =
default;
92 void runOnOperation()
override {
93 auto op = dyn_cast<omp::OffloadModuleInterface>(getOperation());
94 if (!op || !op.getIsTargetDevice())
98 omp::DeclareTargetDeviceType declareType =
100 .value_or(omp::DeclareTargetDeviceType::host);
103 if (funcOp.isExternal() ||
104 declareType != omp::DeclareTargetDeviceType::host)
107 if (failed(rewriteHostFunction(funcOp))) {
108 funcOp.emitOpError() <<
"could not filter host-only operations";
118 op->
walk([&](LLVM::GlobalOp globalOp) {
120 globalOp.setLinkage(LLVM::Linkage::Internal);
153 LogicalResult rewriteHostFunction(LLVM::LLVMFuncOp funcOp) {
154 Region ®ion = funcOp.getFunctionBody();
155 LLVM::LLVMFunctionType functionType = funcOp.getFunctionType();
161 if (
auto targetOp = dyn_cast<omp::TargetOp>(op)) {
162 targetOps.push_back(targetOp);
170 if (
auto targetDataOp = dyn_cast<omp::TargetDataOp>(op)) {
172 cast<omp::BlockArgOpenMPOpInterface>(*targetDataOp)
173 .getBlockArgsPairs(argPairs);
174 for (
auto [operand, blockArg] : argPairs) {
175 auto mapInfo = cast<omp::MapInfoOp>(operand.getDefiningOp());
176 blockArg.replaceAllUsesWith(mapInfo.getVarPtr());
187 builder.setInsertionPointAfter(funcOp);
193 llvm::transform(region.
getArguments(), std::back_inserter(locs),
197 for (
auto [oldArg, newArg] :
199 oldArg.replaceAllUsesWith(newArg);
207 for (omp::TargetOp targetOp : targetOps) {
208 assert(targetOp.getHostEvalVars().empty() &&
209 "unexpected host_eval in target device module");
212 targetOp.getDependVarsMutable().clear();
213 targetOp.setDependKindsAttr(
nullptr);
214 targetOp.getDependIteratedMutable().clear();
215 targetOp.setDependIteratedKindsAttr(
nullptr);
216 targetOp.getDeviceMutable().clear();
217 targetOp.getDynGroupprivateSizeMutable().clear();
218 targetOp.getIfExprMutable().clear();
219 targetOp.getInReductionVarsMutable().clear();
220 targetOp.setInReductionByrefAttr(
nullptr);
221 targetOp.setInReductionSymsAttr(
nullptr);
226 for (
Value allocVar : targetOp.getAllocateVars())
228 for (
Value allocVar : targetOp.getAllocatorVars())
230 for (
Value isDevPtr : targetOp.getIsDevicePtrVars())
232 for (
Value mapVar : targetOp.getHasDeviceAddrVars())
233 collectRewrite(cast<omp::MapInfoOp>(mapVar.getDefiningOp()), mapInfos);
234 for (
Value mapVar : targetOp.getMapVars())
235 collectRewrite(cast<omp::MapInfoOp>(mapVar.getDefiningOp()), mapInfos);
236 for (
Value privateVar : targetOp.getPrivateVars())
238 for (
Value threadLimit : targetOp.getThreadLimitVars())
243 for (omp::MapInfoOp mapOp : mapInfos) {
246 if (
Value varPtrPtr = mapOp.getVarPtrPtr())
250 mapOp.getBoundsMutable().clear();
251 mapOp->moveBefore(&block, block.
end());
254 builder.setInsertionPointToStart(&block);
260 for (
Value value : rewriteValues) {
264 rewriteValue = builder.clone(*value.
getDefiningOp())->getResult(0);
267 newFnArgTypes.push_back(rewriteValue.
getType());
273 for (omp::TargetOp targetOp : targetOps)
274 targetOp->moveBefore(&block, block.
end());
277 builder.setInsertionPointToEnd(&block);
278 LLVM::ReturnOp::create(builder, funcOp.getLoc(),
ValueRange());
286 funcOp.setType(LLVM::LLVMFunctionType::get(
287 LLVM::LLVMVoidType::get(&
getContext()), newFnArgTypes));
static std::optional< omp::DeclareTargetDeviceType > getDeclareTargetDevice(Operation &op)
Provide the device_type of an omp.declare_target attribute, if defined.
static bool keepHostOpInDevice(Operation &op)
Some host operations, like llvm.mlir.addressof and constants, must remain in the device module becaus...
static void collectRewrite(omp::MapInfoOp mapOp, llvm::SetVector< omp::MapInfoOp > &rewrites)
Add an omp.map.info operation and all its members recursively to the output set to be later rewritten...
This class represents an argument of a Block.
Block represents an ordered list of Operations.
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
BlockArgListType getArguments()
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Operation * cloneWithoutRegions(IRMapping &mapper)
Create a partial copy of this operation without traversing into attached regions.
operand_range getOperands()
Returns an iterator on the underlying Value's.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
MLIRContext * getContext()
Return the context this operation is associated with.
void erase()
Remove this operation from its parent block and delete it.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
unsigned getNumArguments()
ValueTypeRange< BlockArgListType > getArgumentTypes()
Returns the argument types of the first block within the region.
void takeBody(Region &other)
Takes body of another region (that region will have no body after this operation completes).
RetT walk(FnT &&callback)
Walk all nested operations, blocks or regions (including this region), depending on the type of callb...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
void replaceAllUsesWith(Value newValue)
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static WalkResult advance()
static WalkResult interrupt()
Include the generated interface declarations.
bool isPure(Operation *op)
Returns true if the given operation is pure, i.e., is speculatable that does not touch memory.