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 {
23
24#define GEN_PASS_DEF_FUNCTIONFILTERINGPASS
25#include "mlir/Dialect/OpenMP/Transforms/Passes.h.inc"
26
27} // namespace omp
28} // namespace mlir
29
30using namespace mlir;
31
32namespace {
33
34class FunctionFilteringPass
35 : public omp::impl::FunctionFilteringPassBase<FunctionFilteringPass> {
36
37 void runOnOperation() override {
38 auto op = dyn_cast<omp::OffloadModuleInterface>(getOperation());
39 if (!op || !op.getIsTargetDevice())
40 return;
41
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 if (declareTargetOp && declareTargetOp.isDeclareTarget())
59 declareType = declareTargetOp.getDeclareTargetDeviceType();
60
61 // Only filter host functions from device modules because the host needs
62 // to provide fallback implementations of device code.
63 if (declareType != omp::DeclareTargetDeviceType::host)
64 return WalkResult::advance();
65
66 SymbolTable::UseRange funcUses = *funcOp.getSymbolUses(op);
67 for (SymbolTable::SymbolUse use : funcUses) {
68 Operation *callOp = use.getUser();
69
70 // Do not delete other functions (which may be device functions) holding
71 // the symbol of a host function as an attribute. The remaining
72 // attribute will point to an undefined symbol after this pass.
73 if (isa<FunctionOpInterface>(callOp))
74 continue;
75
76 // If the callOp has users then replace them with poison values before
77 // removing it. These should get removed before translation to LLVM IR
78 // by the host op filtering pass.
79 if (!callOp->use_empty()) {
80 SmallVector<Value> poisonResults;
81 for (Value res : callOp->getResults()) {
82 opBuilder.setInsertionPoint(callOp);
83 poisonResults.emplace_back(
84 LLVM::PoisonOp::create(opBuilder, res.getLoc(), res.getType()));
85 }
86 callOp->replaceAllUsesWith(poisonResults);
87 }
88
89 callOp->erase();
90 }
91
92 if (!hasTargetRegion) {
93 funcOp.erase();
94 return WalkResult::skip();
95 }
96
97 // MLIR to LLVM IR translation relies on host functions being explicitly
98 // marked as such to perform the second stage removal them from the device
99 // module, where functions that contain target regions are deleted from
100 // the generated LLVM IR.
101 if (declareTargetOp && !declareTargetOp.isDeclareTarget())
102 declareTargetOp.setDeclareTarget(omp::DeclareTargetDeviceType::host,
103 omp::DeclareTargetCaptureClause::to,
104 /*automap=*/false, /*implicit=*/true);
105 return WalkResult::advance();
106 });
107 }
108};
109
110} // namespace
b getContext())
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
Definition Builders.h:94
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:401
bool use_empty()
Returns true if this operation has no uses.
Definition Operation.h:897
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.
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.