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
228 return LLVM::ConstantOp::create(builder, loc, builder.getI64Type(), value);
229}
230
231Value acc::remapOrSelf(Value value, ConversionPatternRewriter &rewriter) {
232 if (!value)
233 return {};
234 if (Value converted = rewriter.getRemappedValue(value))
235 return converted;
236 return value;
237}
238
239Value acc::getAsyncQueue(Location loc, Value asyncOperand, bool asyncOnly,
240 OpBuilder &builder,
241 const ACCRuntimeCallConfig &config) {
242 Type i64Ty = builder.getI64Type();
243 if (asyncOnly)
244 return LLVM::ConstantOp::create(builder, loc, i64Ty,
246 if (asyncOperand)
247 return castToI64(loc, asyncOperand, builder);
248 return LLVM::ConstantOp::create(builder, loc, i64Ty,
249 config.getAsyncSyncRuntimeValue());
250}
251
252LogicalResult acc::emitWaitCall(Location loc, ValueRange waitOperands,
253 Value asyncQueue, OpBuilder &builder,
254 Region &globalSymbolRegion,
255 SymbolTable &symbolTable,
256 const ACCRuntimeCallConfig &config,
257 Value deviceNum) {
258 Type i32Ty = builder.getI32Type();
259 Type i64Ty = builder.getI64Type();
260 Type ptrTy = LLVM::LLVMPointerType::get(builder.getContext());
261
262 SmallVector<Value> queues;
263 queues.reserve(waitOperands.size());
264 for (Value waitOperand : waitOperands)
265 queues.push_back(castToI64(loc, waitOperand, builder));
266
267 unsigned size = queues.size();
268 Value waitNum = LLVM::ConstantOp::create(builder, loc, i32Ty, size);
269 Value waitList;
270 if (size == 0) {
271 waitList = LLVM::ZeroOp::create(builder, loc, ptrTy);
272 } else {
273 waitList = LLVM::AllocaOp::create(builder, loc, ptrTy, i64Ty, waitNum);
274 for (auto [index, queue] : llvm::enumerate(queues)) {
275 Value idx = LLVM::ConstantOp::create(builder, loc, i32Ty,
276 static_cast<int64_t>(index));
277 Value elementPtr = LLVM::GEPOp::create(builder, loc, ptrTy, i64Ty,
278 waitList, ArrayRef<Value>{idx});
279 LLVM::StoreOp::create(builder, loc, queue, elementPtr);
280 }
281 }
282
283 StringRef functionName = getParentFunctionName(waitOperands);
284 if (functionName.empty())
285 if (Block *block = builder.getInsertionBlock())
286 functionName = getParentFunctionName(block->getParentOp());
287 Value ident = createIdent(loc, functionName, builder, globalSymbolRegion,
288 config, &symbolTable);
289 Value flags = LLVM::ConstantOp::create(builder, loc, i64Ty, 0);
290 Value deviceType = LLVM::ConstantOp::create(
291 builder, loc, i64Ty, config.getDeviceTypeRuntimeValue(DeviceType::None));
292 if (!deviceNum)
293 deviceNum = LLVM::ConstantOp::create(builder, loc, i32Ty, 0);
294
295 return createRuntimeCall(
296 loc, builder, globalSymbolRegion, symbolTable,
297 RuntimeFunction::ACCRTL_tgt_acc_wait, config,
298 {ident, flags, deviceType, deviceNum, waitNum, waitList, asyncQueue});
299}
300
301FailureOr<Value> acc::emitGetDevicePtrCall(Operation *clauseOp, Value hostPtr,
302 bool ifPresent, OpBuilder &builder,
303 Region &globalSymbolRegion,
304 SymbolTable &symbolTable,
305 const ACCRuntimeCallConfig &config) {
306 Location loc = clauseOp->getLoc();
307 Value ident = createIdent(loc, getParentFunctionName(clauseOp), builder,
308 globalSymbolRegion, config, &symbolTable);
309 Value flags = LLVM::ConstantOp::create(
310 builder, loc, builder.getI64Type(),
311 config.getMapFlagsRuntimeValue(ifPresent ? MapFlags::if_present
312 : MapFlags::none));
313 // Both slots hold the address of the object, a clause naming a section of
314 // one included: the entry point looks up the mapping that address belongs
315 // to rather than being told which one to ask about.
316 FailureOr<LLVM::CallOp> call = createRuntimeCall(
317 loc, builder, globalSymbolRegion, symbolTable,
318 RuntimeFunction::ACCRTL_tgt_acc_get_deviceptr, config,
319 {ident, /*basePtr=*/hostPtr, flags, /*hostPtr=*/hostPtr});
320 if (failed(call))
321 return failure();
322 return call->getResult();
323}
324
325LogicalResult acc::emitGuardedByIfCond(Location loc, Value ifCond,
326 RewriterBase &rewriter,
327 function_ref<LogicalResult()> emitFn) {
328 if (!ifCond)
329 return emitFn();
330
331 Block *parentBlock = rewriter.getInsertionBlock();
332 Block *continueBlock =
333 rewriter.splitBlock(parentBlock, rewriter.getInsertionPoint());
334 Block *thenBlock = rewriter.createBlock(
335 parentBlock->getParent(), std::next(Region::iterator(parentBlock)));
336
337 rewriter.setInsertionPointToEnd(parentBlock);
338 LLVM::CondBrOp::create(rewriter, loc, ifCond, thenBlock, ValueRange{},
339 continueBlock, ValueRange{});
340
341 rewriter.setInsertionPointToStart(thenBlock);
342 LogicalResult result = emitFn();
343 rewriter.setInsertionPointToEnd(thenBlock);
344 LLVM::BrOp::create(rewriter, loc, ValueRange{}, continueBlock);
345 rewriter.setInsertionPointToStart(continueBlock);
346 return result;
347}
348
349FailureOr<Value>
351 RewriterBase &rewriter,
352 function_ref<FailureOr<Value>()> thenFn,
353 function_ref<FailureOr<Value>()> elseFn) {
354 if (!ifCond)
355 return thenFn();
356
357 Block *parentBlock = rewriter.getInsertionBlock();
358 Block *continueBlock =
359 rewriter.splitBlock(parentBlock, rewriter.getInsertionPoint());
360 Block *thenBlock = rewriter.createBlock(
361 parentBlock->getParent(), std::next(Region::iterator(parentBlock)));
362 Block *elseBlock = rewriter.createBlock(
363 parentBlock->getParent(), std::next(Region::iterator(thenBlock)));
364
365 rewriter.setInsertionPointToEnd(parentBlock);
366 LLVM::CondBrOp::create(rewriter, loc, ifCond, thenBlock, ValueRange{},
367 elseBlock, ValueRange{});
368
369 rewriter.setInsertionPointToStart(thenBlock);
370 FailureOr<Value> thenValue = thenFn();
371 if (failed(thenValue))
372 return failure();
373 rewriter.setInsertionPointToEnd(thenBlock);
374 LLVM::BrOp::create(rewriter, loc, ValueRange{*thenValue}, continueBlock);
375
376 rewriter.setInsertionPointToStart(elseBlock);
377 FailureOr<Value> elseValue = elseFn();
378 if (failed(elseValue))
379 return failure();
380 rewriter.setInsertionPointToEnd(elseBlock);
381 LLVM::BrOp::create(rewriter, loc, ValueRange{*elseValue}, continueBlock);
382
383 assert(thenValue->getType() == elseValue->getType() &&
384 "both paths of an if clause have to produce the same type");
385 BlockArgument selected =
386 continueBlock->addArgument(thenValue->getType(), loc);
387 rewriter.setInsertionPointToStart(continueBlock);
388 return Value(selected);
389}
390
392 RewriterBase &rewriter) {
393 Block *prev = op->getBlock();
394 Block *succ = rewriter.splitBlock(prev, Block::iterator(op));
395 rewriter.setInsertionPointToEnd(prev);
396 LLVM::BrOp::create(rewriter, op->getLoc(), &region.getBlocks().front());
397 for (Block &block : region.getBlocks()) {
398 // A region that ends without a terminator, as an `acc.kernel_environment`
399 // body does, continues after the construct from the end of its block.
400 if (block.empty() || !block.back().hasTrait<OpTrait::IsTerminator>()) {
401 rewriter.setInsertionPointToEnd(&block);
402 LLVM::BrOp::create(rewriter, op->getLoc(), succ);
403 continue;
404 }
405 Operation *terminator = block.getTerminator();
406 if (isa<acc::TerminatorOp>(terminator)) {
407 rewriter.setInsertionPoint(terminator);
408 LLVM::BrOp::create(rewriter, op->getLoc(), succ);
409 rewriter.eraseOp(terminator);
410 }
411 }
412 rewriter.inlineRegionBefore(region, succ);
413}
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:64
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
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.
Value remapOrSelf(Value value, ConversionPatternRewriter &rewriter)
Returns the value value was converted to, or value itself when the conversion left it as it was.
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 ...
Value constantI64(Location loc, int64_t value, OpBuilder &builder)
Creates an i64 constant.
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:155