MLIR 24.0.0git
FunctionFiltering.cpp
Go to the documentation of this file.
1//===- FunctionFiltering.cpp ----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Filter out functions intended for the host when compiling for a target
10// device.
11//
12//===----------------------------------------------------------------------===//
13
15
18#include "mlir/IR/Operation.h"
20
21namespace mlir {
22namespace omp {
24#define GEN_PASS_DEF_FUNCTIONFILTERINGPASS
25#include "mlir/Dialect/OpenMP/Transforms/Passes.h.inc"
26
27} // namespace omp
28} // namespace mlir
30using namespace mlir;
32namespace {
34class FunctionFilteringPass
35 : public omp::impl::FunctionFilteringPassBase<FunctionFilteringPass> {
37 void runOnOperation() override {
38 auto op = dyn_cast<omp::OffloadModuleInterface>(getOperation());
39 if (!op || !op.getIsTargetDevice())
40 return;
42 OpBuilder opBuilder(&getContext());
43 op->walk<WalkOrder::PreOrder>([&](FunctionOpInterface funcOp) {
44 // Do not filter functions with target regions inside, because they have
45 // to be available for both host and device so that regular and reverse
46 // offloading can be supported.
47 bool hasTargetRegion =
48 funcOp
49 ->walk<WalkOrder::PreOrder>([&](omp::TargetOp targetOp) {
50 return WalkResult::interrupt();
51 })
52 .wasInterrupted();
53
54 omp::DeclareTargetDeviceType declareType =
55 omp::DeclareTargetDeviceType::host;
56 auto declareTargetOp =
57 dyn_cast<omp::DeclareTargetInterface>(funcOp.getOperation());
58 omp::DeclareTargetAttr declareTargetAttr =
59 declareTargetOp ? declareTargetOp.getDeclareTarget() : nullptr;
60 if (declareTargetAttr)
61 declareType = declareTargetAttr.getDeviceType();
62
63 // Only filter host functions from device modules because the host needs
64 // to provide fallback implementations of device code.
65 if (declareType != omp::DeclareTargetDeviceType::host)
66 return WalkResult::advance();
67
68 SymbolTable::UseRange funcUses = *funcOp.getSymbolUses(op);
69 for (SymbolTable::SymbolUse use : funcUses) {
70 Operation *callOp = use.getUser();
71
72 // Do not delete other functions (which may be device functions) holding
73 // the symbol of a host function as an attribute. The remaining
74 // attribute will point to an undefined symbol after this pass.
75 if (isa<FunctionOpInterface>(callOp))
76 continue;
78 // If the callOp has users then replace them with poison values before
79 // removing it. These should get removed before translation to LLVM IR
80 // by the host op filtering pass.
81 if (!callOp->use_empty()) {
82 SmallVector<Value> poisonResults;
83 for (Value res : callOp->getResults()) {
84 opBuilder.setInsertionPoint(callOp);
85 poisonResults.emplace_back(
86 LLVM::PoisonOp::create(opBuilder, res.getLoc(), res.getType()));
87 }
88 callOp->replaceAllUsesWith(poisonResults);
89 }
90
91 callOp->erase();
92 }
93
94 if (!hasTargetRegion) {
95 funcOp.erase();
96 return WalkResult::skip();
97 }
98
99 // MLIR to LLVM IR translation relies on host functions being explicitly
100 // marked as such to perform the second stage removal them from the device
101 // module, where functions that contain target regions are deleted from
102 // the generated LLVM IR.
103 if (declareTargetOp && !declareTargetAttr)
104 declareTargetOp.setDeclareTarget(omp::DeclareTargetDeviceType::host,
105 omp::DeclareTargetCaptureClause::to,
106 /*automap=*/false, /*implicit=*/true);
107 return WalkResult::advance();
108 });
109 }
110};
111
112} // namespace
b getContext())
This class helps build Operations.
Definition Builders.h:210
OpT getOperation()
Return the current operation being transformed.
Definition Pass.h:389
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
bool use_empty()
Returns true if this operation has no uses.
Definition Operation.h:904
void replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this operation with the provided 'values'.
Definition Operation.h:297
result_range getResults()
Definition Operation.h:440
void erase()
Remove this operation from its parent block and delete it.
virtual void runOnOperation()=0
The polymorphic API that runs the pass over the currently held operation.
This class represents a specific symbol use.
This class implements a range of SymbolRef uses.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
static WalkResult skip()
Definition WalkResult.h:48
static WalkResult advance()
Definition WalkResult.h:47
static WalkResult interrupt()
Definition WalkResult.h:46
Include the generated interface declarations.