MLIR 24.0.0git
ACCToLLVMUtils.cpp
Go to the documentation of this file.
1//===- ACCToLLVMUtils.cpp - OpenACC to LLVM helpers -------------*- C++ -*-===//
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
10
14#include "llvm/ADT/Hashing.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/Twine.h"
19
20#include <iterator>
21
22using namespace mlir;
23using namespace mlir::acc;
24
26 while (auto fusedLoc = dyn_cast<FusedLoc>(loc))
27 loc = fusedLoc.getLocations().back();
28 return loc;
29}
30
31std::optional<FileLineColLoc>
32acc::getFileLineColLoc(Location loc, bool errorOnInvalidLocation) {
33 Location unfusedLoc = unfuseLoc(loc);
34
35 if (auto fileLoc = dyn_cast<FileLineColLoc>(unfusedLoc))
36 return fileLoc;
37
38 if (auto callSiteLoc = dyn_cast<CallSiteLoc>(unfusedLoc)) {
39 if (auto calleeFileLoc = getFileLineColLoc(callSiteLoc.getCallee(), false))
40 return calleeFileLoc;
41 if (auto callerFileLoc =
42 getFileLineColLoc(callSiteLoc.getCaller(), errorOnInvalidLocation))
43 return callerFileLoc;
44 }
45
46 if (errorOnInvalidLocation)
47 llvm_unreachable(
48 "cannot get file:line information: invalid Location information");
49 return std::nullopt;
50}
51
53 if (!op)
54 return "";
55 auto funcOp = dyn_cast<FunctionOpInterface>(op);
56 if (!funcOp)
57 funcOp = op->getParentOfType<FunctionOpInterface>();
58 return funcOp ? funcOp.getName() : StringRef();
59}
60
62 if (auto *op = value.getDefiningOp())
63 return getParentFunctionName(op);
64 return "";
65}
66
68 for (Value value : values) {
69 if (StringRef name = getParentFunctionName(value); !name.empty())
70 return name;
71 }
72 return "";
73}
74
75std::string acc::getInternalGlobalName(StringRef kind, StringRef detail) {
76 SmallString<64> name("acc.");
77 name += kind;
78 if (detail.empty())
79 return name.str().str();
80
81 name += '.';
82 for (unsigned char c : detail)
83 name += (llvm::isAlnum(c) || c == '_' || c == '$' || c == '.') ? c : '_';
84 return name.str().str();
85}
86
87/// Creates or reuses a module-internal null-terminated string global and
88/// returns the GlobalOp.
89static LLVM::GlobalOp getOrCreateGlobalStringOp(Location loc,
90 OpBuilder &builder,
91 StringRef name, StringRef value,
92 Region &globalSymbolRegion,
93 SymbolTable *symbolTable) {
94 SmallString<32> nullTermStr(value);
95 nullTermStr.push_back('\0');
96 StringAttr valueAttr = builder.getStringAttr(nullTermStr);
97
98 // A name says what the global holds, so a global of that name is the one to
99 // reuse as long as it holds this very value. Names come out of detail the
100 // source spells and are not one to one with it, so a name can also lead to a
101 // global holding something else, which a suffix then keeps apart.
102 SmallString<64> uniqueName(name);
103 if (symbolTable) {
104 unsigned suffix = 0;
105 while (Operation *taken = symbolTable->lookup(uniqueName)) {
106 auto global = dyn_cast<LLVM::GlobalOp>(taken);
107 if (global && global.getValueOrNull() == valueAttr)
108 return global;
109 uniqueName.clear();
110 (name + "." + Twine(suffix++)).toVector(uniqueName);
111 }
112 }
113
114 // Materialize the global through the incoming builder so that it stays
115 // tracked when the caller is a dialect conversion rewriter.
116 OpBuilder::InsertionGuard guard(builder);
117 builder.setInsertionPointToStart(&globalSymbolRegion.front());
118 auto arrayTy = LLVM::LLVMArrayType::get(builder.getI8Type(),
119 nullTermStr.size_in_bytes());
120 auto global =
121 LLVM::GlobalOp::create(builder, loc, arrayTy, /*isConstant=*/true,
122 LLVM::Linkage::Internal, uniqueName, valueAttr,
123 /*alignment=*/0);
124 if (symbolTable)
125 symbolTable->insert(global);
126 return global;
127}
128
130 StringRef name, StringRef value,
131 Region &globalSymbolRegion,
132 SymbolTable *symbolTable) {
133 Type i64Ty = builder.getI64Type();
134 Type ptrTy = LLVM::LLVMPointerType::get(builder.getContext());
135 LLVM::GlobalOp global = getOrCreateGlobalStringOp(
136 loc, builder, name, value, globalSymbolRegion, symbolTable);
137
138 Value globalPtr = LLVM::AddressOfOp::create(builder, loc, global);
139 Value cst0 = LLVM::ConstantOp::create(builder, loc, i64Ty,
140 builder.getI64IntegerAttr(0));
141 return LLVM::GEPOp::create(builder, loc, ptrTy, global.getType(), globalPtr,
142 ArrayRef<Value>({cst0, cst0}));
143}
144
145Value acc::createIdent(Location loc, StringRef functionName, OpBuilder &builder,
146 Region &globalSymbolRegion,
147 const ACCRuntimeCallConfig &config,
148 SymbolTable *symbolTable) {
149 MLIRContext *ctx = builder.getContext();
150 Type i32Ty = builder.getI32Type();
151 Type i64Ty = builder.getI64Type();
152 Type ptrTy = LLVM::LLVMPointerType::get(ctx);
153 Type structTy = LLVM::LLVMStructType::getLiteral(
154 ctx, {i32Ty, i32Ty, i32Ty, i32Ty, ptrTy});
155
156 std::string source;
157 // The position the globals describe is what names them, so a global found
158 // under such a name holds this very source string or ident.
159 std::string position;
160 if (auto fileLineColLoc =
161 getFileLineColLoc(loc, /*errorOnInvalidLocation=*/false)) {
162 std::string filename = fileLineColLoc->getFilename().str();
163 std::string line = std::to_string(fileLineColLoc->getLine());
164 std::string column = std::to_string(fileLineColLoc->getColumn());
165 std::string functionDisplayName =
166 functionName.empty() ? std::string()
167 : config.getFunctionDisplayName(functionName);
168 source = ";";
169 source += filename + ";";
170 source += functionDisplayName + ";";
171 source += line + ";";
172 source += column + ";";
173 source += ";";
174 position = line + "." + column + ".";
175 position += std::to_string(static_cast<uint64_t>(llvm::hash_value(source)));
176 } else {
177 source = ";unknown;unknown;0;0;;";
178 position = "unknown";
179 }
180
181 std::string identGlobalName = getInternalGlobalName("ident", position);
182 LLVM::GlobalOp identGlobal =
183 symbolTable ? symbolTable->lookup<LLVM::GlobalOp>(identGlobalName)
184 : LLVM::GlobalOp();
185 if (!identGlobal) {
186 LLVM::GlobalOp sourceGlobal = getOrCreateGlobalStringOp(
187 loc, builder, getInternalGlobalName("loc", position), source,
188 globalSymbolRegion, symbolTable);
189
190 OpBuilder::InsertionGuard guard(builder);
191 builder.setInsertionPointAfter(sourceGlobal);
192 identGlobal = LLVM::GlobalOp::create(
193 builder, loc, structTy, /*isConstant=*/true, LLVM::Linkage::Internal,
194 identGlobalName, /*value=*/Attribute(), /*alignment=*/0);
195 if (symbolTable)
196 symbolTable->insert(identGlobal);
197
198 Block *block = builder.createBlock(&identGlobal.getInitializerRegion());
199 builder.setInsertionPointToStart(block);
200 Value ident = LLVM::ZeroOp::create(builder, loc, structTy);
201 Value sourceBase = LLVM::AddressOfOp::create(builder, loc, sourceGlobal);
202 Value cst0 = LLVM::ConstantOp::create(builder, loc, i64Ty,
203 builder.getI64IntegerAttr(0));
204 Value sourcePtr =
205 LLVM::GEPOp::create(builder, loc, ptrTy, sourceGlobal.getType(),
206 sourceBase, ArrayRef<Value>({cst0, cst0}));
207 ident = LLVM::InsertValueOp::create(builder, loc, structTy, ident,
208 sourcePtr, ArrayRef<int64_t>{4});
209 LLVM::ReturnOp::create(builder, loc, ident);
210 }
211
212 return LLVM::AddressOfOp::create(builder, loc, identGlobal);
213}
214
216 Type i64Ty = builder.getI64Type();
217 if (value.getType() == i64Ty)
218 return value;
219 if (isa<IndexType>(value.getType()))
220 return arith::IndexCastOp::create(builder, loc, i64Ty, value);
221 unsigned bitwidth = value.getType().getIntOrFloatBitWidth();
222 if (bitwidth > 64)
223 return arith::TruncIOp::create(builder, loc, i64Ty, value);
224 return arith::ExtSIOp::create(builder, loc, i64Ty, value);
225}
226
227Value acc::getAsyncQueue(Location loc, Value asyncOperand, bool asyncOnly,
228 OpBuilder &builder,
229 const ACCRuntimeCallConfig &config) {
230 Type i64Ty = builder.getI64Type();
231 if (asyncOnly)
232 return LLVM::ConstantOp::create(builder, loc, i64Ty,
234 if (asyncOperand)
235 return castToI64(loc, asyncOperand, builder);
236 return LLVM::ConstantOp::create(builder, loc, i64Ty,
237 config.getAsyncSyncRuntimeValue());
238}
239
240LogicalResult acc::emitWaitCall(Location loc, ValueRange waitOperands,
241 Value asyncQueue, OpBuilder &builder,
242 Region &globalSymbolRegion,
243 SymbolTable &symbolTable,
244 const ACCRuntimeCallConfig &config,
245 Value deviceNum) {
246 Type i32Ty = builder.getI32Type();
247 Type i64Ty = builder.getI64Type();
248 Type ptrTy = LLVM::LLVMPointerType::get(builder.getContext());
249
250 SmallVector<Value> queues;
251 queues.reserve(waitOperands.size());
252 for (Value waitOperand : waitOperands)
253 queues.push_back(castToI64(loc, waitOperand, builder));
254
255 unsigned size = queues.size();
256 Value waitNum = LLVM::ConstantOp::create(builder, loc, i32Ty, size);
257 Value waitList;
258 if (size == 0) {
259 waitList = LLVM::ZeroOp::create(builder, loc, ptrTy);
260 } else {
261 waitList = LLVM::AllocaOp::create(builder, loc, ptrTy, i64Ty, waitNum);
262 for (auto [index, queue] : llvm::enumerate(queues)) {
263 Value idx = LLVM::ConstantOp::create(builder, loc, i32Ty,
264 static_cast<int64_t>(index));
265 Value elementPtr = LLVM::GEPOp::create(builder, loc, ptrTy, i64Ty,
266 waitList, ArrayRef<Value>{idx});
267 LLVM::StoreOp::create(builder, loc, queue, elementPtr);
268 }
269 }
270
271 StringRef functionName = getParentFunctionName(waitOperands);
272 if (functionName.empty())
273 if (Block *block = builder.getInsertionBlock())
274 functionName = getParentFunctionName(block->getParentOp());
275 Value ident = createIdent(loc, functionName, builder, globalSymbolRegion,
276 config, &symbolTable);
277 Value flags = LLVM::ConstantOp::create(builder, loc, i64Ty, 0);
278 Value deviceType = LLVM::ConstantOp::create(
279 builder, loc, i64Ty, config.getDeviceTypeRuntimeValue(DeviceType::None));
280 if (!deviceNum)
281 deviceNum = LLVM::ConstantOp::create(builder, loc, i32Ty, 0);
282
283 return createRuntimeCall(
284 loc, builder, globalSymbolRegion, symbolTable,
285 RuntimeFunction::ACCRTL_tgt_acc_wait, config,
286 {ident, flags, deviceType, deviceNum, waitNum, waitList, asyncQueue});
287}
288
289FailureOr<Value> acc::emitGetDevicePtrCall(Operation *clauseOp, Value hostPtr,
290 bool ifPresent, OpBuilder &builder,
291 Region &globalSymbolRegion,
292 SymbolTable &symbolTable,
293 const ACCRuntimeCallConfig &config) {
294 Location loc = clauseOp->getLoc();
295 Value ident = createIdent(loc, getParentFunctionName(clauseOp), builder,
296 globalSymbolRegion, config, &symbolTable);
297 Value flags = LLVM::ConstantOp::create(
298 builder, loc, builder.getI64Type(),
299 config.getMapFlagsRuntimeValue(ifPresent ? MapFlags::if_present
300 : MapFlags::none));
301 // Both slots hold the address of the object, a clause naming a section of
302 // one included: the entry point looks up the mapping that address belongs
303 // to rather than being told which one to ask about.
304 FailureOr<LLVM::CallOp> call = createRuntimeCall(
305 loc, builder, globalSymbolRegion, symbolTable,
306 RuntimeFunction::ACCRTL_tgt_acc_get_deviceptr, config,
307 {ident, /*basePtr=*/hostPtr, flags, /*hostPtr=*/hostPtr});
308 if (failed(call))
309 return failure();
310 return call->getResult();
311}
312
314acc::getDeviceTypesByPrecedence(DeviceType deviceType) {
315 SmallVector<DeviceType, 3> deviceTypes;
316 if (deviceType != DeviceType::None && deviceType != DeviceType::Star)
317 deviceTypes.push_back(deviceType);
318 deviceTypes.push_back(DeviceType::Star);
319 deviceTypes.push_back(DeviceType::None);
320 return deviceTypes;
321}
322
323LogicalResult acc::emitGuardedByIfCond(Location loc, Value ifCond,
324 RewriterBase &rewriter,
325 function_ref<LogicalResult()> emitFn) {
326 if (!ifCond)
327 return emitFn();
328
329 Block *parentBlock = rewriter.getInsertionBlock();
330 Block *continueBlock =
331 rewriter.splitBlock(parentBlock, rewriter.getInsertionPoint());
332 Block *thenBlock = rewriter.createBlock(
333 parentBlock->getParent(), std::next(Region::iterator(parentBlock)));
334
335 rewriter.setInsertionPointToEnd(parentBlock);
336 LLVM::CondBrOp::create(rewriter, loc, ifCond, thenBlock, ValueRange{},
337 continueBlock, ValueRange{});
338
339 rewriter.setInsertionPointToStart(thenBlock);
340 LogicalResult result = emitFn();
341 rewriter.setInsertionPointToEnd(thenBlock);
342 LLVM::BrOp::create(rewriter, loc, ValueRange{}, continueBlock);
343 rewriter.setInsertionPointToStart(continueBlock);
344 return result;
345}
346
347FailureOr<Value>
349 RewriterBase &rewriter,
350 function_ref<FailureOr<Value>()> thenFn,
351 function_ref<FailureOr<Value>()> elseFn) {
352 if (!ifCond)
353 return thenFn();
354
355 Block *parentBlock = rewriter.getInsertionBlock();
356 Block *continueBlock =
357 rewriter.splitBlock(parentBlock, rewriter.getInsertionPoint());
358 Block *thenBlock = rewriter.createBlock(
359 parentBlock->getParent(), std::next(Region::iterator(parentBlock)));
360 Block *elseBlock = rewriter.createBlock(
361 parentBlock->getParent(), std::next(Region::iterator(thenBlock)));
362
363 rewriter.setInsertionPointToEnd(parentBlock);
364 LLVM::CondBrOp::create(rewriter, loc, ifCond, thenBlock, ValueRange{},
365 elseBlock, ValueRange{});
366
367 rewriter.setInsertionPointToStart(thenBlock);
368 FailureOr<Value> thenValue = thenFn();
369 if (failed(thenValue))
370 return failure();
371 rewriter.setInsertionPointToEnd(thenBlock);
372 LLVM::BrOp::create(rewriter, loc, ValueRange{*thenValue}, continueBlock);
373
374 rewriter.setInsertionPointToStart(elseBlock);
375 FailureOr<Value> elseValue = elseFn();
376 if (failed(elseValue))
377 return failure();
378 rewriter.setInsertionPointToEnd(elseBlock);
379 LLVM::BrOp::create(rewriter, loc, ValueRange{*elseValue}, continueBlock);
380
381 assert(thenValue->getType() == elseValue->getType() &&
382 "both paths of an if clause have to produce the same type");
383 BlockArgument selected =
384 continueBlock->addArgument(thenValue->getType(), loc);
385 rewriter.setInsertionPointToStart(continueBlock);
386 return Value(selected);
387}
388
390 RewriterBase &rewriter) {
391 Block *prev = op->getBlock();
392 Block *succ = rewriter.splitBlock(prev, Block::iterator(op));
393 rewriter.setInsertionPointToEnd(prev);
394 LLVM::BrOp::create(rewriter, op->getLoc(), &region.getBlocks().front());
395 for (Block &block : region.getBlocks()) {
396 // A region that ends without a terminator, as an `acc.kernel_environment`
397 // body does, continues after the construct from the end of its block.
398 if (block.empty() || !block.back().hasTrait<OpTrait::IsTerminator>()) {
399 rewriter.setInsertionPointToEnd(&block);
400 LLVM::BrOp::create(rewriter, op->getLoc(), succ);
401 continue;
402 }
403 Operation *terminator = block.getTerminator();
404 if (isa<acc::TerminatorOp>(terminator)) {
405 rewriter.setInsertionPoint(terminator);
406 LLVM::BrOp::create(rewriter, op->getLoc(), succ);
407 rewriter.eraseOp(terminator);
408 }
409 }
410 rewriter.inlineRegionBefore(region, succ);
411}
static LLVM::GlobalOp getOrCreateGlobalStringOp(Location loc, OpBuilder &builder, StringRef name, StringRef value, Region &globalSymbolRegion, SymbolTable *symbolTable)
Creates or reuses a module-internal null-terminated string global and returns the GlobalOp.
Attributes are known-constant values of operations.
Definition Attributes.h:25
This class represents an argument of a Block.
Definition Value.h:306
Block represents an ordered list of Operations.
Definition Block.h:34
OpListType::iterator iterator
Definition Block.h:165
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
IntegerType getI64Type()
Definition Builders.cpp:73
IntegerType getI32Type()
Definition Builders.cpp:71
IntegerAttr getI64IntegerAttr(int64_t value)
Definition Builders.cpp:120
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:271
MLIRContext * getContext() const
Definition Builders.h:56
IntegerType getI8Type()
Definition Builders.cpp:67
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:351
This class helps build Operations.
Definition Builders.h:210
Block::iterator getInsertionPoint() const
Returns the current insertion point of the builder.
Definition Builders.h:448
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition Builders.cpp:439
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition Builders.h:434
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:401
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:439
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
Definition Builders.h:445
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition Builders.h:415
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
Block * getBlock()
Returns the operation block that contains this operation.
Definition Operation.h:230
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition Operation.h:255
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Block & front()
Definition Region.h:65
BlockListType & getBlocks()
Definition Region.h:45
BlockListType::iterator iterator
Definition Region.h:52
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
Block * splitBlock(Block *block, Block::iterator before)
Split the operations starting at "before" (inclusive) out of the given block into a new block,...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Definition SymbolTable.h:25
Operation * lookup(StringRef name) const
Look up a symbol with the specified name, returning null if no such name exists.
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition Types.cpp:124
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
Configuration for OpenACC to LLVM runtime lowering.
std::string getFunctionDisplayName(StringRef mangledOrSymbol) const
int64_t getDeviceTypeRuntimeValue(DeviceType type) const
int64_t getMapFlagsRuntimeValue(MapFlags flags) const
SmallVector< DeviceType, 3 > getDeviceTypesByPrecedence(DeviceType deviceType)
The clauses of a construct can be given once per device type.
std::optional< FileLineColLoc > getFileLineColLoc(Location loc, bool errorOnInvalidLocation)
Returns file:line:column location information when available.
LogicalResult emitWaitCall(Location loc, ValueRange waitOperands, Value asyncQueue, OpBuilder &builder, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config, Value deviceNum={})
Emits the runtime call that waits for waitOperands on asyncQueue, which is what a wait clause or an a...
Value getAsyncQueue(Location loc, Value asyncOperand, bool asyncOnly, OpBuilder &builder, const ACCRuntimeCallConfig &config)
Returns the queue an async clause selects: the value of the clause when it has one,...
Value createIdent(Location loc, StringRef functionName, OpBuilder &builder, Region &globalSymbolRegion, const ACCRuntimeCallConfig &config, SymbolTable *symbolTable=nullptr)
Returns a pointer to a constant global holding an ident_t for OpenACC runtime calls.
FailureOr< Value > emitValueSelectedByIfCond(Location loc, Value ifCond, RewriterBase &rewriter, function_ref< FailureOr< Value >()> thenFn, function_ref< FailureOr< Value >()> elseFn)
Emits thenFn on the path a branch on ifCond takes and elseFn on the other one, and returns the value ...
std::string getInternalGlobalName(StringRef kind, StringRef detail)
Returns the name to give a global that the conversion creates to hold detail of kind,...
StringRef getParentFunctionName(Operation *op)
Returns the symbol name of the function op belongs to, or of op itself when it is a function.
LogicalResult emitGuardedByIfCond(Location loc, Value ifCond, RewriterBase &rewriter, function_ref< LogicalResult()> emitFn)
Runs emitFn guarded by a branch on ifCond, or unguarded when there is no condition.
Value castToI64(Location loc, Value value, OpBuilder &builder)
Sign-extends or truncates value to the i64 the runtime entry points take for values like queue number...
Value getOrCreateGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Region &globalSymbolRegion, SymbolTable *symbolTable=nullptr)
Creates or reuses a null-terminated string global in globalSymbolRegion.
void spliceConstructRegion(Operation *op, Region &region, RewriterBase &rewriter)
Splices region, the body of a structured construct, into the block holding op, so that the construct ...
FailureOr< LLVM::CallOp > createRuntimeCall(Location loc, OpBuilder &builder, Region &globalSymbolRegion, SymbolTable &symbolTable, RuntimeFunction fn, const ACCRuntimeCallConfig &config, ArrayRef< Value > arguments)
Declares (if needed) and returns a call to the runtime function identified by fn using the name from ...
Location unfuseLoc(Location loc)
Unfuses fused locations, returning the last sub-location.
FailureOr< Value > emitGetDevicePtrCall(Operation *clauseOp, Value hostPtr, bool ifPresent, OpBuilder &builder, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config)
Emits the runtime call that asks for the device address the object of the data clause clauseOp is map...
Include the generated interface declarations.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147