17#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
18#include "mlir/IR/BuiltinOps.h"
20#include "llvm/ADT/SparseBitVector.h"
21#include "llvm/Support/AMDGPUPrintf.h"
22#include "llvm/Support/MathExtras.h"
29std::optional<int64_t> getConstantInt(mlir::Value value) {
30 auto constOp = value.getDefiningOp<cir::ConstantOp>();
32 constOp ? mlir::dyn_cast<cir::IntAttr>(constOp.getValue()) :
nullptr;
35 const llvm::APInt &v = intAttr.getValue();
36 if (mlir::cast<cir::IntType>(intAttr.getType()).isSigned()
37 ? v.getSignificantBits() > 64
38 : v.getActiveBits() > 63)
40 return v.getSExtValue();
43bool isByteType(mlir::Type ty) {
44 auto intTy = mlir::dyn_cast<cir::IntType>(ty);
45 return intTy && intTy.getWidth() == 8;
48bool getConstantStringInfo(mlir::Value ptr, mlir::ModuleOp mod,
49 mlir::SymbolTableCollection &symbolTables,
52 while (mlir::Operation *def = ptr.getDefiningOp()) {
53 if (
auto cast = mlir::dyn_cast<cir::CastOp>(def)) {
54 if (
cast.getKind() != cir::CastKind::array_to_ptrdecay &&
55 cast.getKind() != cir::CastKind::bitcast &&
56 cast.getKind() != cir::CastKind::address_space)
59 }
else if (
auto elt = mlir::dyn_cast<cir::GetElementOp>(def)) {
60 std::optional<int64_t> index = getConstantInt(elt.getIndex());
61 if (!index || !isByteType(elt.getElementType()) ||
62 llvm::AddOverflow(offset, *index, offset))
65 }
else if (
auto stride = mlir::dyn_cast<cir::PtrStrideOp>(def)) {
66 std::optional<int64_t> index = getConstantInt(stride.getStride());
67 if (!index || !isByteType(stride.getElementType()) ||
68 llvm::AddOverflow(offset, *index, offset))
70 ptr = stride.getBase();
76 auto getGlobal = ptr.getDefiningOp<cir::GetGlobalOp>();
82 mlir::Operation *symbol =
83 symbolTables.lookupSymbolIn(mod, getGlobal.getNameAttr());
84 if (
auto global = mlir::dyn_cast_if_present<cir::GlobalOp>(symbol)) {
85 std::optional<mlir::Attribute> init = global.getInitialValue();
86 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(global.getSymType());
87 if (!global.getConstant() || !init || !arrayTy ||
88 !isByteType(arrayTy.getElementType()))
90 if (
auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(*init)) {
91 auto strAttr = mlir::dyn_cast<mlir::StringAttr>(constArr.getElts());
94 data = strAttr.getValue().str();
95 }
else if (!mlir::isa<cir::ZeroAttr>(*init)) {
99 data.resize(arrayTy.getSize(),
'\0');
100 }
else if (
auto global =
101 mlir::dyn_cast_if_present<mlir::LLVM::GlobalOp>(symbol)) {
102 if (!global.getConstant())
104 mlir::Attribute value = global.getValueOrNull();
105 if (
auto strAttr = mlir::dyn_cast_if_present<mlir::StringAttr>(value)) {
106 data = strAttr.getValue().str();
107 }
else if (
auto dense =
108 mlir::dyn_cast_if_present<mlir::DenseIntElementsAttr>(value);
109 dense && dense.getElementType().isInteger(8)) {
110 for (
const llvm::APInt &c : dense.getValues<llvm::APInt>())
111 data.push_back(
static_cast<char>(c.getZExtValue()));
119 if (offset < 0 ||
static_cast<uint64_t>(offset) > data.size())
121 llvm::StringRef rest = llvm::StringRef(data).drop_front(offset);
122 str = rest.substr(0, rest.find(
'\0')).str();
129 mlir::Value realSize;
130 mlir::Value alignedSize;
134class AMDGPUPrintfLowering {
136 AMDGPUPrintfLowering(cir::OffloadPrintfOp op,
137 mlir::ConversionPatternRewriter &rewriter,
138 const mlir::DataLayout &dataLayout,
139 mlir::SymbolTableCollection &symbolTables,
140 unsigned genericAddrSpace)
141 : op(op), rewriter(rewriter), dataLayout(dataLayout),
142 symbolTables(symbolTables), mod(op->getParentOfType<mlir::ModuleOp>()),
143 genericAddrSpace(genericAddrSpace) {}
145 mlir::LogicalResult lower(mlir::ValueRange args,
bool isBuffered);
148 mlir::Value getI32(
uint32_t value) {
149 return mlir::LLVM::ConstantOp::create(
150 rewriter, op.getLoc(), rewriter.getI32Type(), llvm::APInt(32, value));
152 mlir::Value getI64(uint64_t value) {
153 return mlir::LLVM::ConstantOp::create(
154 rewriter, op.getLoc(), rewriter.getI64Type(), llvm::APInt(64, value));
156 mlir::Value createCall(llvm::StringRef name, mlir::Type resTy,
157 mlir::ValueRange args);
158 mlir::Value gepInBounds(mlir::Value ptr, mlir::LLVM::GEPArg offset);
159 void addPrintfFormatMetadata(llvm::StringRef entry,
bool onlyIfEmpty);
161 mlir::Value fitArgInto64Bits(mlir::Value arg);
162 mlir::Value callPrintfBegin(mlir::Value version);
163 mlir::Value callAppendArgs(mlir::Value desc,
int numArgs, mlir::Value arg0,
164 mlir::Value arg1, mlir::Value arg2,
165 mlir::Value arg3, mlir::Value arg4,
166 mlir::Value arg5, mlir::Value arg6,
bool isLast);
167 mlir::Value appendArg(mlir::Value desc, mlir::Value arg,
bool isLast);
168 mlir::Value getStrlenWithNull(mlir::Value str);
169 mlir::Value callAppendStringN(mlir::Value desc, mlir::Value str,
170 mlir::Value
length,
bool isLast);
171 mlir::Value appendString(mlir::Value desc, mlir::Value arg,
bool isLast);
172 mlir::Value processArg(mlir::Value desc, mlir::Value arg,
bool specIsCString,
174 bool isCStringArg(mlir::ValueRange args,
size_t i)
const;
175 mlir::Value callBufferedPrintfStart(
176 mlir::ValueRange args, mlir::Value fmt,
bool isConstFmtStr,
177 llvm::SmallVectorImpl<StringData> &stringContents, mlir::Value &argSize);
179 processConstantStringArg(
const StringData &sd,
180 llvm::SmallVectorImpl<mlir::Value> &whatToStore);
181 mlir::Value processNonStringArg(mlir::Value arg);
182 void callBufferedPrintfArgPush(mlir::ValueRange args, mlir::Value ptrToStore,
183 llvm::ArrayRef<StringData> stringContents,
185 mlir::Value emitAMDGPUPrintfCall(mlir::ValueRange args,
bool isBuffered);
187 cir::OffloadPrintfOp op;
188 mlir::ConversionPatternRewriter &rewriter;
189 const mlir::DataLayout &dataLayout;
190 mlir::SymbolTableCollection &symbolTables;
192 unsigned genericAddrSpace;
195 mlir::Block *cont =
nullptr;
197 llvm::SparseBitVector<8> specIsCString;
202mlir::Value AMDGPUPrintfLowering::createCall(llvm::StringRef name,
204 mlir::ValueRange args) {
205 auto fnTy = mlir::LLVM::LLVMFunctionType::get(
206 resTy, llvm::to_vector(args.getTypes()),
false);
208 return mlir::LLVM::CallOp::create(
209 rewriter, op.getLoc(), fnTy,
210 mlir::FlatSymbolRefAttr::get(rewriter.getContext(), name), args)
214mlir::Value AMDGPUPrintfLowering::gepInBounds(mlir::Value ptr,
215 mlir::LLVM::GEPArg offset) {
216 return mlir::LLVM::GEPOp::create(rewriter, op.getLoc(), ptr.getType(),
217 rewriter.getI8Type(), ptr,
218 llvm::ArrayRef<mlir::LLVM::GEPArg>{offset},
219 mlir::LLVM::GEPNoWrapFlags::inbounds);
222void AMDGPUPrintfLowering::addPrintfFormatMetadata(llvm::StringRef entry,
224 constexpr llvm::StringLiteral
name =
"llvm.printf.fmts";
225 mlir::Attribute
node = mlir::LLVM::MDNodeAttr::get(
226 rewriter.getContext(),
227 {mlir::LLVM::MDStringAttr::get(
228 rewriter.getContext(),
229 mlir::StringAttr::get(rewriter.getContext(), entry))});
231 mlir::LLVM::NamedMetadataOp metaD;
232 for (
auto md : mod.getOps<mlir::LLVM::NamedMetadataOp>()) {
233 if (md.getMetadataName() == name) {
240 mlir::OpBuilder::InsertionGuard guard(rewriter);
241 rewriter.setInsertionPointToEnd(mod.getBody());
242 mlir::LLVM::NamedMetadataOp::create(rewriter, mod.getLoc(), name,
243 rewriter.getArrayAttr(node));
247 if (onlyIfEmpty && !metaD.getNodes().empty())
249 llvm::SmallVector<mlir::Attribute> nodes(metaD.getNodes().getValue());
250 nodes.push_back(node);
251 rewriter.modifyOpInPlace(
252 metaD, [&] { metaD.setNodesAttr(rewriter.getArrayAttr(nodes)); });
255mlir::Value AMDGPUPrintfLowering::fitArgInto64Bits(mlir::Value arg) {
256 mlir::Type int64Ty = rewriter.getI64Type();
257 mlir::Type ty =
arg.getType();
259 if (
auto intTy = mlir::dyn_cast<mlir::IntegerType>(ty)) {
260 switch (intTy.getWidth()) {
262 return mlir::LLVM::ZExtOp::create(rewriter, op.getLoc(), int64Ty, arg);
269 return mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), int64Ty, arg);
272 if (mlir::isa<mlir::LLVM::LLVMPointerType>(ty)) {
273 return mlir::LLVM::PtrToIntOp::create(rewriter, op.getLoc(), int64Ty, arg);
276 llvm_unreachable(
"unexpected type");
279mlir::Value AMDGPUPrintfLowering::callPrintfBegin(mlir::Value version) {
280 return createCall(
"__ockl_printf_begin", rewriter.getI64Type(), version);
283mlir::Value AMDGPUPrintfLowering::callAppendArgs(
284 mlir::Value desc,
int numArgs, mlir::Value arg0, mlir::Value arg1,
285 mlir::Value arg2, mlir::Value arg3, mlir::Value arg4, mlir::Value arg5,
286 mlir::Value arg6,
bool isLast) {
287 mlir::Value isLastValue = getI32(isLast);
288 mlir::Value numArgsValue = getI32(numArgs);
289 return createCall(
"__ockl_printf_append_args", rewriter.getI64Type(),
290 {desc, numArgsValue, arg0, arg1, arg2, arg3, arg4, arg5,
294mlir::Value AMDGPUPrintfLowering::appendArg(mlir::Value desc, mlir::Value arg,
296 mlir::Value arg0 = fitArgInto64Bits(arg);
297 mlir::Value zero = getI64(0);
298 return callAppendArgs(desc, 1, arg0, zero, zero, zero, zero, zero, zero,
304mlir::Value AMDGPUPrintfLowering::getStrlenWithNull(mlir::Value str) {
305 mlir::Block *prev = rewriter.getInsertionBlock();
306 mlir::Region *region = cont->getParent();
308 mlir::Value charZero = mlir::LLVM::ConstantOp::create(
309 rewriter, op.getLoc(), rewriter.getI8Type(), llvm::APInt(8, 0));
310 mlir::Value one = getI64(1);
311 mlir::Value zero = getI64(0);
312 mlir::Type int64Ty = rewriter.getI64Type();
320 mlir::Block *
join = rewriter.createBlock(region, cont->getIterator(),
321 {int64Ty}, {op.getLoc()});
322 mlir::Block *whileBlock = rewriter.createBlock(
323 region,
join->getIterator(), {str.getType()}, {op.getLoc()});
324 mlir::Block *whileDone = rewriter.createBlock(region,
join->getIterator());
327 rewriter.setInsertionPointToEnd(prev);
328 mlir::Value cmpNull = mlir::LLVM::ICmpOp::create(
329 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::eq, str,
330 mlir::LLVM::ZeroOp::create(rewriter, op.getLoc(), str.getType()));
331 mlir::LLVM::CondBrOp::create(rewriter, op.getLoc(), cmpNull, join, zero,
335 rewriter.setInsertionPointToEnd(whileBlock);
337 mlir::Value ptrPhi = whileBlock->getArgument(0);
338 mlir::Value ptrNext = mlir::LLVM::GEPOp::create(
339 rewriter, op.getLoc(), str.getType(), rewriter.getI8Type(), ptrPhi,
340 llvm::ArrayRef<mlir::LLVM::GEPArg>{one});
343 mlir::Value data = mlir::LLVM::LoadOp::create(rewriter, op.getLoc(),
344 rewriter.getI8Type(), ptrPhi);
345 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
346 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::eq, data, charZero);
347 mlir::LLVM::CondBrOp::create(rewriter, op.getLoc(), cmp, whileDone,
348 mlir::ValueRange(), whileBlock, ptrNext);
351 rewriter.setInsertionPointToEnd(whileDone);
352 auto addrTy = mlir::IntegerType::get(
353 rewriter.getContext(), *dataLayout.getTypeIndexBitwidth(str.getType()));
354 mlir::Value endAddr =
355 mlir::LLVM::PtrToAddrOp::create(rewriter, op.getLoc(), addrTy, ptrPhi);
356 mlir::Value beginAddr =
357 mlir::LLVM::PtrToAddrOp::create(rewriter, op.getLoc(), addrTy, str);
359 mlir::LLVM::SubOp::create(rewriter, op.getLoc(), endAddr, beginAddr);
360 if (addrTy != int64Ty)
361 len = mlir::LLVM::ZExtOp::create(rewriter, op.getLoc(), int64Ty, len);
362 len = mlir::LLVM::AddOp::create(rewriter, op.getLoc(), len, one);
365 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), len, join);
366 rewriter.setInsertionPointToEnd(join);
367 return join->getArgument(0);
370mlir::Value AMDGPUPrintfLowering::callAppendStringN(mlir::Value desc,
374 mlir::Value isLastInt32 = getI32(isLast);
378 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), genericAddrSpace);
379 if (str.getType() != ptrTy)
381 mlir::LLVM::AddrSpaceCastOp::create(rewriter, op.getLoc(), ptrTy, str);
382 return createCall(
"__ockl_printf_append_string_n", rewriter.getI64Type(),
383 {desc, str, length, isLastInt32});
386mlir::Value AMDGPUPrintfLowering::appendString(mlir::Value desc,
387 mlir::Value arg,
bool isLast) {
388 mlir::Value
length = getStrlenWithNull(arg);
389 return callAppendStringN(desc, arg,
length, isLast);
392mlir::Value AMDGPUPrintfLowering::processArg(mlir::Value desc, mlir::Value arg,
393 bool specIsCString,
bool isLast) {
394 if (specIsCString && mlir::isa<mlir::LLVM::LLVMPointerType>(
arg.getType())) {
395 return appendString(desc, arg, isLast);
400 return appendArg(desc, arg, isLast);
404bool AMDGPUPrintfLowering::isCStringArg(mlir::ValueRange args,
size_t i)
const {
405 return specIsCString.test(i) &&
406 mlir::isa<mlir::LLVM::LLVMPointerType>(args[i].
getType());
412mlir::Value AMDGPUPrintfLowering::callBufferedPrintfStart(
413 mlir::ValueRange args, mlir::Value fmt,
bool isConstFmtStr,
414 llvm::SmallVectorImpl<StringData> &stringContents, mlir::Value &argSize) {
415 mlir::Value nonConstStrLen;
416 mlir::Value lenWithNull;
417 mlir::Value lenWithNullAligned;
426 lenWithNull = getStrlenWithNull(fmt);
429 tempAdd = mlir::LLVM::AddOp::create(rewriter, op.getLoc(), lenWithNull,
432 mlir::LLVM::AndOp::create(rewriter, op.getLoc(), tempAdd, getI64(~7U));
434 stringContents.push_back({
"", lenWithNull, nonConstStrLen,
false});
437 mlir::OperandRange cirArgs = op->getOperands();
438 for (
size_t i = 1; i < args.size(); i++) {
439 if (isCStringArg(args, i)) {
441 if (getConstantStringInfo(cirArgs[i], mod, symbolTables, argStr)) {
442 auto alignedLen = llvm::alignTo(argStr.size() + 1, 8);
443 stringContents.push_back({argStr, {}, {},
445 bufSize += alignedLen;
447 lenWithNull = getStrlenWithNull(args[i]);
450 tempAdd = mlir::LLVM::AddOp::create(rewriter, op.getLoc(), lenWithNull,
452 lenWithNullAligned = mlir::LLVM::AndOp::create(rewriter, op.getLoc(),
453 tempAdd, getI64(~7U));
455 if (nonConstStrLen) {
456 mlir::Value val = mlir::LLVM::AddOp::create(
457 rewriter, op.getLoc(), lenWithNullAligned, nonConstStrLen);
458 nonConstStrLen = val;
460 nonConstStrLen = lenWithNullAligned;
462 stringContents.push_back({
"", lenWithNull, lenWithNullAligned,
false});
466 dataLayout.getTypeAllocSize(args[i].
getType()).getFixedValue();
469 bufSize += llvm::alignTo(allocSize, 8);
474 mlir::Value sizeToReserve = getI64(bufSize);
476 sizeToReserve = mlir::LLVM::AddOp::create(rewriter, op.getLoc(),
477 nonConstStrLen, sizeToReserve);
479 argSize = mlir::LLVM::TruncOp::create(rewriter, op.getLoc(),
480 rewriter.getI32Type(), sizeToReserve);
483 unsigned globalAS = 0;
484 if (
auto as = mlir::dyn_cast_if_present<mlir::IntegerAttr>(
485 dataLayout.getGlobalMemorySpace()))
486 globalAS = as.getValue().getZExtValue();
488 mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), globalAS);
490 mlir::StringAttr::get(rewriter.getContext(),
"__printf_alloc");
491 bool declared = symbolTables.lookupSymbolIn(mod, allocName);
492 mlir::Value ptr = createCall(allocName, ptrTy, argSize);
494 mlir::cast<mlir::LLVM::LLVMFuncOp>(
495 symbolTables.lookupSymbolIn(mod, allocName))
501void AMDGPUPrintfLowering::processConstantStringArg(
502 const StringData &sd, llvm::SmallVectorImpl<mlir::Value> &whatToStore) {
503 llvm::SmallVector<uint32_t, 16> words;
504 llvm::packAMDGPUPrintfConstantString(sd.str, words);
506 whatToStore.push_back(getI32(word));
509mlir::Value AMDGPUPrintfLowering::processNonStringArg(mlir::Value arg) {
510 mlir::Type ty =
arg.getType();
512 if (
auto intTy = mlir::dyn_cast<mlir::IntegerType>(ty)) {
513 if (intTy.getWidth() < 64) {
514 return mlir::LLVM::ZExtOp::create(rewriter, op.getLoc(),
515 rewriter.getI64Type(), arg);
519 if (mlir::isa<mlir::FloatType>(ty)) {
520 if (dataLayout.getTypeAllocSize(ty).getFixedValue() < 8) {
521 return mlir::LLVM::FPExtOp::create(rewriter, op.getLoc(),
522 rewriter.getF64Type(), arg);
529void AMDGPUPrintfLowering::callBufferedPrintfArgPush(
530 mlir::ValueRange args, mlir::Value ptrToStore,
531 llvm::ArrayRef<StringData> stringContents,
bool isConstFmtStr) {
532 const StringData *strIt = stringContents.begin();
533 size_t i = isConstFmtStr ? 1 : 0;
534 for (; i < args.size(); i++) {
535 if (i != 0 && !isCStringArg(args, i)) {
538 mlir::Value toStore = processNonStringArg(args[i]);
539 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), toStore, ptrToStore);
541 dataLayout.getTypeAllocSize(toStore.getType()).getFixedValue();
542 ptrToStore = gepInBounds(ptrToStore, llvm::alignTo(allocSize, 8));
546 if (!strIt->isConst) {
552 auto memcpy = mlir::LLVM::MemcpyOp::create(
553 rewriter, op.getLoc(), ptrToStore, args[i], strIt->realSize,
555 mlir::NamedAttribute align1(mlir::LLVM::LLVMDialect::getAlignAttrName(),
556 rewriter.getI64IntegerAttr(1));
558 rewriter.getArrayAttr({rewriter.getDictionaryAttr(align1),
559 rewriter.getDictionaryAttr(align1),
560 rewriter.getDictionaryAttr({})}));
562 ptrToStore = gepInBounds(ptrToStore, strIt->alignedSize);
569 llvm::SmallVector<mlir::Value, 32> whatToStore;
570 processConstantStringArg(*strIt, whatToStore);
573 for (mlir::Value toStore : whatToStore) {
574 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), toStore, ptrToStore);
575 ptrToStore = gepInBounds(
577 dataLayout.getTypeAllocSize(toStore.getType()).getFixedValue());
582mlir::Value AMDGPUPrintfLowering::emitAMDGPUPrintfCall(mlir::ValueRange args,
584 size_t numOps = args.size();
587 mlir::Value fmt = args[0];
589 if (getConstantStringInfo(op.getFormat(), mod, symbolTables, fmtStr))
590 llvm::locateAMDGPUPrintfCStrings(specIsCString, fmtStr);
593 llvm::SmallVector<StringData, 8> stringContents;
594 bool isConstFmtStr = !fmtStr.empty();
597 mlir::Value ptr = callBufferedPrintfStart(args, fmt, isConstFmtStr,
598 stringContents, argSize);
602 mlir::Value cmp = mlir::LLVM::ICmpOp::create(
603 rewriter, op.getLoc(), mlir::LLVM::ICmpPredicate::ne, ptr,
604 mlir::LLVM::ZeroOp::create(rewriter, op.getLoc(), ptr.getType()));
607 mlir::Block *end = cont;
608 mlir::Block *argPush =
609 rewriter.createBlock(cont->getParent(), cont->getIterator());
611 rewriter.setInsertionPointToEnd(cmp.getParentBlock());
612 mlir::LLVM::CondBrOp::create(rewriter, op.getLoc(), cmp, argPush, end);
613 rewriter.setInsertionPointToEnd(argPush);
619 mlir::Value constantTwo = getI32(2);
620 mlir::Value controlDWord =
621 mlir::LLVM::ShlOp::create(rewriter, op.getLoc(), argSize, constantTwo);
623 controlDWord = mlir::LLVM::OrOp::create(rewriter, op.getLoc(),
624 controlDWord, constantTwo);
626 mlir::LLVM::StoreOp::create(rewriter, op.getLoc(), controlDWord, ptr);
628 ptr = gepInBounds(ptr, 4);
633 addPrintfFormatMetadata(llvm::getAMDGPUPrintfFormatMetadata(fmtStr),
636 mlir::LLVM::StoreOp::create(
637 rewriter, op.getLoc(),
638 getI64(llvm::getAMDGPUPrintfFormatHash(fmtStr)), ptr);
639 ptr = gepInBounds(ptr, 8);
644 addPrintfFormatMetadata(llvm::AMDGPUPrintfNonConstFormatMetadata,
649 callBufferedPrintfArgPush(args, ptr, stringContents, isConstFmtStr);
652 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), end);
653 rewriter.setInsertionPointToStart(end);
654 mlir::Value notCmp = mlir::LLVM::XOrOp::create(
655 rewriter, op.getLoc(), cmp,
656 mlir::LLVM::ConstantOp::create(
657 rewriter, op.getLoc(), rewriter.getI1Type(), llvm::APInt(1, 1)));
658 return mlir::LLVM::SExtOp::create(rewriter, op.getLoc(),
659 rewriter.getI32Type(), notCmp);
662 mlir::Value desc = callPrintfBegin(getI64(0));
663 desc = appendString(desc, fmt, numOps == 1);
668 for (
unsigned int i = 1; i != numOps; ++i) {
669 bool isLast = i == numOps - 1;
670 bool isCString = specIsCString.test(i);
671 desc = processArg(desc, args[i], isCString, isLast);
674 return mlir::LLVM::TruncOp::create(rewriter, op.getLoc(),
675 rewriter.getI32Type(), desc);
678mlir::LogicalResult AMDGPUPrintfLowering::lower(mlir::ValueRange args,
682 for (
auto [cirArg, arg] : llvm::zip(op.getArgs(), args.drop_front())) {
683 mlir::Type ty =
arg.getType();
684 if (ty.isInteger(32) || ty.isInteger(64) || ty.isF64() ||
685 mlir::isa<mlir::LLVM::LLVMPointerType>(ty))
687 return op.emitError() <<
"unsupported argument type " << cirArg.getType()
688 <<
" for AMDGPU printf";
692 mlir::Block *block = op->getBlock();
693 cont = rewriter.splitBlock(block, mlir::Block::iterator(op));
694 rewriter.setInsertionPointToEnd(block);
696 mlir::Value result = emitAMDGPUPrintfCall(args, isBuffered);
697 if (rewriter.getInsertionBlock() != cont)
698 mlir::LLVM::BrOp::create(rewriter, op.getLoc(), cont);
700 rewriter.replaceOp(op, result);
701 return mlir::success();
705 mlir::ValueRange operands,
706 mlir::ConversionPatternRewriter &rewriter,
707 const mlir::DataLayout &dataLayout,
708 mlir::SymbolTableCollection &symbolTables,
709 unsigned genericAddrSpace,
711 return AMDGPUPrintfLowering(op, rewriter, dataLayout, symbolTables,
713 .lower(operands, isBuffered);
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
mlir::LogicalResult lowerAMDGPUPrintf(cir::OffloadPrintfOp op, mlir::ValueRange operands, mlir::ConversionPatternRewriter &rewriter, const mlir::DataLayout &dataLayout, mlir::SymbolTableCollection &symbolTables, unsigned genericAddrSpace, bool isBuffered)
Lowers op, whose lowered operands are operands, to the buffered printf runtime interface if isBuffere...
void createLLVMFuncOpIfNotExist(mlir::ConversionPatternRewriter &rewriter, mlir::SymbolTableCollection &symbolTables, mlir::Operation *srcOp, llvm::StringRef fnName, mlir::Type fnTy, mlir::ArrayAttr argAttrs, mlir::ArrayAttr resAttrs)
Declare fnName with type fnTy before the function enclosing srcOp, unless the module already has a sy...
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t