14c9c98f3SStanislav Mekhanoshin //=== AMDGPUPrintfRuntimeBinding.cpp - OpenCL printf implementation -------===//
24c9c98f3SStanislav Mekhanoshin //
34c9c98f3SStanislav Mekhanoshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44c9c98f3SStanislav Mekhanoshin // See https://llvm.org/LICENSE.txt for license information.
54c9c98f3SStanislav Mekhanoshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64c9c98f3SStanislav Mekhanoshin //
74c9c98f3SStanislav Mekhanoshin //===----------------------------------------------------------------------===//
84c9c98f3SStanislav Mekhanoshin // \file
94c9c98f3SStanislav Mekhanoshin //
104c9c98f3SStanislav Mekhanoshin // The pass bind printfs to a kernel arg pointer that will be bound to a buffer
114c9c98f3SStanislav Mekhanoshin // later by the runtime.
124c9c98f3SStanislav Mekhanoshin //
134c9c98f3SStanislav Mekhanoshin // This pass traverses the functions in the module and converts
144c9c98f3SStanislav Mekhanoshin // each call to printf to a sequence of operations that
154c9c98f3SStanislav Mekhanoshin // store the following into the printf buffer:
164c9c98f3SStanislav Mekhanoshin // - format string (passed as a module's metadata unique ID)
174c9c98f3SStanislav Mekhanoshin // - bitwise copies of printf arguments
184c9c98f3SStanislav Mekhanoshin // The backend passes will need to store metadata in the kernel
194c9c98f3SStanislav Mekhanoshin //===----------------------------------------------------------------------===//
204c9c98f3SStanislav Mekhanoshin
214c9c98f3SStanislav Mekhanoshin #include "AMDGPU.h"
22ffe8720aSserge-sans-paille #include "llvm/ADT/Triple.h"
234c9c98f3SStanislav Mekhanoshin #include "llvm/Analysis/InstructionSimplify.h"
244c9c98f3SStanislav Mekhanoshin #include "llvm/Analysis/TargetLibraryInfo.h"
254c9c98f3SStanislav Mekhanoshin #include "llvm/IR/Dominators.h"
264c9c98f3SStanislav Mekhanoshin #include "llvm/IR/IRBuilder.h"
274c9c98f3SStanislav Mekhanoshin #include "llvm/IR/Instructions.h"
2805da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
294c9c98f3SStanislav Mekhanoshin #include "llvm/Transforms/Utils/BasicBlockUtils.h"
306a87e9b0Sdfukalov
314c9c98f3SStanislav Mekhanoshin using namespace llvm;
324c9c98f3SStanislav Mekhanoshin
334c9c98f3SStanislav Mekhanoshin #define DEBUG_TYPE "printfToRuntime"
344c9c98f3SStanislav Mekhanoshin #define DWORD_ALIGN 4
354c9c98f3SStanislav Mekhanoshin
364c9c98f3SStanislav Mekhanoshin namespace {
37fd323a89SArthur Eubanks class AMDGPUPrintfRuntimeBinding final : public ModulePass {
384c9c98f3SStanislav Mekhanoshin
394c9c98f3SStanislav Mekhanoshin public:
404c9c98f3SStanislav Mekhanoshin static char ID;
414c9c98f3SStanislav Mekhanoshin
424c9c98f3SStanislav Mekhanoshin explicit AMDGPUPrintfRuntimeBinding();
434c9c98f3SStanislav Mekhanoshin
444c9c98f3SStanislav Mekhanoshin private:
454c9c98f3SStanislav Mekhanoshin bool runOnModule(Module &M) override;
464c9c98f3SStanislav Mekhanoshin
getAnalysisUsage(AnalysisUsage & AU) const474c9c98f3SStanislav Mekhanoshin void getAnalysisUsage(AnalysisUsage &AU) const override {
484c9c98f3SStanislav Mekhanoshin AU.addRequired<TargetLibraryInfoWrapperPass>();
494c9c98f3SStanislav Mekhanoshin AU.addRequired<DominatorTreeWrapperPass>();
504c9c98f3SStanislav Mekhanoshin }
51fd323a89SArthur Eubanks };
524c9c98f3SStanislav Mekhanoshin
53fd323a89SArthur Eubanks class AMDGPUPrintfRuntimeBindingImpl {
54fd323a89SArthur Eubanks public:
AMDGPUPrintfRuntimeBindingImpl(function_ref<const DominatorTree & (Function &)> GetDT,function_ref<const TargetLibraryInfo & (Function &)> GetTLI)55fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBindingImpl(
56fd323a89SArthur Eubanks function_ref<const DominatorTree &(Function &)> GetDT,
57fd323a89SArthur Eubanks function_ref<const TargetLibraryInfo &(Function &)> GetTLI)
58fd323a89SArthur Eubanks : GetDT(GetDT), GetTLI(GetTLI) {}
59fd323a89SArthur Eubanks bool run(Module &M);
60fd323a89SArthur Eubanks
61fd323a89SArthur Eubanks private:
62fd323a89SArthur Eubanks void getConversionSpecifiers(SmallVectorImpl<char> &OpConvSpecifiers,
63fd323a89SArthur Eubanks StringRef fmt, size_t num_ops) const;
64fd323a89SArthur Eubanks
65fd323a89SArthur Eubanks bool shouldPrintAsStr(char Specifier, Type *OpType) const;
66fd323a89SArthur Eubanks bool lowerPrintfForGpu(Module &M);
67fd323a89SArthur Eubanks
simplify(Instruction * I,const TargetLibraryInfo * TLI,const DominatorTree * DT)68fd323a89SArthur Eubanks Value *simplify(Instruction *I, const TargetLibraryInfo *TLI,
69fd323a89SArthur Eubanks const DominatorTree *DT) {
70*b8c2781fSSimon Moll return simplifyInstruction(I, {*TD, TLI, DT});
714c9c98f3SStanislav Mekhanoshin }
724c9c98f3SStanislav Mekhanoshin
734c9c98f3SStanislav Mekhanoshin const DataLayout *TD;
74fd323a89SArthur Eubanks function_ref<const DominatorTree &(Function &)> GetDT;
75fd323a89SArthur Eubanks function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
76dafda610SJay Foad SmallVector<CallInst *, 32> Printfs;
774c9c98f3SStanislav Mekhanoshin };
784c9c98f3SStanislav Mekhanoshin } // namespace
794c9c98f3SStanislav Mekhanoshin
804c9c98f3SStanislav Mekhanoshin char AMDGPUPrintfRuntimeBinding::ID = 0;
814c9c98f3SStanislav Mekhanoshin
824c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_BEGIN(AMDGPUPrintfRuntimeBinding,
834c9c98f3SStanislav Mekhanoshin "amdgpu-printf-runtime-binding", "AMDGPU Printf lowering",
844c9c98f3SStanislav Mekhanoshin false, false)
854c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
864c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
874c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_END(AMDGPUPrintfRuntimeBinding, "amdgpu-printf-runtime-binding",
884c9c98f3SStanislav Mekhanoshin "AMDGPU Printf lowering", false, false)
894c9c98f3SStanislav Mekhanoshin
904c9c98f3SStanislav Mekhanoshin char &llvm::AMDGPUPrintfRuntimeBindingID = AMDGPUPrintfRuntimeBinding::ID;
914c9c98f3SStanislav Mekhanoshin
924c9c98f3SStanislav Mekhanoshin namespace llvm {
createAMDGPUPrintfRuntimeBinding()934c9c98f3SStanislav Mekhanoshin ModulePass *createAMDGPUPrintfRuntimeBinding() {
944c9c98f3SStanislav Mekhanoshin return new AMDGPUPrintfRuntimeBinding();
954c9c98f3SStanislav Mekhanoshin }
964c9c98f3SStanislav Mekhanoshin } // namespace llvm
974c9c98f3SStanislav Mekhanoshin
AMDGPUPrintfRuntimeBinding()98fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBinding::AMDGPUPrintfRuntimeBinding() : ModulePass(ID) {
994c9c98f3SStanislav Mekhanoshin initializeAMDGPUPrintfRuntimeBindingPass(*PassRegistry::getPassRegistry());
1004c9c98f3SStanislav Mekhanoshin }
1014c9c98f3SStanislav Mekhanoshin
getConversionSpecifiers(SmallVectorImpl<char> & OpConvSpecifiers,StringRef Fmt,size_t NumOps) const102fd323a89SArthur Eubanks void AMDGPUPrintfRuntimeBindingImpl::getConversionSpecifiers(
1034c9c98f3SStanislav Mekhanoshin SmallVectorImpl<char> &OpConvSpecifiers, StringRef Fmt,
1044c9c98f3SStanislav Mekhanoshin size_t NumOps) const {
1054c9c98f3SStanislav Mekhanoshin // not all format characters are collected.
1064c9c98f3SStanislav Mekhanoshin // At this time the format characters of interest
1074c9c98f3SStanislav Mekhanoshin // are %p and %s, which use to know if we
1084c9c98f3SStanislav Mekhanoshin // are either storing a literal string or a
1094c9c98f3SStanislav Mekhanoshin // pointer to the printf buffer.
1104c9c98f3SStanislav Mekhanoshin static const char ConvSpecifiers[] = "cdieEfgGaosuxXp";
1114c9c98f3SStanislav Mekhanoshin size_t CurFmtSpecifierIdx = 0;
1124c9c98f3SStanislav Mekhanoshin size_t PrevFmtSpecifierIdx = 0;
1134c9c98f3SStanislav Mekhanoshin
1144c9c98f3SStanislav Mekhanoshin while ((CurFmtSpecifierIdx = Fmt.find_first_of(
1154c9c98f3SStanislav Mekhanoshin ConvSpecifiers, CurFmtSpecifierIdx)) != StringRef::npos) {
1164c9c98f3SStanislav Mekhanoshin bool ArgDump = false;
1174c9c98f3SStanislav Mekhanoshin StringRef CurFmt = Fmt.substr(PrevFmtSpecifierIdx,
1184c9c98f3SStanislav Mekhanoshin CurFmtSpecifierIdx - PrevFmtSpecifierIdx);
1194c9c98f3SStanislav Mekhanoshin size_t pTag = CurFmt.find_last_of("%");
1204c9c98f3SStanislav Mekhanoshin if (pTag != StringRef::npos) {
1214c9c98f3SStanislav Mekhanoshin ArgDump = true;
1224c9c98f3SStanislav Mekhanoshin while (pTag && CurFmt[--pTag] == '%') {
1234c9c98f3SStanislav Mekhanoshin ArgDump = !ArgDump;
1244c9c98f3SStanislav Mekhanoshin }
1254c9c98f3SStanislav Mekhanoshin }
1264c9c98f3SStanislav Mekhanoshin
1274c9c98f3SStanislav Mekhanoshin if (ArgDump)
1284c9c98f3SStanislav Mekhanoshin OpConvSpecifiers.push_back(Fmt[CurFmtSpecifierIdx]);
1294c9c98f3SStanislav Mekhanoshin
1304c9c98f3SStanislav Mekhanoshin PrevFmtSpecifierIdx = ++CurFmtSpecifierIdx;
1314c9c98f3SStanislav Mekhanoshin }
1324c9c98f3SStanislav Mekhanoshin }
1334c9c98f3SStanislav Mekhanoshin
shouldPrintAsStr(char Specifier,Type * OpType) const134fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::shouldPrintAsStr(char Specifier,
1354c9c98f3SStanislav Mekhanoshin Type *OpType) const {
1364c9c98f3SStanislav Mekhanoshin if (Specifier != 's')
1374c9c98f3SStanislav Mekhanoshin return false;
1384c9c98f3SStanislav Mekhanoshin const PointerType *PT = dyn_cast<PointerType>(OpType);
1394c9c98f3SStanislav Mekhanoshin if (!PT || PT->getAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS)
1404c9c98f3SStanislav Mekhanoshin return false;
1414c9c98f3SStanislav Mekhanoshin Type *ElemType = PT->getContainedType(0);
1424c9c98f3SStanislav Mekhanoshin if (ElemType->getTypeID() != Type::IntegerTyID)
1434c9c98f3SStanislav Mekhanoshin return false;
1444c9c98f3SStanislav Mekhanoshin IntegerType *ElemIType = cast<IntegerType>(ElemType);
1454c9c98f3SStanislav Mekhanoshin return ElemIType->getBitWidth() == 8;
1464c9c98f3SStanislav Mekhanoshin }
1474c9c98f3SStanislav Mekhanoshin
lowerPrintfForGpu(Module & M)148fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) {
1494c9c98f3SStanislav Mekhanoshin LLVMContext &Ctx = M.getContext();
1504c9c98f3SStanislav Mekhanoshin IRBuilder<> Builder(Ctx);
1514c9c98f3SStanislav Mekhanoshin Type *I32Ty = Type::getInt32Ty(Ctx);
1524c9c98f3SStanislav Mekhanoshin unsigned UniqID = 0;
153dc6e8dfdSJacob Lambert // NB: This is important for this string size to be divisible by 4
1544c9c98f3SStanislav Mekhanoshin const char NonLiteralStr[4] = "???";
1554c9c98f3SStanislav Mekhanoshin
156dafda610SJay Foad for (auto CI : Printfs) {
157c1e32b3fSKazu Hirata unsigned NumOps = CI->arg_size();
1584c9c98f3SStanislav Mekhanoshin
1594c9c98f3SStanislav Mekhanoshin SmallString<16> OpConvSpecifiers;
1604c9c98f3SStanislav Mekhanoshin Value *Op = CI->getArgOperand(0);
1614c9c98f3SStanislav Mekhanoshin
1624c9c98f3SStanislav Mekhanoshin if (auto LI = dyn_cast<LoadInst>(Op)) {
1634c9c98f3SStanislav Mekhanoshin Op = LI->getPointerOperand();
1644c9c98f3SStanislav Mekhanoshin for (auto Use : Op->users()) {
1654c9c98f3SStanislav Mekhanoshin if (auto SI = dyn_cast<StoreInst>(Use)) {
1664c9c98f3SStanislav Mekhanoshin Op = SI->getValueOperand();
1674c9c98f3SStanislav Mekhanoshin break;
1684c9c98f3SStanislav Mekhanoshin }
1694c9c98f3SStanislav Mekhanoshin }
1704c9c98f3SStanislav Mekhanoshin }
1714c9c98f3SStanislav Mekhanoshin
1724c9c98f3SStanislav Mekhanoshin if (auto I = dyn_cast<Instruction>(Op)) {
173fd323a89SArthur Eubanks Value *Op_simplified =
174fd323a89SArthur Eubanks simplify(I, &GetTLI(*I->getFunction()), &GetDT(*I->getFunction()));
1754c9c98f3SStanislav Mekhanoshin if (Op_simplified)
1764c9c98f3SStanislav Mekhanoshin Op = Op_simplified;
1774c9c98f3SStanislav Mekhanoshin }
1784c9c98f3SStanislav Mekhanoshin
1794c9c98f3SStanislav Mekhanoshin ConstantExpr *ConstExpr = dyn_cast<ConstantExpr>(Op);
1804c9c98f3SStanislav Mekhanoshin
1814c9c98f3SStanislav Mekhanoshin if (ConstExpr) {
1824c9c98f3SStanislav Mekhanoshin GlobalVariable *GVar = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
1834c9c98f3SStanislav Mekhanoshin
1844c9c98f3SStanislav Mekhanoshin StringRef Str("unknown");
1854c9c98f3SStanislav Mekhanoshin if (GVar && GVar->hasInitializer()) {
186ee3da895SSimon Pilgrim auto *Init = GVar->getInitializer();
187ee3da895SSimon Pilgrim if (auto *CA = dyn_cast<ConstantDataArray>(Init)) {
1884c9c98f3SStanislav Mekhanoshin if (CA->isString())
1894c9c98f3SStanislav Mekhanoshin Str = CA->getAsCString();
1904c9c98f3SStanislav Mekhanoshin } else if (isa<ConstantAggregateZero>(Init)) {
1914c9c98f3SStanislav Mekhanoshin Str = "";
1924c9c98f3SStanislav Mekhanoshin }
1934c9c98f3SStanislav Mekhanoshin //
1944c9c98f3SStanislav Mekhanoshin // we need this call to ascertain
1954c9c98f3SStanislav Mekhanoshin // that we are printing a string
1964c9c98f3SStanislav Mekhanoshin // or a pointer. It takes out the
1974c9c98f3SStanislav Mekhanoshin // specifiers and fills up the first
1984c9c98f3SStanislav Mekhanoshin // arg
1994c9c98f3SStanislav Mekhanoshin getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1);
2004c9c98f3SStanislav Mekhanoshin }
2014c9c98f3SStanislav Mekhanoshin // Add metadata for the string
2024c9c98f3SStanislav Mekhanoshin std::string AStreamHolder;
2034c9c98f3SStanislav Mekhanoshin raw_string_ostream Sizes(AStreamHolder);
2044c9c98f3SStanislav Mekhanoshin int Sum = DWORD_ALIGN;
205c1e32b3fSKazu Hirata Sizes << CI->arg_size() - 1;
2064c9c98f3SStanislav Mekhanoshin Sizes << ':';
207c1e32b3fSKazu Hirata for (unsigned ArgCount = 1;
208c1e32b3fSKazu Hirata ArgCount < CI->arg_size() && ArgCount <= OpConvSpecifiers.size();
2094c9c98f3SStanislav Mekhanoshin ArgCount++) {
2104c9c98f3SStanislav Mekhanoshin Value *Arg = CI->getArgOperand(ArgCount);
2114c9c98f3SStanislav Mekhanoshin Type *ArgType = Arg->getType();
2124c9c98f3SStanislav Mekhanoshin unsigned ArgSize = TD->getTypeAllocSizeInBits(ArgType);
2134c9c98f3SStanislav Mekhanoshin ArgSize = ArgSize / 8;
2144c9c98f3SStanislav Mekhanoshin //
2154c9c98f3SStanislav Mekhanoshin // ArgSize by design should be a multiple of DWORD_ALIGN,
2164c9c98f3SStanislav Mekhanoshin // expand the arguments that do not follow this rule.
2174c9c98f3SStanislav Mekhanoshin //
2184c9c98f3SStanislav Mekhanoshin if (ArgSize % DWORD_ALIGN != 0) {
2194c9c98f3SStanislav Mekhanoshin llvm::Type *ResType = llvm::Type::getInt32Ty(Ctx);
2203254a001SChristopher Tetreault auto *LLVMVecType = llvm::dyn_cast<llvm::FixedVectorType>(ArgType);
2214c9c98f3SStanislav Mekhanoshin int NumElem = LLVMVecType ? LLVMVecType->getNumElements() : 1;
2224c9c98f3SStanislav Mekhanoshin if (LLVMVecType && NumElem > 1)
2233254a001SChristopher Tetreault ResType = llvm::FixedVectorType::get(ResType, NumElem);
2244c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(CI);
2254c9c98f3SStanislav Mekhanoshin Builder.SetCurrentDebugLocation(CI->getDebugLoc());
2264c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'x' ||
2274c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'X' ||
2284c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'u' ||
2294c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'o')
2304c9c98f3SStanislav Mekhanoshin Arg = Builder.CreateZExt(Arg, ResType);
2314c9c98f3SStanislav Mekhanoshin else
2324c9c98f3SStanislav Mekhanoshin Arg = Builder.CreateSExt(Arg, ResType);
2334c9c98f3SStanislav Mekhanoshin ArgType = Arg->getType();
2344c9c98f3SStanislav Mekhanoshin ArgSize = TD->getTypeAllocSizeInBits(ArgType);
2354c9c98f3SStanislav Mekhanoshin ArgSize = ArgSize / 8;
2364c9c98f3SStanislav Mekhanoshin CI->setOperand(ArgCount, Arg);
2374c9c98f3SStanislav Mekhanoshin }
2384c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'f') {
2394c9c98f3SStanislav Mekhanoshin ConstantFP *FpCons = dyn_cast<ConstantFP>(Arg);
2404c9c98f3SStanislav Mekhanoshin if (FpCons)
2414c9c98f3SStanislav Mekhanoshin ArgSize = 4;
2424c9c98f3SStanislav Mekhanoshin else {
2434c9c98f3SStanislav Mekhanoshin FPExtInst *FpExt = dyn_cast<FPExtInst>(Arg);
2444c9c98f3SStanislav Mekhanoshin if (FpExt && FpExt->getType()->isDoubleTy() &&
2454c9c98f3SStanislav Mekhanoshin FpExt->getOperand(0)->getType()->isFloatTy())
2464c9c98f3SStanislav Mekhanoshin ArgSize = 4;
2474c9c98f3SStanislav Mekhanoshin }
2484c9c98f3SStanislav Mekhanoshin }
2494c9c98f3SStanislav Mekhanoshin if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) {
250ee3da895SSimon Pilgrim if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) {
251ee3da895SSimon Pilgrim auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
2524c9c98f3SStanislav Mekhanoshin if (GV && GV->hasInitializer()) {
2534c9c98f3SStanislav Mekhanoshin Constant *Init = GV->getInitializer();
254ee3da895SSimon Pilgrim bool IsZeroValue = Init->isZeroValue();
255ee3da895SSimon Pilgrim auto *CA = dyn_cast<ConstantDataArray>(Init);
256ee3da895SSimon Pilgrim if (IsZeroValue || (CA && CA->isString())) {
257ee3da895SSimon Pilgrim size_t SizeStr =
258ee3da895SSimon Pilgrim IsZeroValue ? 1 : (strlen(CA->getAsCString().data()) + 1);
2594c9c98f3SStanislav Mekhanoshin size_t Rem = SizeStr % DWORD_ALIGN;
2604c9c98f3SStanislav Mekhanoshin size_t NSizeStr = 0;
2614c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf string original size = " << SizeStr
2624c9c98f3SStanislav Mekhanoshin << '\n');
2634c9c98f3SStanislav Mekhanoshin if (Rem) {
2644c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr + (DWORD_ALIGN - Rem);
2654c9c98f3SStanislav Mekhanoshin } else {
2664c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr;
2674c9c98f3SStanislav Mekhanoshin }
2684c9c98f3SStanislav Mekhanoshin ArgSize = NSizeStr;
2694c9c98f3SStanislav Mekhanoshin }
2704c9c98f3SStanislav Mekhanoshin } else {
2714c9c98f3SStanislav Mekhanoshin ArgSize = sizeof(NonLiteralStr);
2724c9c98f3SStanislav Mekhanoshin }
2734c9c98f3SStanislav Mekhanoshin } else {
2744c9c98f3SStanislav Mekhanoshin ArgSize = sizeof(NonLiteralStr);
2754c9c98f3SStanislav Mekhanoshin }
2764c9c98f3SStanislav Mekhanoshin }
2774c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf ArgSize (in buffer) = " << ArgSize
2784c9c98f3SStanislav Mekhanoshin << " for type: " << *ArgType << '\n');
2794c9c98f3SStanislav Mekhanoshin Sizes << ArgSize << ':';
2804c9c98f3SStanislav Mekhanoshin Sum += ArgSize;
2814c9c98f3SStanislav Mekhanoshin }
2824c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf format string in source = " << Str.str()
2834c9c98f3SStanislav Mekhanoshin << '\n');
284262dd1e4SKazu Hirata for (char C : Str) {
2854c9c98f3SStanislav Mekhanoshin // Rest of the C escape sequences (e.g. \') are handled correctly
2864c9c98f3SStanislav Mekhanoshin // by the MDParser
287262dd1e4SKazu Hirata switch (C) {
2884c9c98f3SStanislav Mekhanoshin case '\a':
2894c9c98f3SStanislav Mekhanoshin Sizes << "\\a";
2904c9c98f3SStanislav Mekhanoshin break;
2914c9c98f3SStanislav Mekhanoshin case '\b':
2924c9c98f3SStanislav Mekhanoshin Sizes << "\\b";
2934c9c98f3SStanislav Mekhanoshin break;
2944c9c98f3SStanislav Mekhanoshin case '\f':
2954c9c98f3SStanislav Mekhanoshin Sizes << "\\f";
2964c9c98f3SStanislav Mekhanoshin break;
2974c9c98f3SStanislav Mekhanoshin case '\n':
2984c9c98f3SStanislav Mekhanoshin Sizes << "\\n";
2994c9c98f3SStanislav Mekhanoshin break;
3004c9c98f3SStanislav Mekhanoshin case '\r':
3014c9c98f3SStanislav Mekhanoshin Sizes << "\\r";
3024c9c98f3SStanislav Mekhanoshin break;
3034c9c98f3SStanislav Mekhanoshin case '\v':
3044c9c98f3SStanislav Mekhanoshin Sizes << "\\v";
3054c9c98f3SStanislav Mekhanoshin break;
3064c9c98f3SStanislav Mekhanoshin case ':':
3074c9c98f3SStanislav Mekhanoshin // ':' cannot be scanned by Flex, as it is defined as a delimiter
3084c9c98f3SStanislav Mekhanoshin // Replace it with it's octal representation \72
3094c9c98f3SStanislav Mekhanoshin Sizes << "\\72";
3104c9c98f3SStanislav Mekhanoshin break;
3114c9c98f3SStanislav Mekhanoshin default:
312262dd1e4SKazu Hirata Sizes << C;
3134c9c98f3SStanislav Mekhanoshin break;
3144c9c98f3SStanislav Mekhanoshin }
3154c9c98f3SStanislav Mekhanoshin }
3164c9c98f3SStanislav Mekhanoshin
3174c9c98f3SStanislav Mekhanoshin // Insert the printf_alloc call
3184c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(CI);
3194c9c98f3SStanislav Mekhanoshin Builder.SetCurrentDebugLocation(CI->getDebugLoc());
3204c9c98f3SStanislav Mekhanoshin
3214c9c98f3SStanislav Mekhanoshin AttributeList Attr = AttributeList::get(Ctx, AttributeList::FunctionIndex,
3224c9c98f3SStanislav Mekhanoshin Attribute::NoUnwind);
3234c9c98f3SStanislav Mekhanoshin
3244c9c98f3SStanislav Mekhanoshin Type *SizetTy = Type::getInt32Ty(Ctx);
3254c9c98f3SStanislav Mekhanoshin
3264c9c98f3SStanislav Mekhanoshin Type *Tys_alloc[1] = {SizetTy};
327cfb94212SNikita Popov Type *I8Ty = Type::getInt8Ty(Ctx);
328cfb94212SNikita Popov Type *I8Ptr = PointerType::get(I8Ty, 1);
3294c9c98f3SStanislav Mekhanoshin FunctionType *FTy_alloc = FunctionType::get(I8Ptr, Tys_alloc, false);
3304c9c98f3SStanislav Mekhanoshin FunctionCallee PrintfAllocFn =
3314c9c98f3SStanislav Mekhanoshin M.getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr);
3324c9c98f3SStanislav Mekhanoshin
3334c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf metadata = " << Sizes.str() << '\n');
334c50faffbSKazu Hirata std::string fmtstr = itostr(++UniqID) + ":" + Sizes.str();
3354c9c98f3SStanislav Mekhanoshin MDString *fmtStrArray = MDString::get(Ctx, fmtstr);
3364c9c98f3SStanislav Mekhanoshin
3374c9c98f3SStanislav Mekhanoshin // Instead of creating global variables, the
3384c9c98f3SStanislav Mekhanoshin // printf format strings are extracted
3394c9c98f3SStanislav Mekhanoshin // and passed as metadata. This avoids
3404c9c98f3SStanislav Mekhanoshin // polluting llvm's symbol tables in this module.
3414c9c98f3SStanislav Mekhanoshin // Metadata is going to be extracted
3424c9c98f3SStanislav Mekhanoshin // by the backend passes and inserted
3434c9c98f3SStanislav Mekhanoshin // into the OpenCL binary as appropriate.
3444c9c98f3SStanislav Mekhanoshin StringRef amd("llvm.printf.fmts");
3454c9c98f3SStanislav Mekhanoshin NamedMDNode *metaD = M.getOrInsertNamedMetadata(amd);
3464c9c98f3SStanislav Mekhanoshin MDNode *myMD = MDNode::get(Ctx, fmtStrArray);
3474c9c98f3SStanislav Mekhanoshin metaD->addOperand(myMD);
3484c9c98f3SStanislav Mekhanoshin Value *sumC = ConstantInt::get(SizetTy, Sum, false);
3494c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 1> alloc_args;
3504c9c98f3SStanislav Mekhanoshin alloc_args.push_back(sumC);
3514c9c98f3SStanislav Mekhanoshin CallInst *pcall =
3524c9c98f3SStanislav Mekhanoshin CallInst::Create(PrintfAllocFn, alloc_args, "printf_alloc_fn", CI);
3534c9c98f3SStanislav Mekhanoshin
3544c9c98f3SStanislav Mekhanoshin //
3554c9c98f3SStanislav Mekhanoshin // Insert code to split basicblock with a
3564c9c98f3SStanislav Mekhanoshin // piece of hammock code.
3574c9c98f3SStanislav Mekhanoshin // basicblock splits after buffer overflow check
3584c9c98f3SStanislav Mekhanoshin //
3594c9c98f3SStanislav Mekhanoshin ConstantPointerNull *zeroIntPtr =
360cfb94212SNikita Popov ConstantPointerNull::get(PointerType::get(I8Ty, 1));
3610805e40aSSimon Pilgrim auto *cmp = cast<ICmpInst>(Builder.CreateICmpNE(pcall, zeroIntPtr, ""));
3624c9c98f3SStanislav Mekhanoshin if (!CI->use_empty()) {
3634c9c98f3SStanislav Mekhanoshin Value *result =
3644c9c98f3SStanislav Mekhanoshin Builder.CreateSExt(Builder.CreateNot(cmp), I32Ty, "printf_res");
3654c9c98f3SStanislav Mekhanoshin CI->replaceAllUsesWith(result);
3664c9c98f3SStanislav Mekhanoshin }
3674c9c98f3SStanislav Mekhanoshin SplitBlock(CI->getParent(), cmp);
3684c9c98f3SStanislav Mekhanoshin Instruction *Brnch =
3694c9c98f3SStanislav Mekhanoshin SplitBlockAndInsertIfThen(cmp, cmp->getNextNode(), false);
3704c9c98f3SStanislav Mekhanoshin
3714c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(Brnch);
3724c9c98f3SStanislav Mekhanoshin
3734c9c98f3SStanislav Mekhanoshin // store unique printf id in the buffer
3744c9c98f3SStanislav Mekhanoshin //
37597a23ab2SSimon Pilgrim GetElementPtrInst *BufferIdx = GetElementPtrInst::Create(
3769e225a2aSNikita Popov I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 0)), "PrintBuffID",
3779e225a2aSNikita Popov Brnch);
3784c9c98f3SStanislav Mekhanoshin
3794c9c98f3SStanislav Mekhanoshin Type *idPointer = PointerType::get(I32Ty, AMDGPUAS::GLOBAL_ADDRESS);
3804c9c98f3SStanislav Mekhanoshin Value *id_gep_cast =
3814c9c98f3SStanislav Mekhanoshin new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", Brnch);
3824c9c98f3SStanislav Mekhanoshin
38311aa3707SEli Friedman new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast, Brnch);
3844c9c98f3SStanislav Mekhanoshin
3859e225a2aSNikita Popov // 1st 4 bytes hold the printf_id
3864c9c98f3SStanislav Mekhanoshin // the following GEP is the buffer pointer
3879e225a2aSNikita Popov BufferIdx = GetElementPtrInst::Create(
3889e225a2aSNikita Popov I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 4)), "PrintBuffGep",
3899e225a2aSNikita Popov Brnch);
3904c9c98f3SStanislav Mekhanoshin
3914c9c98f3SStanislav Mekhanoshin Type *Int32Ty = Type::getInt32Ty(Ctx);
3924c9c98f3SStanislav Mekhanoshin Type *Int64Ty = Type::getInt64Ty(Ctx);
393c1e32b3fSKazu Hirata for (unsigned ArgCount = 1;
394c1e32b3fSKazu Hirata ArgCount < CI->arg_size() && ArgCount <= OpConvSpecifiers.size();
3954c9c98f3SStanislav Mekhanoshin ArgCount++) {
3964c9c98f3SStanislav Mekhanoshin Value *Arg = CI->getArgOperand(ArgCount);
3974c9c98f3SStanislav Mekhanoshin Type *ArgType = Arg->getType();
3984c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 32> WhatToStore;
3992dea3f12SChristopher Tetreault if (ArgType->isFPOrFPVectorTy() && !isa<VectorType>(ArgType)) {
4004c9c98f3SStanislav Mekhanoshin Type *IType = (ArgType->isFloatTy()) ? Int32Ty : Int64Ty;
4014c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'f') {
40297a23ab2SSimon Pilgrim if (auto *FpCons = dyn_cast<ConstantFP>(Arg)) {
40397a23ab2SSimon Pilgrim APFloat Val(FpCons->getValueAPF());
4044c9c98f3SStanislav Mekhanoshin bool Lost = false;
4054c9c98f3SStanislav Mekhanoshin Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
4064c9c98f3SStanislav Mekhanoshin &Lost);
4074c9c98f3SStanislav Mekhanoshin Arg = ConstantFP::get(Ctx, Val);
4084c9c98f3SStanislav Mekhanoshin IType = Int32Ty;
40997a23ab2SSimon Pilgrim } else if (auto *FpExt = dyn_cast<FPExtInst>(Arg)) {
41097a23ab2SSimon Pilgrim if (FpExt->getType()->isDoubleTy() &&
4114c9c98f3SStanislav Mekhanoshin FpExt->getOperand(0)->getType()->isFloatTy()) {
4124c9c98f3SStanislav Mekhanoshin Arg = FpExt->getOperand(0);
4134c9c98f3SStanislav Mekhanoshin IType = Int32Ty;
4144c9c98f3SStanislav Mekhanoshin }
4154c9c98f3SStanislav Mekhanoshin }
4164c9c98f3SStanislav Mekhanoshin }
4174c9c98f3SStanislav Mekhanoshin Arg = new BitCastInst(Arg, IType, "PrintArgFP", Brnch);
4184c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg);
4194c9c98f3SStanislav Mekhanoshin } else if (ArgType->getTypeID() == Type::PointerTyID) {
4204c9c98f3SStanislav Mekhanoshin if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) {
4214c9c98f3SStanislav Mekhanoshin const char *S = NonLiteralStr;
42297a23ab2SSimon Pilgrim if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) {
42397a23ab2SSimon Pilgrim auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
4244c9c98f3SStanislav Mekhanoshin if (GV && GV->hasInitializer()) {
4254c9c98f3SStanislav Mekhanoshin Constant *Init = GV->getInitializer();
426ee3da895SSimon Pilgrim bool IsZeroValue = Init->isZeroValue();
427ee3da895SSimon Pilgrim auto *CA = dyn_cast<ConstantDataArray>(Init);
428ee3da895SSimon Pilgrim if (IsZeroValue || (CA && CA->isString())) {
429ee3da895SSimon Pilgrim S = IsZeroValue ? "" : CA->getAsCString().data();
4304c9c98f3SStanislav Mekhanoshin }
4314c9c98f3SStanislav Mekhanoshin }
4324c9c98f3SStanislav Mekhanoshin }
4334c9c98f3SStanislav Mekhanoshin size_t SizeStr = strlen(S) + 1;
4344c9c98f3SStanislav Mekhanoshin size_t Rem = SizeStr % DWORD_ALIGN;
4354c9c98f3SStanislav Mekhanoshin size_t NSizeStr = 0;
4364c9c98f3SStanislav Mekhanoshin if (Rem) {
4374c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr + (DWORD_ALIGN - Rem);
4384c9c98f3SStanislav Mekhanoshin } else {
4394c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr;
4404c9c98f3SStanislav Mekhanoshin }
4414c9c98f3SStanislav Mekhanoshin if (S[0]) {
4424c9c98f3SStanislav Mekhanoshin char *MyNewStr = new char[NSizeStr]();
4434c9c98f3SStanislav Mekhanoshin strcpy(MyNewStr, S);
4444c9c98f3SStanislav Mekhanoshin int NumInts = NSizeStr / 4;
4454c9c98f3SStanislav Mekhanoshin int CharC = 0;
4464c9c98f3SStanislav Mekhanoshin while (NumInts) {
4474c9c98f3SStanislav Mekhanoshin int ANum = *(int *)(MyNewStr + CharC);
4484c9c98f3SStanislav Mekhanoshin CharC += 4;
4494c9c98f3SStanislav Mekhanoshin NumInts--;
4504c9c98f3SStanislav Mekhanoshin Value *ANumV = ConstantInt::get(Int32Ty, ANum, false);
4514c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(ANumV);
4524c9c98f3SStanislav Mekhanoshin }
4534c9c98f3SStanislav Mekhanoshin delete[] MyNewStr;
4544c9c98f3SStanislav Mekhanoshin } else {
4554c9c98f3SStanislav Mekhanoshin // Empty string, give a hint to RT it is no NULL
4564c9c98f3SStanislav Mekhanoshin Value *ANumV = ConstantInt::get(Int32Ty, 0xFFFFFF00, false);
4574c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(ANumV);
4584c9c98f3SStanislav Mekhanoshin }
4594c9c98f3SStanislav Mekhanoshin } else {
4604c9c98f3SStanislav Mekhanoshin uint64_t Size = TD->getTypeAllocSizeInBits(ArgType);
4614c9c98f3SStanislav Mekhanoshin assert((Size == 32 || Size == 64) && "unsupported size");
4624c9c98f3SStanislav Mekhanoshin Type *DstType = (Size == 32) ? Int32Ty : Int64Ty;
4634c9c98f3SStanislav Mekhanoshin Arg = new PtrToIntInst(Arg, DstType, "PrintArgPtr", Brnch);
4644c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg);
4654c9c98f3SStanislav Mekhanoshin }
4662dea3f12SChristopher Tetreault } else if (isa<FixedVectorType>(ArgType)) {
4675a667c0eSKazu Hirata Type *IType = nullptr;
4683254a001SChristopher Tetreault uint32_t EleCount = cast<FixedVectorType>(ArgType)->getNumElements();
4694c9c98f3SStanislav Mekhanoshin uint32_t EleSize = ArgType->getScalarSizeInBits();
4704c9c98f3SStanislav Mekhanoshin uint32_t TotalSize = EleCount * EleSize;
4714c9c98f3SStanislav Mekhanoshin if (EleCount == 3) {
472cc035d47SBenjamin Kramer ShuffleVectorInst *Shuffle =
473cc035d47SBenjamin Kramer new ShuffleVectorInst(Arg, Arg, ArrayRef<int>{0, 1, 2, 2});
4744c9c98f3SStanislav Mekhanoshin Shuffle->insertBefore(Brnch);
4754c9c98f3SStanislav Mekhanoshin Arg = Shuffle;
4764c9c98f3SStanislav Mekhanoshin ArgType = Arg->getType();
4774c9c98f3SStanislav Mekhanoshin TotalSize += EleSize;
4784c9c98f3SStanislav Mekhanoshin }
4794c9c98f3SStanislav Mekhanoshin switch (EleSize) {
4804c9c98f3SStanislav Mekhanoshin default:
4814c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64;
48297a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext());
4834c9c98f3SStanislav Mekhanoshin break;
4844c9c98f3SStanislav Mekhanoshin case 8:
4854c9c98f3SStanislav Mekhanoshin if (EleCount >= 8) {
4864c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64;
48797a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext());
4884c9c98f3SStanislav Mekhanoshin } else if (EleCount >= 3) {
4894c9c98f3SStanislav Mekhanoshin EleCount = 1;
49097a23ab2SSimon Pilgrim IType = Type::getInt32Ty(ArgType->getContext());
4914c9c98f3SStanislav Mekhanoshin } else {
4924c9c98f3SStanislav Mekhanoshin EleCount = 1;
49397a23ab2SSimon Pilgrim IType = Type::getInt16Ty(ArgType->getContext());
4944c9c98f3SStanislav Mekhanoshin }
4954c9c98f3SStanislav Mekhanoshin break;
4964c9c98f3SStanislav Mekhanoshin case 16:
4974c9c98f3SStanislav Mekhanoshin if (EleCount >= 3) {
4984c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64;
49997a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext());
5004c9c98f3SStanislav Mekhanoshin } else {
5014c9c98f3SStanislav Mekhanoshin EleCount = 1;
50297a23ab2SSimon Pilgrim IType = Type::getInt32Ty(ArgType->getContext());
5034c9c98f3SStanislav Mekhanoshin }
5044c9c98f3SStanislav Mekhanoshin break;
5054c9c98f3SStanislav Mekhanoshin }
5064c9c98f3SStanislav Mekhanoshin if (EleCount > 1) {
507aad93654SChristopher Tetreault IType = FixedVectorType::get(IType, EleCount);
5084c9c98f3SStanislav Mekhanoshin }
5094c9c98f3SStanislav Mekhanoshin Arg = new BitCastInst(Arg, IType, "PrintArgVect", Brnch);
5104c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg);
5114c9c98f3SStanislav Mekhanoshin } else {
5124c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg);
5134c9c98f3SStanislav Mekhanoshin }
514438315bfSStanislav Mekhanoshin for (unsigned I = 0, E = WhatToStore.size(); I != E; ++I) {
515438315bfSStanislav Mekhanoshin Value *TheBtCast = WhatToStore[I];
5164c9c98f3SStanislav Mekhanoshin unsigned ArgSize =
5174c9c98f3SStanislav Mekhanoshin TD->getTypeAllocSizeInBits(TheBtCast->getType()) / 8;
5184c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 1> BuffOffset;
5194c9c98f3SStanislav Mekhanoshin BuffOffset.push_back(ConstantInt::get(I32Ty, ArgSize));
5204c9c98f3SStanislav Mekhanoshin
5214c9c98f3SStanislav Mekhanoshin Type *ArgPointer = PointerType::get(TheBtCast->getType(), 1);
5224c9c98f3SStanislav Mekhanoshin Value *CastedGEP =
5234c9c98f3SStanislav Mekhanoshin new BitCastInst(BufferIdx, ArgPointer, "PrintBuffPtrCast", Brnch);
5244c9c98f3SStanislav Mekhanoshin StoreInst *StBuff = new StoreInst(TheBtCast, CastedGEP, Brnch);
5254c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "inserting store to printf buffer:\n"
5264c9c98f3SStanislav Mekhanoshin << *StBuff << '\n');
5274c9c98f3SStanislav Mekhanoshin (void)StBuff;
528c1e32b3fSKazu Hirata if (I + 1 == E && ArgCount + 1 == CI->arg_size())
5294c9c98f3SStanislav Mekhanoshin break;
530cfb94212SNikita Popov BufferIdx = GetElementPtrInst::Create(I8Ty, BufferIdx, BuffOffset,
53197a23ab2SSimon Pilgrim "PrintBuffNextPtr", Brnch);
5324c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:\n"
5334c9c98f3SStanislav Mekhanoshin << *BufferIdx << '\n');
5344c9c98f3SStanislav Mekhanoshin }
5354c9c98f3SStanislav Mekhanoshin }
5364c9c98f3SStanislav Mekhanoshin }
5374c9c98f3SStanislav Mekhanoshin }
5384c9c98f3SStanislav Mekhanoshin
5394c9c98f3SStanislav Mekhanoshin // erase the printf calls
540dafda610SJay Foad for (auto CI : Printfs)
5414c9c98f3SStanislav Mekhanoshin CI->eraseFromParent();
5424c9c98f3SStanislav Mekhanoshin
5434c9c98f3SStanislav Mekhanoshin Printfs.clear();
5444c9c98f3SStanislav Mekhanoshin return true;
5454c9c98f3SStanislav Mekhanoshin }
5464c9c98f3SStanislav Mekhanoshin
run(Module & M)547fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::run(Module &M) {
5484c9c98f3SStanislav Mekhanoshin Triple TT(M.getTargetTriple());
5494c9c98f3SStanislav Mekhanoshin if (TT.getArch() == Triple::r600)
5504c9c98f3SStanislav Mekhanoshin return false;
5514c9c98f3SStanislav Mekhanoshin
552dafda610SJay Foad auto PrintfFunction = M.getFunction("printf");
553dafda610SJay Foad if (!PrintfFunction)
554dafda610SJay Foad return false;
555dafda610SJay Foad
556dafda610SJay Foad for (auto &U : PrintfFunction->uses()) {
557dafda610SJay Foad if (auto *CI = dyn_cast<CallInst>(U.getUser())) {
558dafda610SJay Foad if (CI->isCallee(&U))
559dafda610SJay Foad Printfs.push_back(CI);
560dafda610SJay Foad }
561dafda610SJay Foad }
5624c9c98f3SStanislav Mekhanoshin
5634c9c98f3SStanislav Mekhanoshin if (Printfs.empty())
5644c9c98f3SStanislav Mekhanoshin return false;
5654c9c98f3SStanislav Mekhanoshin
5664c9c98f3SStanislav Mekhanoshin TD = &M.getDataLayout();
567fd323a89SArthur Eubanks
568fd323a89SArthur Eubanks return lowerPrintfForGpu(M);
569fd323a89SArthur Eubanks }
570fd323a89SArthur Eubanks
runOnModule(Module & M)571fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBinding::runOnModule(Module &M) {
572fd323a89SArthur Eubanks auto GetDT = [this](Function &F) -> DominatorTree & {
573fd323a89SArthur Eubanks return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
574fd323a89SArthur Eubanks };
5759c27b59cSTeresa Johnson auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
5769c27b59cSTeresa Johnson return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
5779c27b59cSTeresa Johnson };
5784c9c98f3SStanislav Mekhanoshin
579fd323a89SArthur Eubanks return AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M);
580fd323a89SArthur Eubanks }
581fd323a89SArthur Eubanks
582fd323a89SArthur Eubanks PreservedAnalyses
run(Module & M,ModuleAnalysisManager & AM)583fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBindingPass::run(Module &M, ModuleAnalysisManager &AM) {
584fd323a89SArthur Eubanks FunctionAnalysisManager &FAM =
585fd323a89SArthur Eubanks AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
586fd323a89SArthur Eubanks auto GetDT = [&FAM](Function &F) -> DominatorTree & {
587fd323a89SArthur Eubanks return FAM.getResult<DominatorTreeAnalysis>(F);
588fd323a89SArthur Eubanks };
589fd323a89SArthur Eubanks auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
590fd323a89SArthur Eubanks return FAM.getResult<TargetLibraryAnalysis>(F);
591fd323a89SArthur Eubanks };
592fd323a89SArthur Eubanks bool Changed = AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M);
593fd323a89SArthur Eubanks return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
5944c9c98f3SStanislav Mekhanoshin }
595