MLIR 24.0.0git
Utils.cpp
Go to the documentation of this file.
1//===- StackToShared.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// This file implements various OpenMP dialect utilities.
10//
11//===----------------------------------------------------------------------===//
12
14
17
18using namespace mlir;
19
21 ModuleOp module, const OffloadModuleOpts &opts) {
22 if (auto offloadMod = llvm::dyn_cast<OffloadModuleInterface>(*module)) {
23 offloadMod.setIsTargetDevice(opts.isTargetDevice);
24 offloadMod.setIsGPU(opts.isGPU);
25 if (opts.forceUSM)
26 offloadMod.setRequires(offloadMod.getRequires() |
27 ClauseRequires::unified_shared_memory);
28 offloadMod.setFlags(opts.targetDebugKind, opts.assumeTeamsOversubscription,
32 opts.openMPDeviceVersion, opts.noGPULib);
33 if (opts.isTargetDevice && !opts.hostIRFile.empty())
34 offloadMod.setHostIRFilePath(opts.hostIRFile);
35
36 auto strTriples = llvm::to_vector(
37 llvm::map_range(opts.targetTriples, [](const llvm::Triple &triple) {
38 return triple.normalize();
39 }));
40 offloadMod.setTargetTriples(strTriples);
41 }
42}
43
44void mlir::omp::setOpenMPVersionAttribute(ModuleOp module, int64_t version) {
45 module->setDiscardableAttr(
46 StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
47 VersionAttr::get(module.getContext(), version));
48}
49
50void mlir::omp::setOpenMPIntegerWrapAround(ModuleOp module, bool value) {
51 module->setAttr(StringAttr::get(module.getContext(),
52 llvm::Twine{"omp.integer_wrap_around"}),
53 IntegerWrapAroundAttr::get(module.getContext(), value));
54}
55
57 int64_t fallback) {
58 if (Attribute verAttr = module->getDiscardableAttr("omp.version"))
59 return llvm::cast<VersionAttr>(verAttr).getVersion();
60 return fallback;
61}
62
63bool mlir::omp::isOpenMPModule(ModuleOp module) {
64 return module->hasDiscardableAttr("omp.version");
65}
66
67static bool allocaUseRequiresSharedMem(const OpOperand &use) {
68 Operation *owner = use.getOwner();
69 if (auto parallelOp = dyn_cast<omp::ParallelOp>(owner)) {
70 if (llvm::is_contained(parallelOp.getReductionVars(), use.get()))
71 return true;
72 } else if (auto callOp = dyn_cast<CallOpInterface>(owner)) {
73 if (llvm::is_contained(callOp.getArgOperands(), use.get()))
74 return true;
75 }
76
77 // If it is used directly inside of a parallel region, it has to be replaced
78 // unless the use is a private clause.
79 if (owner->getParentOfType<omp::ParallelOp>()) {
80 if (auto argIface = dyn_cast<omp::BlockArgOpenMPOpInterface>(owner)) {
81 OperandRange privateVars = argIface.getPrivateVars();
82 auto it = llvm::find(privateVars, use.get());
83 if (it != privateVars.end()) {
84 ArrayAttr privateSyms = *argIface.getPrivateSyms();
85 size_t idx = std::distance(privateVars.begin(), it);
86 auto privateOp =
88 owner, cast<SymbolRefAttr>(privateSyms[idx]));
89 return privateOp.getDataSharingType() !=
90 omp::DataSharingClauseType::Private;
91 }
92 }
93 return true;
94 }
95 return false;
96}
97
99 for (const OpOperand &use : alloc.getUses()) {
100 Operation *owner = use.getOwner();
101 if (isa<LLVM::AddrSpaceCastOp, LLVM::GEPOp>(owner)) {
102 if (llvm::any_of(owner->getResults(), [&](Value result) {
103 return allocaUsesRequireSharedMem(result);
104 }))
105 return true;
106 } else if (allocaUseRequiresSharedMem(use)) {
107 return true;
108 }
109 }
110 return false;
111}
112
114 if (isa<omp::ParallelOp>(op))
115 return false;
116
117 auto offloadIface = op.getParentOfType<omp::OffloadModuleInterface>();
118 if (!offloadIface || !offloadIface.getIsTargetDevice())
119 return false;
120
121 auto targetOp = op.getParentOfType<omp::TargetOp>();
122
123 // It must be inside of a generic omp.target or in a target device function,
124 // and not inside of omp.parallel.
125 if (auto parallelOp = op.getParentOfType<omp::ParallelOp>()) {
126 if (!targetOp || targetOp->isProperAncestor(parallelOp))
127 return false;
128 }
129
130 // The omp.target operation itself is considered in a shared device context in
131 // order to properly process its own allocation-defining entry block
132 // arguments.
133 if (!targetOp)
134 targetOp = dyn_cast<omp::TargetOp>(op);
135
136 if (targetOp) {
137 if (targetOp.getKernelType() != omp::TargetExecMode::generic)
138 return false;
139 } else {
140 auto declTargetIface = op.getParentOfType<omp::DeclareTargetInterface>();
141 if (!declTargetIface || !declTargetIface.isDeclareTarget() ||
142 declTargetIface.getDeclareTargetDeviceType() ==
143 omp::DeclareTargetDeviceType::host)
144 return false;
145 }
146 return true;
147}
static bool allocaUseRequiresSharedMem(const OpOperand &use)
Definition Utils.cpp:67
ArrayAttr()
Attributes are known-constant values of operations.
Definition Attributes.h:25
IRValueT get() const
Return the current value being used by this operand.
This class represents an operand of an operation.
Definition Value.h:254
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:44
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition Operation.h:255
result_range getResults()
Definition Operation.h:440
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
Definition Value.h:188
Operation * getOwner() const
Return the owner of this operand.
Definition UseDefLists.h:38
void setOffloadModuleInterfaceAttributes(ModuleOp module, const OffloadModuleOpts &opts)
Sets OpenMP offload module interface attributes on a ModuleOp, shared between Flang and Clang (CIR) f...
Definition Utils.cpp:20
bool isOpenMPModule(ModuleOp module)
Checks whether this is an OpenMP-enabled module.
Definition Utils.cpp:63
int64_t getOpenMPVersionAttribute(ModuleOp module, int64_t fallback=-1)
Returns the value of the omp.version attribute, if present, or the fallback.
Definition Utils.cpp:56
bool opInSharedDeviceContext(Operation &op)
Check whether the given operation is located in a context where an allocation to be used by multiple ...
Definition Utils.cpp:113
void setOpenMPVersionAttribute(ModuleOp module, int64_t version)
Adds or updates the omp.version attribute.
Definition Utils.cpp:44
void setOpenMPIntegerWrapAround(ModuleOp module, bool value)
Add the omp.integer_wrap_around attribute.
Definition Utils.cpp:50
bool allocaUsesRequireSharedMem(Value alloc)
Check whether the value representing an allocation, assumed to have been defined in a shared device c...
Definition Utils.cpp:98
Include the generated interface declarations.
Offload-specific OpenMP module attributes, associated to the OffloadModuleInterface.
Definition Utils.h:29
std::vector< llvm::Triple > targetTriples
Definition Utils.h:58