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" 224c9c98f3SStanislav Mekhanoshin #include "llvm/Analysis/InstructionSimplify.h" 234c9c98f3SStanislav Mekhanoshin #include "llvm/Analysis/TargetLibraryInfo.h" 244c9c98f3SStanislav Mekhanoshin #include "llvm/IR/Dominators.h" 254c9c98f3SStanislav Mekhanoshin #include "llvm/IR/IRBuilder.h" 264c9c98f3SStanislav Mekhanoshin #include "llvm/IR/Instructions.h" 2705da2fe5SReid Kleckner #include "llvm/InitializePasses.h" 284c9c98f3SStanislav Mekhanoshin #include "llvm/Transforms/Utils/BasicBlockUtils.h" 296a87e9b0Sdfukalov 304c9c98f3SStanislav Mekhanoshin using namespace llvm; 314c9c98f3SStanislav Mekhanoshin 324c9c98f3SStanislav Mekhanoshin #define DEBUG_TYPE "printfToRuntime" 334c9c98f3SStanislav Mekhanoshin #define DWORD_ALIGN 4 344c9c98f3SStanislav Mekhanoshin 354c9c98f3SStanislav Mekhanoshin namespace { 36fd323a89SArthur Eubanks class AMDGPUPrintfRuntimeBinding final : public ModulePass { 374c9c98f3SStanislav Mekhanoshin 384c9c98f3SStanislav Mekhanoshin public: 394c9c98f3SStanislav Mekhanoshin static char ID; 404c9c98f3SStanislav Mekhanoshin 414c9c98f3SStanislav Mekhanoshin explicit AMDGPUPrintfRuntimeBinding(); 424c9c98f3SStanislav Mekhanoshin 434c9c98f3SStanislav Mekhanoshin private: 444c9c98f3SStanislav Mekhanoshin bool runOnModule(Module &M) override; 454c9c98f3SStanislav Mekhanoshin 464c9c98f3SStanislav Mekhanoshin void getAnalysisUsage(AnalysisUsage &AU) const override { 474c9c98f3SStanislav Mekhanoshin AU.addRequired<TargetLibraryInfoWrapperPass>(); 484c9c98f3SStanislav Mekhanoshin AU.addRequired<DominatorTreeWrapperPass>(); 494c9c98f3SStanislav Mekhanoshin } 50fd323a89SArthur Eubanks }; 514c9c98f3SStanislav Mekhanoshin 52fd323a89SArthur Eubanks class AMDGPUPrintfRuntimeBindingImpl { 53fd323a89SArthur Eubanks public: 54fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBindingImpl( 55fd323a89SArthur Eubanks function_ref<const DominatorTree &(Function &)> GetDT, 56fd323a89SArthur Eubanks function_ref<const TargetLibraryInfo &(Function &)> GetTLI) 57fd323a89SArthur Eubanks : GetDT(GetDT), GetTLI(GetTLI) {} 58fd323a89SArthur Eubanks bool run(Module &M); 59fd323a89SArthur Eubanks 60fd323a89SArthur Eubanks private: 61fd323a89SArthur Eubanks void getConversionSpecifiers(SmallVectorImpl<char> &OpConvSpecifiers, 62fd323a89SArthur Eubanks StringRef fmt, size_t num_ops) const; 63fd323a89SArthur Eubanks 64fd323a89SArthur Eubanks bool shouldPrintAsStr(char Specifier, Type *OpType) const; 65fd323a89SArthur Eubanks bool lowerPrintfForGpu(Module &M); 66fd323a89SArthur Eubanks 67fd323a89SArthur Eubanks Value *simplify(Instruction *I, const TargetLibraryInfo *TLI, 68fd323a89SArthur Eubanks const DominatorTree *DT) { 694c9c98f3SStanislav Mekhanoshin return SimplifyInstruction(I, {*TD, TLI, DT}); 704c9c98f3SStanislav Mekhanoshin } 714c9c98f3SStanislav Mekhanoshin 724c9c98f3SStanislav Mekhanoshin const DataLayout *TD; 73fd323a89SArthur Eubanks function_ref<const DominatorTree &(Function &)> GetDT; 74fd323a89SArthur Eubanks function_ref<const TargetLibraryInfo &(Function &)> GetTLI; 75dafda610SJay Foad SmallVector<CallInst *, 32> Printfs; 764c9c98f3SStanislav Mekhanoshin }; 774c9c98f3SStanislav Mekhanoshin } // namespace 784c9c98f3SStanislav Mekhanoshin 794c9c98f3SStanislav Mekhanoshin char AMDGPUPrintfRuntimeBinding::ID = 0; 804c9c98f3SStanislav Mekhanoshin 814c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_BEGIN(AMDGPUPrintfRuntimeBinding, 824c9c98f3SStanislav Mekhanoshin "amdgpu-printf-runtime-binding", "AMDGPU Printf lowering", 834c9c98f3SStanislav Mekhanoshin false, false) 844c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 854c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 864c9c98f3SStanislav Mekhanoshin INITIALIZE_PASS_END(AMDGPUPrintfRuntimeBinding, "amdgpu-printf-runtime-binding", 874c9c98f3SStanislav Mekhanoshin "AMDGPU Printf lowering", false, false) 884c9c98f3SStanislav Mekhanoshin 894c9c98f3SStanislav Mekhanoshin char &llvm::AMDGPUPrintfRuntimeBindingID = AMDGPUPrintfRuntimeBinding::ID; 904c9c98f3SStanislav Mekhanoshin 914c9c98f3SStanislav Mekhanoshin namespace llvm { 924c9c98f3SStanislav Mekhanoshin ModulePass *createAMDGPUPrintfRuntimeBinding() { 934c9c98f3SStanislav Mekhanoshin return new AMDGPUPrintfRuntimeBinding(); 944c9c98f3SStanislav Mekhanoshin } 954c9c98f3SStanislav Mekhanoshin } // namespace llvm 964c9c98f3SStanislav Mekhanoshin 97fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBinding::AMDGPUPrintfRuntimeBinding() : ModulePass(ID) { 984c9c98f3SStanislav Mekhanoshin initializeAMDGPUPrintfRuntimeBindingPass(*PassRegistry::getPassRegistry()); 994c9c98f3SStanislav Mekhanoshin } 1004c9c98f3SStanislav Mekhanoshin 101fd323a89SArthur Eubanks void AMDGPUPrintfRuntimeBindingImpl::getConversionSpecifiers( 1024c9c98f3SStanislav Mekhanoshin SmallVectorImpl<char> &OpConvSpecifiers, StringRef Fmt, 1034c9c98f3SStanislav Mekhanoshin size_t NumOps) const { 1044c9c98f3SStanislav Mekhanoshin // not all format characters are collected. 1054c9c98f3SStanislav Mekhanoshin // At this time the format characters of interest 1064c9c98f3SStanislav Mekhanoshin // are %p and %s, which use to know if we 1074c9c98f3SStanislav Mekhanoshin // are either storing a literal string or a 1084c9c98f3SStanislav Mekhanoshin // pointer to the printf buffer. 1094c9c98f3SStanislav Mekhanoshin static const char ConvSpecifiers[] = "cdieEfgGaosuxXp"; 1104c9c98f3SStanislav Mekhanoshin size_t CurFmtSpecifierIdx = 0; 1114c9c98f3SStanislav Mekhanoshin size_t PrevFmtSpecifierIdx = 0; 1124c9c98f3SStanislav Mekhanoshin 1134c9c98f3SStanislav Mekhanoshin while ((CurFmtSpecifierIdx = Fmt.find_first_of( 1144c9c98f3SStanislav Mekhanoshin ConvSpecifiers, CurFmtSpecifierIdx)) != StringRef::npos) { 1154c9c98f3SStanislav Mekhanoshin bool ArgDump = false; 1164c9c98f3SStanislav Mekhanoshin StringRef CurFmt = Fmt.substr(PrevFmtSpecifierIdx, 1174c9c98f3SStanislav Mekhanoshin CurFmtSpecifierIdx - PrevFmtSpecifierIdx); 1184c9c98f3SStanislav Mekhanoshin size_t pTag = CurFmt.find_last_of("%"); 1194c9c98f3SStanislav Mekhanoshin if (pTag != StringRef::npos) { 1204c9c98f3SStanislav Mekhanoshin ArgDump = true; 1214c9c98f3SStanislav Mekhanoshin while (pTag && CurFmt[--pTag] == '%') { 1224c9c98f3SStanislav Mekhanoshin ArgDump = !ArgDump; 1234c9c98f3SStanislav Mekhanoshin } 1244c9c98f3SStanislav Mekhanoshin } 1254c9c98f3SStanislav Mekhanoshin 1264c9c98f3SStanislav Mekhanoshin if (ArgDump) 1274c9c98f3SStanislav Mekhanoshin OpConvSpecifiers.push_back(Fmt[CurFmtSpecifierIdx]); 1284c9c98f3SStanislav Mekhanoshin 1294c9c98f3SStanislav Mekhanoshin PrevFmtSpecifierIdx = ++CurFmtSpecifierIdx; 1304c9c98f3SStanislav Mekhanoshin } 1314c9c98f3SStanislav Mekhanoshin } 1324c9c98f3SStanislav Mekhanoshin 133fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::shouldPrintAsStr(char Specifier, 1344c9c98f3SStanislav Mekhanoshin Type *OpType) const { 1354c9c98f3SStanislav Mekhanoshin if (Specifier != 's') 1364c9c98f3SStanislav Mekhanoshin return false; 1374c9c98f3SStanislav Mekhanoshin const PointerType *PT = dyn_cast<PointerType>(OpType); 1384c9c98f3SStanislav Mekhanoshin if (!PT || PT->getAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS) 1394c9c98f3SStanislav Mekhanoshin return false; 1404c9c98f3SStanislav Mekhanoshin Type *ElemType = PT->getContainedType(0); 1414c9c98f3SStanislav Mekhanoshin if (ElemType->getTypeID() != Type::IntegerTyID) 1424c9c98f3SStanislav Mekhanoshin return false; 1434c9c98f3SStanislav Mekhanoshin IntegerType *ElemIType = cast<IntegerType>(ElemType); 1444c9c98f3SStanislav Mekhanoshin return ElemIType->getBitWidth() == 8; 1454c9c98f3SStanislav Mekhanoshin } 1464c9c98f3SStanislav Mekhanoshin 147fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) { 1484c9c98f3SStanislav Mekhanoshin LLVMContext &Ctx = M.getContext(); 1494c9c98f3SStanislav Mekhanoshin IRBuilder<> Builder(Ctx); 1504c9c98f3SStanislav Mekhanoshin Type *I32Ty = Type::getInt32Ty(Ctx); 1514c9c98f3SStanislav Mekhanoshin unsigned UniqID = 0; 152*dc6e8dfdSJacob Lambert // NB: This is important for this string size to be divisible by 4 1534c9c98f3SStanislav Mekhanoshin const char NonLiteralStr[4] = "???"; 1544c9c98f3SStanislav Mekhanoshin 155dafda610SJay Foad for (auto CI : Printfs) { 1564c9c98f3SStanislav Mekhanoshin unsigned NumOps = CI->getNumArgOperands(); 1574c9c98f3SStanislav Mekhanoshin 1584c9c98f3SStanislav Mekhanoshin SmallString<16> OpConvSpecifiers; 1594c9c98f3SStanislav Mekhanoshin Value *Op = CI->getArgOperand(0); 1604c9c98f3SStanislav Mekhanoshin 1614c9c98f3SStanislav Mekhanoshin if (auto LI = dyn_cast<LoadInst>(Op)) { 1624c9c98f3SStanislav Mekhanoshin Op = LI->getPointerOperand(); 1634c9c98f3SStanislav Mekhanoshin for (auto Use : Op->users()) { 1644c9c98f3SStanislav Mekhanoshin if (auto SI = dyn_cast<StoreInst>(Use)) { 1654c9c98f3SStanislav Mekhanoshin Op = SI->getValueOperand(); 1664c9c98f3SStanislav Mekhanoshin break; 1674c9c98f3SStanislav Mekhanoshin } 1684c9c98f3SStanislav Mekhanoshin } 1694c9c98f3SStanislav Mekhanoshin } 1704c9c98f3SStanislav Mekhanoshin 1714c9c98f3SStanislav Mekhanoshin if (auto I = dyn_cast<Instruction>(Op)) { 172fd323a89SArthur Eubanks Value *Op_simplified = 173fd323a89SArthur Eubanks simplify(I, &GetTLI(*I->getFunction()), &GetDT(*I->getFunction())); 1744c9c98f3SStanislav Mekhanoshin if (Op_simplified) 1754c9c98f3SStanislav Mekhanoshin Op = Op_simplified; 1764c9c98f3SStanislav Mekhanoshin } 1774c9c98f3SStanislav Mekhanoshin 1784c9c98f3SStanislav Mekhanoshin ConstantExpr *ConstExpr = dyn_cast<ConstantExpr>(Op); 1794c9c98f3SStanislav Mekhanoshin 1804c9c98f3SStanislav Mekhanoshin if (ConstExpr) { 1814c9c98f3SStanislav Mekhanoshin GlobalVariable *GVar = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); 1824c9c98f3SStanislav Mekhanoshin 1834c9c98f3SStanislav Mekhanoshin StringRef Str("unknown"); 1844c9c98f3SStanislav Mekhanoshin if (GVar && GVar->hasInitializer()) { 185ee3da895SSimon Pilgrim auto *Init = GVar->getInitializer(); 186ee3da895SSimon Pilgrim if (auto *CA = dyn_cast<ConstantDataArray>(Init)) { 1874c9c98f3SStanislav Mekhanoshin if (CA->isString()) 1884c9c98f3SStanislav Mekhanoshin Str = CA->getAsCString(); 1894c9c98f3SStanislav Mekhanoshin } else if (isa<ConstantAggregateZero>(Init)) { 1904c9c98f3SStanislav Mekhanoshin Str = ""; 1914c9c98f3SStanislav Mekhanoshin } 1924c9c98f3SStanislav Mekhanoshin // 1934c9c98f3SStanislav Mekhanoshin // we need this call to ascertain 1944c9c98f3SStanislav Mekhanoshin // that we are printing a string 1954c9c98f3SStanislav Mekhanoshin // or a pointer. It takes out the 1964c9c98f3SStanislav Mekhanoshin // specifiers and fills up the first 1974c9c98f3SStanislav Mekhanoshin // arg 1984c9c98f3SStanislav Mekhanoshin getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1); 1994c9c98f3SStanislav Mekhanoshin } 2004c9c98f3SStanislav Mekhanoshin // Add metadata for the string 2014c9c98f3SStanislav Mekhanoshin std::string AStreamHolder; 2024c9c98f3SStanislav Mekhanoshin raw_string_ostream Sizes(AStreamHolder); 2034c9c98f3SStanislav Mekhanoshin int Sum = DWORD_ALIGN; 2044c9c98f3SStanislav Mekhanoshin Sizes << CI->getNumArgOperands() - 1; 2054c9c98f3SStanislav Mekhanoshin Sizes << ':'; 2064c9c98f3SStanislav Mekhanoshin for (unsigned ArgCount = 1; ArgCount < CI->getNumArgOperands() && 2074c9c98f3SStanislav Mekhanoshin ArgCount <= OpConvSpecifiers.size(); 2084c9c98f3SStanislav Mekhanoshin ArgCount++) { 2094c9c98f3SStanislav Mekhanoshin Value *Arg = CI->getArgOperand(ArgCount); 2104c9c98f3SStanislav Mekhanoshin Type *ArgType = Arg->getType(); 2114c9c98f3SStanislav Mekhanoshin unsigned ArgSize = TD->getTypeAllocSizeInBits(ArgType); 2124c9c98f3SStanislav Mekhanoshin ArgSize = ArgSize / 8; 2134c9c98f3SStanislav Mekhanoshin // 2144c9c98f3SStanislav Mekhanoshin // ArgSize by design should be a multiple of DWORD_ALIGN, 2154c9c98f3SStanislav Mekhanoshin // expand the arguments that do not follow this rule. 2164c9c98f3SStanislav Mekhanoshin // 2174c9c98f3SStanislav Mekhanoshin if (ArgSize % DWORD_ALIGN != 0) { 2184c9c98f3SStanislav Mekhanoshin llvm::Type *ResType = llvm::Type::getInt32Ty(Ctx); 2193254a001SChristopher Tetreault auto *LLVMVecType = llvm::dyn_cast<llvm::FixedVectorType>(ArgType); 2204c9c98f3SStanislav Mekhanoshin int NumElem = LLVMVecType ? LLVMVecType->getNumElements() : 1; 2214c9c98f3SStanislav Mekhanoshin if (LLVMVecType && NumElem > 1) 2223254a001SChristopher Tetreault ResType = llvm::FixedVectorType::get(ResType, NumElem); 2234c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(CI); 2244c9c98f3SStanislav Mekhanoshin Builder.SetCurrentDebugLocation(CI->getDebugLoc()); 2254c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'x' || 2264c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'X' || 2274c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'u' || 2284c9c98f3SStanislav Mekhanoshin OpConvSpecifiers[ArgCount - 1] == 'o') 2294c9c98f3SStanislav Mekhanoshin Arg = Builder.CreateZExt(Arg, ResType); 2304c9c98f3SStanislav Mekhanoshin else 2314c9c98f3SStanislav Mekhanoshin Arg = Builder.CreateSExt(Arg, ResType); 2324c9c98f3SStanislav Mekhanoshin ArgType = Arg->getType(); 2334c9c98f3SStanislav Mekhanoshin ArgSize = TD->getTypeAllocSizeInBits(ArgType); 2344c9c98f3SStanislav Mekhanoshin ArgSize = ArgSize / 8; 2354c9c98f3SStanislav Mekhanoshin CI->setOperand(ArgCount, Arg); 2364c9c98f3SStanislav Mekhanoshin } 2374c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'f') { 2384c9c98f3SStanislav Mekhanoshin ConstantFP *FpCons = dyn_cast<ConstantFP>(Arg); 2394c9c98f3SStanislav Mekhanoshin if (FpCons) 2404c9c98f3SStanislav Mekhanoshin ArgSize = 4; 2414c9c98f3SStanislav Mekhanoshin else { 2424c9c98f3SStanislav Mekhanoshin FPExtInst *FpExt = dyn_cast<FPExtInst>(Arg); 2434c9c98f3SStanislav Mekhanoshin if (FpExt && FpExt->getType()->isDoubleTy() && 2444c9c98f3SStanislav Mekhanoshin FpExt->getOperand(0)->getType()->isFloatTy()) 2454c9c98f3SStanislav Mekhanoshin ArgSize = 4; 2464c9c98f3SStanislav Mekhanoshin } 2474c9c98f3SStanislav Mekhanoshin } 2484c9c98f3SStanislav Mekhanoshin if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) { 249ee3da895SSimon Pilgrim if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) { 250ee3da895SSimon Pilgrim auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); 2514c9c98f3SStanislav Mekhanoshin if (GV && GV->hasInitializer()) { 2524c9c98f3SStanislav Mekhanoshin Constant *Init = GV->getInitializer(); 253ee3da895SSimon Pilgrim bool IsZeroValue = Init->isZeroValue(); 254ee3da895SSimon Pilgrim auto *CA = dyn_cast<ConstantDataArray>(Init); 255ee3da895SSimon Pilgrim if (IsZeroValue || (CA && CA->isString())) { 256ee3da895SSimon Pilgrim size_t SizeStr = 257ee3da895SSimon Pilgrim IsZeroValue ? 1 : (strlen(CA->getAsCString().data()) + 1); 2584c9c98f3SStanislav Mekhanoshin size_t Rem = SizeStr % DWORD_ALIGN; 2594c9c98f3SStanislav Mekhanoshin size_t NSizeStr = 0; 2604c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf string original size = " << SizeStr 2614c9c98f3SStanislav Mekhanoshin << '\n'); 2624c9c98f3SStanislav Mekhanoshin if (Rem) { 2634c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr + (DWORD_ALIGN - Rem); 2644c9c98f3SStanislav Mekhanoshin } else { 2654c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr; 2664c9c98f3SStanislav Mekhanoshin } 2674c9c98f3SStanislav Mekhanoshin ArgSize = NSizeStr; 2684c9c98f3SStanislav Mekhanoshin } 2694c9c98f3SStanislav Mekhanoshin } else { 2704c9c98f3SStanislav Mekhanoshin ArgSize = sizeof(NonLiteralStr); 2714c9c98f3SStanislav Mekhanoshin } 2724c9c98f3SStanislav Mekhanoshin } else { 2734c9c98f3SStanislav Mekhanoshin ArgSize = sizeof(NonLiteralStr); 2744c9c98f3SStanislav Mekhanoshin } 2754c9c98f3SStanislav Mekhanoshin } 2764c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf ArgSize (in buffer) = " << ArgSize 2774c9c98f3SStanislav Mekhanoshin << " for type: " << *ArgType << '\n'); 2784c9c98f3SStanislav Mekhanoshin Sizes << ArgSize << ':'; 2794c9c98f3SStanislav Mekhanoshin Sum += ArgSize; 2804c9c98f3SStanislav Mekhanoshin } 2814c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf format string in source = " << Str.str() 2824c9c98f3SStanislav Mekhanoshin << '\n'); 2834c9c98f3SStanislav Mekhanoshin for (size_t I = 0; I < Str.size(); ++I) { 2844c9c98f3SStanislav Mekhanoshin // Rest of the C escape sequences (e.g. \') are handled correctly 2854c9c98f3SStanislav Mekhanoshin // by the MDParser 2864c9c98f3SStanislav Mekhanoshin switch (Str[I]) { 2874c9c98f3SStanislav Mekhanoshin case '\a': 2884c9c98f3SStanislav Mekhanoshin Sizes << "\\a"; 2894c9c98f3SStanislav Mekhanoshin break; 2904c9c98f3SStanislav Mekhanoshin case '\b': 2914c9c98f3SStanislav Mekhanoshin Sizes << "\\b"; 2924c9c98f3SStanislav Mekhanoshin break; 2934c9c98f3SStanislav Mekhanoshin case '\f': 2944c9c98f3SStanislav Mekhanoshin Sizes << "\\f"; 2954c9c98f3SStanislav Mekhanoshin break; 2964c9c98f3SStanislav Mekhanoshin case '\n': 2974c9c98f3SStanislav Mekhanoshin Sizes << "\\n"; 2984c9c98f3SStanislav Mekhanoshin break; 2994c9c98f3SStanislav Mekhanoshin case '\r': 3004c9c98f3SStanislav Mekhanoshin Sizes << "\\r"; 3014c9c98f3SStanislav Mekhanoshin break; 3024c9c98f3SStanislav Mekhanoshin case '\v': 3034c9c98f3SStanislav Mekhanoshin Sizes << "\\v"; 3044c9c98f3SStanislav Mekhanoshin break; 3054c9c98f3SStanislav Mekhanoshin case ':': 3064c9c98f3SStanislav Mekhanoshin // ':' cannot be scanned by Flex, as it is defined as a delimiter 3074c9c98f3SStanislav Mekhanoshin // Replace it with it's octal representation \72 3084c9c98f3SStanislav Mekhanoshin Sizes << "\\72"; 3094c9c98f3SStanislav Mekhanoshin break; 3104c9c98f3SStanislav Mekhanoshin default: 3114c9c98f3SStanislav Mekhanoshin Sizes << Str[I]; 3124c9c98f3SStanislav Mekhanoshin break; 3134c9c98f3SStanislav Mekhanoshin } 3144c9c98f3SStanislav Mekhanoshin } 3154c9c98f3SStanislav Mekhanoshin 3164c9c98f3SStanislav Mekhanoshin // Insert the printf_alloc call 3174c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(CI); 3184c9c98f3SStanislav Mekhanoshin Builder.SetCurrentDebugLocation(CI->getDebugLoc()); 3194c9c98f3SStanislav Mekhanoshin 3204c9c98f3SStanislav Mekhanoshin AttributeList Attr = AttributeList::get(Ctx, AttributeList::FunctionIndex, 3214c9c98f3SStanislav Mekhanoshin Attribute::NoUnwind); 3224c9c98f3SStanislav Mekhanoshin 3234c9c98f3SStanislav Mekhanoshin Type *SizetTy = Type::getInt32Ty(Ctx); 3244c9c98f3SStanislav Mekhanoshin 3254c9c98f3SStanislav Mekhanoshin Type *Tys_alloc[1] = {SizetTy}; 326cfb94212SNikita Popov Type *I8Ty = Type::getInt8Ty(Ctx); 327cfb94212SNikita Popov Type *I8Ptr = PointerType::get(I8Ty, 1); 3284c9c98f3SStanislav Mekhanoshin FunctionType *FTy_alloc = FunctionType::get(I8Ptr, Tys_alloc, false); 3294c9c98f3SStanislav Mekhanoshin FunctionCallee PrintfAllocFn = 3304c9c98f3SStanislav Mekhanoshin M.getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr); 3314c9c98f3SStanislav Mekhanoshin 3324c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "Printf metadata = " << Sizes.str() << '\n'); 333c50faffbSKazu Hirata std::string fmtstr = itostr(++UniqID) + ":" + Sizes.str(); 3344c9c98f3SStanislav Mekhanoshin MDString *fmtStrArray = MDString::get(Ctx, fmtstr); 3354c9c98f3SStanislav Mekhanoshin 3364c9c98f3SStanislav Mekhanoshin // Instead of creating global variables, the 3374c9c98f3SStanislav Mekhanoshin // printf format strings are extracted 3384c9c98f3SStanislav Mekhanoshin // and passed as metadata. This avoids 3394c9c98f3SStanislav Mekhanoshin // polluting llvm's symbol tables in this module. 3404c9c98f3SStanislav Mekhanoshin // Metadata is going to be extracted 3414c9c98f3SStanislav Mekhanoshin // by the backend passes and inserted 3424c9c98f3SStanislav Mekhanoshin // into the OpenCL binary as appropriate. 3434c9c98f3SStanislav Mekhanoshin StringRef amd("llvm.printf.fmts"); 3444c9c98f3SStanislav Mekhanoshin NamedMDNode *metaD = M.getOrInsertNamedMetadata(amd); 3454c9c98f3SStanislav Mekhanoshin MDNode *myMD = MDNode::get(Ctx, fmtStrArray); 3464c9c98f3SStanislav Mekhanoshin metaD->addOperand(myMD); 3474c9c98f3SStanislav Mekhanoshin Value *sumC = ConstantInt::get(SizetTy, Sum, false); 3484c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 1> alloc_args; 3494c9c98f3SStanislav Mekhanoshin alloc_args.push_back(sumC); 3504c9c98f3SStanislav Mekhanoshin CallInst *pcall = 3514c9c98f3SStanislav Mekhanoshin CallInst::Create(PrintfAllocFn, alloc_args, "printf_alloc_fn", CI); 3524c9c98f3SStanislav Mekhanoshin 3534c9c98f3SStanislav Mekhanoshin // 3544c9c98f3SStanislav Mekhanoshin // Insert code to split basicblock with a 3554c9c98f3SStanislav Mekhanoshin // piece of hammock code. 3564c9c98f3SStanislav Mekhanoshin // basicblock splits after buffer overflow check 3574c9c98f3SStanislav Mekhanoshin // 3584c9c98f3SStanislav Mekhanoshin ConstantPointerNull *zeroIntPtr = 359cfb94212SNikita Popov ConstantPointerNull::get(PointerType::get(I8Ty, 1)); 3600805e40aSSimon Pilgrim auto *cmp = cast<ICmpInst>(Builder.CreateICmpNE(pcall, zeroIntPtr, "")); 3614c9c98f3SStanislav Mekhanoshin if (!CI->use_empty()) { 3624c9c98f3SStanislav Mekhanoshin Value *result = 3634c9c98f3SStanislav Mekhanoshin Builder.CreateSExt(Builder.CreateNot(cmp), I32Ty, "printf_res"); 3644c9c98f3SStanislav Mekhanoshin CI->replaceAllUsesWith(result); 3654c9c98f3SStanislav Mekhanoshin } 3664c9c98f3SStanislav Mekhanoshin SplitBlock(CI->getParent(), cmp); 3674c9c98f3SStanislav Mekhanoshin Instruction *Brnch = 3684c9c98f3SStanislav Mekhanoshin SplitBlockAndInsertIfThen(cmp, cmp->getNextNode(), false); 3694c9c98f3SStanislav Mekhanoshin 3704c9c98f3SStanislav Mekhanoshin Builder.SetInsertPoint(Brnch); 3714c9c98f3SStanislav Mekhanoshin 3724c9c98f3SStanislav Mekhanoshin // store unique printf id in the buffer 3734c9c98f3SStanislav Mekhanoshin // 37497a23ab2SSimon Pilgrim GetElementPtrInst *BufferIdx = GetElementPtrInst::Create( 3759e225a2aSNikita Popov I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 0)), "PrintBuffID", 3769e225a2aSNikita Popov Brnch); 3774c9c98f3SStanislav Mekhanoshin 3784c9c98f3SStanislav Mekhanoshin Type *idPointer = PointerType::get(I32Ty, AMDGPUAS::GLOBAL_ADDRESS); 3794c9c98f3SStanislav Mekhanoshin Value *id_gep_cast = 3804c9c98f3SStanislav Mekhanoshin new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", Brnch); 3814c9c98f3SStanislav Mekhanoshin 38211aa3707SEli Friedman new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast, Brnch); 3834c9c98f3SStanislav Mekhanoshin 3849e225a2aSNikita Popov // 1st 4 bytes hold the printf_id 3854c9c98f3SStanislav Mekhanoshin // the following GEP is the buffer pointer 3869e225a2aSNikita Popov BufferIdx = GetElementPtrInst::Create( 3879e225a2aSNikita Popov I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 4)), "PrintBuffGep", 3889e225a2aSNikita Popov Brnch); 3894c9c98f3SStanislav Mekhanoshin 3904c9c98f3SStanislav Mekhanoshin Type *Int32Ty = Type::getInt32Ty(Ctx); 3914c9c98f3SStanislav Mekhanoshin Type *Int64Ty = Type::getInt64Ty(Ctx); 3924c9c98f3SStanislav Mekhanoshin for (unsigned ArgCount = 1; ArgCount < CI->getNumArgOperands() && 3934c9c98f3SStanislav Mekhanoshin ArgCount <= OpConvSpecifiers.size(); 3944c9c98f3SStanislav Mekhanoshin ArgCount++) { 3954c9c98f3SStanislav Mekhanoshin Value *Arg = CI->getArgOperand(ArgCount); 3964c9c98f3SStanislav Mekhanoshin Type *ArgType = Arg->getType(); 3974c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 32> WhatToStore; 3982dea3f12SChristopher Tetreault if (ArgType->isFPOrFPVectorTy() && !isa<VectorType>(ArgType)) { 3994c9c98f3SStanislav Mekhanoshin Type *IType = (ArgType->isFloatTy()) ? Int32Ty : Int64Ty; 4004c9c98f3SStanislav Mekhanoshin if (OpConvSpecifiers[ArgCount - 1] == 'f') { 40197a23ab2SSimon Pilgrim if (auto *FpCons = dyn_cast<ConstantFP>(Arg)) { 40297a23ab2SSimon Pilgrim APFloat Val(FpCons->getValueAPF()); 4034c9c98f3SStanislav Mekhanoshin bool Lost = false; 4044c9c98f3SStanislav Mekhanoshin Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, 4054c9c98f3SStanislav Mekhanoshin &Lost); 4064c9c98f3SStanislav Mekhanoshin Arg = ConstantFP::get(Ctx, Val); 4074c9c98f3SStanislav Mekhanoshin IType = Int32Ty; 40897a23ab2SSimon Pilgrim } else if (auto *FpExt = dyn_cast<FPExtInst>(Arg)) { 40997a23ab2SSimon Pilgrim if (FpExt->getType()->isDoubleTy() && 4104c9c98f3SStanislav Mekhanoshin FpExt->getOperand(0)->getType()->isFloatTy()) { 4114c9c98f3SStanislav Mekhanoshin Arg = FpExt->getOperand(0); 4124c9c98f3SStanislav Mekhanoshin IType = Int32Ty; 4134c9c98f3SStanislav Mekhanoshin } 4144c9c98f3SStanislav Mekhanoshin } 4154c9c98f3SStanislav Mekhanoshin } 4164c9c98f3SStanislav Mekhanoshin Arg = new BitCastInst(Arg, IType, "PrintArgFP", Brnch); 4174c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg); 4184c9c98f3SStanislav Mekhanoshin } else if (ArgType->getTypeID() == Type::PointerTyID) { 4194c9c98f3SStanislav Mekhanoshin if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) { 4204c9c98f3SStanislav Mekhanoshin const char *S = NonLiteralStr; 42197a23ab2SSimon Pilgrim if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) { 42297a23ab2SSimon Pilgrim auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0)); 4234c9c98f3SStanislav Mekhanoshin if (GV && GV->hasInitializer()) { 4244c9c98f3SStanislav Mekhanoshin Constant *Init = GV->getInitializer(); 425ee3da895SSimon Pilgrim bool IsZeroValue = Init->isZeroValue(); 426ee3da895SSimon Pilgrim auto *CA = dyn_cast<ConstantDataArray>(Init); 427ee3da895SSimon Pilgrim if (IsZeroValue || (CA && CA->isString())) { 428ee3da895SSimon Pilgrim S = IsZeroValue ? "" : CA->getAsCString().data(); 4294c9c98f3SStanislav Mekhanoshin } 4304c9c98f3SStanislav Mekhanoshin } 4314c9c98f3SStanislav Mekhanoshin } 4324c9c98f3SStanislav Mekhanoshin size_t SizeStr = strlen(S) + 1; 4334c9c98f3SStanislav Mekhanoshin size_t Rem = SizeStr % DWORD_ALIGN; 4344c9c98f3SStanislav Mekhanoshin size_t NSizeStr = 0; 4354c9c98f3SStanislav Mekhanoshin if (Rem) { 4364c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr + (DWORD_ALIGN - Rem); 4374c9c98f3SStanislav Mekhanoshin } else { 4384c9c98f3SStanislav Mekhanoshin NSizeStr = SizeStr; 4394c9c98f3SStanislav Mekhanoshin } 4404c9c98f3SStanislav Mekhanoshin if (S[0]) { 4414c9c98f3SStanislav Mekhanoshin char *MyNewStr = new char[NSizeStr](); 4424c9c98f3SStanislav Mekhanoshin strcpy(MyNewStr, S); 4434c9c98f3SStanislav Mekhanoshin int NumInts = NSizeStr / 4; 4444c9c98f3SStanislav Mekhanoshin int CharC = 0; 4454c9c98f3SStanislav Mekhanoshin while (NumInts) { 4464c9c98f3SStanislav Mekhanoshin int ANum = *(int *)(MyNewStr + CharC); 4474c9c98f3SStanislav Mekhanoshin CharC += 4; 4484c9c98f3SStanislav Mekhanoshin NumInts--; 4494c9c98f3SStanislav Mekhanoshin Value *ANumV = ConstantInt::get(Int32Ty, ANum, false); 4504c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(ANumV); 4514c9c98f3SStanislav Mekhanoshin } 4524c9c98f3SStanislav Mekhanoshin delete[] MyNewStr; 4534c9c98f3SStanislav Mekhanoshin } else { 4544c9c98f3SStanislav Mekhanoshin // Empty string, give a hint to RT it is no NULL 4554c9c98f3SStanislav Mekhanoshin Value *ANumV = ConstantInt::get(Int32Ty, 0xFFFFFF00, false); 4564c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(ANumV); 4574c9c98f3SStanislav Mekhanoshin } 4584c9c98f3SStanislav Mekhanoshin } else { 4594c9c98f3SStanislav Mekhanoshin uint64_t Size = TD->getTypeAllocSizeInBits(ArgType); 4604c9c98f3SStanislav Mekhanoshin assert((Size == 32 || Size == 64) && "unsupported size"); 4614c9c98f3SStanislav Mekhanoshin Type *DstType = (Size == 32) ? Int32Ty : Int64Ty; 4624c9c98f3SStanislav Mekhanoshin Arg = new PtrToIntInst(Arg, DstType, "PrintArgPtr", Brnch); 4634c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg); 4644c9c98f3SStanislav Mekhanoshin } 4652dea3f12SChristopher Tetreault } else if (isa<FixedVectorType>(ArgType)) { 4664c9c98f3SStanislav Mekhanoshin Type *IType = NULL; 4673254a001SChristopher Tetreault uint32_t EleCount = cast<FixedVectorType>(ArgType)->getNumElements(); 4684c9c98f3SStanislav Mekhanoshin uint32_t EleSize = ArgType->getScalarSizeInBits(); 4694c9c98f3SStanislav Mekhanoshin uint32_t TotalSize = EleCount * EleSize; 4704c9c98f3SStanislav Mekhanoshin if (EleCount == 3) { 471cc035d47SBenjamin Kramer ShuffleVectorInst *Shuffle = 472cc035d47SBenjamin Kramer new ShuffleVectorInst(Arg, Arg, ArrayRef<int>{0, 1, 2, 2}); 4734c9c98f3SStanislav Mekhanoshin Shuffle->insertBefore(Brnch); 4744c9c98f3SStanislav Mekhanoshin Arg = Shuffle; 4754c9c98f3SStanislav Mekhanoshin ArgType = Arg->getType(); 4764c9c98f3SStanislav Mekhanoshin TotalSize += EleSize; 4774c9c98f3SStanislav Mekhanoshin } 4784c9c98f3SStanislav Mekhanoshin switch (EleSize) { 4794c9c98f3SStanislav Mekhanoshin default: 4804c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64; 48197a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext()); 4824c9c98f3SStanislav Mekhanoshin break; 4834c9c98f3SStanislav Mekhanoshin case 8: 4844c9c98f3SStanislav Mekhanoshin if (EleCount >= 8) { 4854c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64; 48697a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext()); 4874c9c98f3SStanislav Mekhanoshin } else if (EleCount >= 3) { 4884c9c98f3SStanislav Mekhanoshin EleCount = 1; 48997a23ab2SSimon Pilgrim IType = Type::getInt32Ty(ArgType->getContext()); 4904c9c98f3SStanislav Mekhanoshin } else { 4914c9c98f3SStanislav Mekhanoshin EleCount = 1; 49297a23ab2SSimon Pilgrim IType = Type::getInt16Ty(ArgType->getContext()); 4934c9c98f3SStanislav Mekhanoshin } 4944c9c98f3SStanislav Mekhanoshin break; 4954c9c98f3SStanislav Mekhanoshin case 16: 4964c9c98f3SStanislav Mekhanoshin if (EleCount >= 3) { 4974c9c98f3SStanislav Mekhanoshin EleCount = TotalSize / 64; 49897a23ab2SSimon Pilgrim IType = Type::getInt64Ty(ArgType->getContext()); 4994c9c98f3SStanislav Mekhanoshin } else { 5004c9c98f3SStanislav Mekhanoshin EleCount = 1; 50197a23ab2SSimon Pilgrim IType = Type::getInt32Ty(ArgType->getContext()); 5024c9c98f3SStanislav Mekhanoshin } 5034c9c98f3SStanislav Mekhanoshin break; 5044c9c98f3SStanislav Mekhanoshin } 5054c9c98f3SStanislav Mekhanoshin if (EleCount > 1) { 506aad93654SChristopher Tetreault IType = FixedVectorType::get(IType, EleCount); 5074c9c98f3SStanislav Mekhanoshin } 5084c9c98f3SStanislav Mekhanoshin Arg = new BitCastInst(Arg, IType, "PrintArgVect", Brnch); 5094c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg); 5104c9c98f3SStanislav Mekhanoshin } else { 5114c9c98f3SStanislav Mekhanoshin WhatToStore.push_back(Arg); 5124c9c98f3SStanislav Mekhanoshin } 513438315bfSStanislav Mekhanoshin for (unsigned I = 0, E = WhatToStore.size(); I != E; ++I) { 514438315bfSStanislav Mekhanoshin Value *TheBtCast = WhatToStore[I]; 5154c9c98f3SStanislav Mekhanoshin unsigned ArgSize = 5164c9c98f3SStanislav Mekhanoshin TD->getTypeAllocSizeInBits(TheBtCast->getType()) / 8; 5174c9c98f3SStanislav Mekhanoshin SmallVector<Value *, 1> BuffOffset; 5184c9c98f3SStanislav Mekhanoshin BuffOffset.push_back(ConstantInt::get(I32Ty, ArgSize)); 5194c9c98f3SStanislav Mekhanoshin 5204c9c98f3SStanislav Mekhanoshin Type *ArgPointer = PointerType::get(TheBtCast->getType(), 1); 5214c9c98f3SStanislav Mekhanoshin Value *CastedGEP = 5224c9c98f3SStanislav Mekhanoshin new BitCastInst(BufferIdx, ArgPointer, "PrintBuffPtrCast", Brnch); 5234c9c98f3SStanislav Mekhanoshin StoreInst *StBuff = new StoreInst(TheBtCast, CastedGEP, Brnch); 5244c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "inserting store to printf buffer:\n" 5254c9c98f3SStanislav Mekhanoshin << *StBuff << '\n'); 5264c9c98f3SStanislav Mekhanoshin (void)StBuff; 527438315bfSStanislav Mekhanoshin if (I + 1 == E && ArgCount + 1 == CI->getNumArgOperands()) 5284c9c98f3SStanislav Mekhanoshin break; 529cfb94212SNikita Popov BufferIdx = GetElementPtrInst::Create(I8Ty, BufferIdx, BuffOffset, 53097a23ab2SSimon Pilgrim "PrintBuffNextPtr", Brnch); 5314c9c98f3SStanislav Mekhanoshin LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:\n" 5324c9c98f3SStanislav Mekhanoshin << *BufferIdx << '\n'); 5334c9c98f3SStanislav Mekhanoshin } 5344c9c98f3SStanislav Mekhanoshin } 5354c9c98f3SStanislav Mekhanoshin } 5364c9c98f3SStanislav Mekhanoshin } 5374c9c98f3SStanislav Mekhanoshin 5384c9c98f3SStanislav Mekhanoshin // erase the printf calls 539dafda610SJay Foad for (auto CI : Printfs) 5404c9c98f3SStanislav Mekhanoshin CI->eraseFromParent(); 5414c9c98f3SStanislav Mekhanoshin 5424c9c98f3SStanislav Mekhanoshin Printfs.clear(); 5434c9c98f3SStanislav Mekhanoshin return true; 5444c9c98f3SStanislav Mekhanoshin } 5454c9c98f3SStanislav Mekhanoshin 546fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBindingImpl::run(Module &M) { 5474c9c98f3SStanislav Mekhanoshin Triple TT(M.getTargetTriple()); 5484c9c98f3SStanislav Mekhanoshin if (TT.getArch() == Triple::r600) 5494c9c98f3SStanislav Mekhanoshin return false; 5504c9c98f3SStanislav Mekhanoshin 551dafda610SJay Foad auto PrintfFunction = M.getFunction("printf"); 552dafda610SJay Foad if (!PrintfFunction) 553dafda610SJay Foad return false; 554dafda610SJay Foad 555dafda610SJay Foad for (auto &U : PrintfFunction->uses()) { 556dafda610SJay Foad if (auto *CI = dyn_cast<CallInst>(U.getUser())) { 557dafda610SJay Foad if (CI->isCallee(&U)) 558dafda610SJay Foad Printfs.push_back(CI); 559dafda610SJay Foad } 560dafda610SJay Foad } 5614c9c98f3SStanislav Mekhanoshin 5624c9c98f3SStanislav Mekhanoshin if (Printfs.empty()) 5634c9c98f3SStanislav Mekhanoshin return false; 5644c9c98f3SStanislav Mekhanoshin 56552c5014dSSameer Sahasrabuddhe if (auto HostcallFunction = M.getFunction("__ockl_hostcall_internal")) { 56652c5014dSSameer Sahasrabuddhe for (auto &U : HostcallFunction->uses()) { 56752c5014dSSameer Sahasrabuddhe if (auto *CI = dyn_cast<CallInst>(U.getUser())) { 56852c5014dSSameer Sahasrabuddhe M.getContext().emitError( 56952c5014dSSameer Sahasrabuddhe CI, "Cannot use both printf and hostcall in the same module"); 57052c5014dSSameer Sahasrabuddhe } 57152c5014dSSameer Sahasrabuddhe } 57252c5014dSSameer Sahasrabuddhe } 57352c5014dSSameer Sahasrabuddhe 5744c9c98f3SStanislav Mekhanoshin TD = &M.getDataLayout(); 575fd323a89SArthur Eubanks 576fd323a89SArthur Eubanks return lowerPrintfForGpu(M); 577fd323a89SArthur Eubanks } 578fd323a89SArthur Eubanks 579fd323a89SArthur Eubanks bool AMDGPUPrintfRuntimeBinding::runOnModule(Module &M) { 580fd323a89SArthur Eubanks auto GetDT = [this](Function &F) -> DominatorTree & { 581fd323a89SArthur Eubanks return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); 582fd323a89SArthur Eubanks }; 5839c27b59cSTeresa Johnson auto GetTLI = [this](Function &F) -> TargetLibraryInfo & { 5849c27b59cSTeresa Johnson return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 5859c27b59cSTeresa Johnson }; 5864c9c98f3SStanislav Mekhanoshin 587fd323a89SArthur Eubanks return AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M); 588fd323a89SArthur Eubanks } 589fd323a89SArthur Eubanks 590fd323a89SArthur Eubanks PreservedAnalyses 591fd323a89SArthur Eubanks AMDGPUPrintfRuntimeBindingPass::run(Module &M, ModuleAnalysisManager &AM) { 592fd323a89SArthur Eubanks FunctionAnalysisManager &FAM = 593fd323a89SArthur Eubanks AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 594fd323a89SArthur Eubanks auto GetDT = [&FAM](Function &F) -> DominatorTree & { 595fd323a89SArthur Eubanks return FAM.getResult<DominatorTreeAnalysis>(F); 596fd323a89SArthur Eubanks }; 597fd323a89SArthur Eubanks auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 598fd323a89SArthur Eubanks return FAM.getResult<TargetLibraryAnalysis>(F); 599fd323a89SArthur Eubanks }; 600fd323a89SArthur Eubanks bool Changed = AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M); 601fd323a89SArthur Eubanks return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); 6024c9c98f3SStanislav Mekhanoshin } 603