xref: /llvm-project/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp (revision 68b6cabd9e5511d22ba6f0a4102705dbc85d150f)
1 //=== AMDGPUPrintfRuntimeBinding.cpp - OpenCL printf implementation -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // \file
9 //
10 // The pass bind printfs to a kernel arg pointer that will be bound to a buffer
11 // later by the runtime.
12 //
13 // This pass traverses the functions in the module and converts
14 // each call to printf to a sequence of operations that
15 // store the following into the printf buffer:
16 // - format string (passed as a module's metadata unique ID)
17 // - bitwise copies of printf arguments
18 // The backend passes will need to store metadata in the kernel
19 //===----------------------------------------------------------------------===//
20 
21 #include "AMDGPU.h"
22 #include "llvm/ADT/Triple.h"
23 #include "llvm/Analysis/InstructionSimplify.h"
24 #include "llvm/Analysis/TargetLibraryInfo.h"
25 #include "llvm/IR/DiagnosticInfo.h"
26 #include "llvm/IR/Dominators.h"
27 #include "llvm/IR/IRBuilder.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/InitializePasses.h"
30 #include "llvm/Support/BinaryByteStream.h"
31 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
32 
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "printfToRuntime"
36 #define DWORD_ALIGN 4
37 
38 namespace {
39 class AMDGPUPrintfRuntimeBinding final : public ModulePass {
40 
41 public:
42   static char ID;
43 
44   explicit AMDGPUPrintfRuntimeBinding();
45 
46 private:
47   bool runOnModule(Module &M) override;
48 
49   void getAnalysisUsage(AnalysisUsage &AU) const override {
50     AU.addRequired<TargetLibraryInfoWrapperPass>();
51     AU.addRequired<DominatorTreeWrapperPass>();
52   }
53 };
54 
55 class AMDGPUPrintfRuntimeBindingImpl {
56 public:
57   AMDGPUPrintfRuntimeBindingImpl(
58       function_ref<const DominatorTree &(Function &)> GetDT,
59       function_ref<const TargetLibraryInfo &(Function &)> GetTLI)
60       : GetDT(GetDT), GetTLI(GetTLI) {}
61   bool run(Module &M);
62 
63 private:
64   void getConversionSpecifiers(SmallVectorImpl<char> &OpConvSpecifiers,
65                                StringRef fmt, size_t num_ops) const;
66 
67   bool lowerPrintfForGpu(Module &M);
68 
69   Value *simplify(Instruction *I, const TargetLibraryInfo *TLI,
70                   const DominatorTree *DT) {
71     return simplifyInstruction(I, {*TD, TLI, DT});
72   }
73 
74   const DataLayout *TD;
75   function_ref<const DominatorTree &(Function &)> GetDT;
76   function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
77   SmallVector<CallInst *, 32> Printfs;
78 };
79 } // namespace
80 
81 char AMDGPUPrintfRuntimeBinding::ID = 0;
82 
83 INITIALIZE_PASS_BEGIN(AMDGPUPrintfRuntimeBinding,
84                       "amdgpu-printf-runtime-binding", "AMDGPU Printf lowering",
85                       false, false)
86 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
87 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
88 INITIALIZE_PASS_END(AMDGPUPrintfRuntimeBinding, "amdgpu-printf-runtime-binding",
89                     "AMDGPU Printf lowering", false, false)
90 
91 char &llvm::AMDGPUPrintfRuntimeBindingID = AMDGPUPrintfRuntimeBinding::ID;
92 
93 namespace llvm {
94 ModulePass *createAMDGPUPrintfRuntimeBinding() {
95   return new AMDGPUPrintfRuntimeBinding();
96 }
97 } // namespace llvm
98 
99 AMDGPUPrintfRuntimeBinding::AMDGPUPrintfRuntimeBinding() : ModulePass(ID) {
100   initializeAMDGPUPrintfRuntimeBindingPass(*PassRegistry::getPassRegistry());
101 }
102 
103 void AMDGPUPrintfRuntimeBindingImpl::getConversionSpecifiers(
104     SmallVectorImpl<char> &OpConvSpecifiers, StringRef Fmt,
105     size_t NumOps) const {
106   // not all format characters are collected.
107   // At this time the format characters of interest
108   // are %p and %s, which use to know if we
109   // are either storing a literal string or a
110   // pointer to the printf buffer.
111   static const char ConvSpecifiers[] = "cdieEfgGaosuxXp";
112   size_t CurFmtSpecifierIdx = 0;
113   size_t PrevFmtSpecifierIdx = 0;
114 
115   while ((CurFmtSpecifierIdx = Fmt.find_first_of(
116               ConvSpecifiers, CurFmtSpecifierIdx)) != StringRef::npos) {
117     bool ArgDump = false;
118     StringRef CurFmt = Fmt.substr(PrevFmtSpecifierIdx,
119                                   CurFmtSpecifierIdx - PrevFmtSpecifierIdx);
120     size_t pTag = CurFmt.find_last_of("%");
121     if (pTag != StringRef::npos) {
122       ArgDump = true;
123       while (pTag && CurFmt[--pTag] == '%') {
124         ArgDump = !ArgDump;
125       }
126     }
127 
128     if (ArgDump)
129       OpConvSpecifiers.push_back(Fmt[CurFmtSpecifierIdx]);
130 
131     PrevFmtSpecifierIdx = ++CurFmtSpecifierIdx;
132   }
133 }
134 
135 static bool shouldPrintAsStr(char Specifier, Type *OpType) {
136   return Specifier == 's' && isa<PointerType>(OpType);
137 }
138 
139 static void diagnoseInvalidFormatString(const CallBase *CI) {
140   DiagnosticInfoUnsupported UnsupportedFormatStr(
141       *CI->getParent()->getParent(),
142       "printf format string must be a trivially resolved constant string "
143       "global variable",
144       CI->getDebugLoc());
145   CI->getContext().diagnose(UnsupportedFormatStr);
146 }
147 
148 bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) {
149   LLVMContext &Ctx = M.getContext();
150   IRBuilder<> Builder(Ctx);
151   Type *I32Ty = Type::getInt32Ty(Ctx);
152   unsigned UniqID = 0;
153   constexpr StringLiteral NonLiteralStr("???");
154   static_assert(NonLiteralStr.size() == 3);
155 
156   for (auto *CI : Printfs) {
157     unsigned NumOps = CI->arg_size();
158 
159     SmallString<16> OpConvSpecifiers;
160     Value *Op = CI->getArgOperand(0);
161 
162     if (auto LI = dyn_cast<LoadInst>(Op)) {
163       Op = LI->getPointerOperand();
164       for (auto *Use : Op->users()) {
165         if (auto SI = dyn_cast<StoreInst>(Use)) {
166           Op = SI->getValueOperand();
167           break;
168         }
169       }
170     }
171 
172     if (auto I = dyn_cast<Instruction>(Op)) {
173       Value *Op_simplified =
174           simplify(I, &GetTLI(*I->getFunction()), &GetDT(*I->getFunction()));
175       if (Op_simplified)
176         Op = Op_simplified;
177     }
178 
179     Value *Stripped = Op->stripPointerCasts();
180     if (isa<UndefValue>(Stripped) || isa<ConstantPointerNull>(Stripped))
181       continue;
182 
183     GlobalVariable *GVar = dyn_cast<GlobalVariable>(Stripped);
184     if (!GVar || !GVar->hasDefinitiveInitializer() || !GVar->isConstant()) {
185       diagnoseInvalidFormatString(CI);
186       continue;
187     }
188 
189     auto *Init = GVar->getInitializer();
190     if (isa<UndefValue>(Init) || isa<ConstantAggregateZero>(Init))
191       continue;
192 
193     auto *CA = dyn_cast<ConstantDataArray>(Init);
194     if (!CA || !CA->isString()) {
195       diagnoseInvalidFormatString(CI);
196       continue;
197     }
198 
199     StringRef Str(CA->getAsCString());
200 
201     // We need this call to ascertain that we are printing a string or a
202     // pointer. It takes out the specifiers and fills up the first arg.
203     getConversionSpecifiers(OpConvSpecifiers, Str, NumOps - 1);
204 
205     // Add metadata for the string
206     std::string AStreamHolder;
207     raw_string_ostream Sizes(AStreamHolder);
208     int Sum = DWORD_ALIGN;
209     Sizes << CI->arg_size() - 1;
210     Sizes << ':';
211     for (unsigned ArgCount = 1;
212          ArgCount < CI->arg_size() && ArgCount <= OpConvSpecifiers.size();
213          ArgCount++) {
214       Value *Arg = CI->getArgOperand(ArgCount);
215       Type *ArgType = Arg->getType();
216       unsigned ArgSize = TD->getTypeAllocSize(ArgType);
217       //
218       // ArgSize by design should be a multiple of DWORD_ALIGN,
219       // expand the arguments that do not follow this rule.
220       //
221       if (ArgSize % DWORD_ALIGN != 0) {
222         llvm::Type *ResType = llvm::Type::getInt32Ty(Ctx);
223         auto *LLVMVecType = llvm::dyn_cast<llvm::FixedVectorType>(ArgType);
224         int NumElem = LLVMVecType ? LLVMVecType->getNumElements() : 1;
225         if (LLVMVecType && NumElem > 1)
226           ResType = llvm::FixedVectorType::get(ResType, NumElem);
227         Builder.SetInsertPoint(CI);
228         Builder.SetCurrentDebugLocation(CI->getDebugLoc());
229         if (OpConvSpecifiers[ArgCount - 1] == 'x' ||
230             OpConvSpecifiers[ArgCount - 1] == 'X' ||
231             OpConvSpecifiers[ArgCount - 1] == 'u' ||
232             OpConvSpecifiers[ArgCount - 1] == 'o')
233           Arg = Builder.CreateZExt(Arg, ResType);
234         else
235           Arg = Builder.CreateSExt(Arg, ResType);
236         ArgType = Arg->getType();
237         ArgSize = TD->getTypeAllocSize(ArgType);
238         CI->setOperand(ArgCount, Arg);
239       }
240       if (OpConvSpecifiers[ArgCount - 1] == 'f') {
241         ConstantFP *FpCons = dyn_cast<ConstantFP>(Arg);
242         if (FpCons)
243           ArgSize = 4;
244         else {
245           FPExtInst *FpExt = dyn_cast<FPExtInst>(Arg);
246           if (FpExt && FpExt->getType()->isDoubleTy() &&
247               FpExt->getOperand(0)->getType()->isFloatTy())
248             ArgSize = 4;
249         }
250       }
251       if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) {
252         ArgSize = NonLiteralStr.size() + 1;
253         if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) {
254           auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
255           if (GV && GV->hasInitializer()) {
256             Constant *Init = GV->getInitializer();
257             bool IsZeroValue = Init->isZeroValue();
258             auto *CA = dyn_cast<ConstantDataArray>(Init);
259             if (IsZeroValue || (CA && CA->isString())) {
260               size_t SizeStr =
261                   IsZeroValue ? 1 : (strlen(CA->getAsCString().data()) + 1);
262               size_t Rem = SizeStr % DWORD_ALIGN;
263               size_t NSizeStr = 0;
264               LLVM_DEBUG(dbgs() << "Printf string original size = " << SizeStr
265                                 << '\n');
266               if (Rem) {
267                 NSizeStr = SizeStr + (DWORD_ALIGN - Rem);
268               } else {
269                 NSizeStr = SizeStr;
270               }
271               ArgSize = NSizeStr;
272             }
273           }
274         }
275       }
276       LLVM_DEBUG(dbgs() << "Printf ArgSize (in buffer) = " << ArgSize
277                         << " for type: " << *ArgType << '\n');
278       Sizes << ArgSize << ':';
279       Sum += ArgSize;
280     }
281     LLVM_DEBUG(dbgs() << "Printf format string in source = " << Str.str()
282                       << '\n');
283     for (char C : Str) {
284       // Rest of the C escape sequences (e.g. \') are handled correctly
285       // by the MDParser
286       switch (C) {
287       case '\a':
288         Sizes << "\\a";
289         break;
290       case '\b':
291         Sizes << "\\b";
292         break;
293       case '\f':
294         Sizes << "\\f";
295         break;
296       case '\n':
297         Sizes << "\\n";
298         break;
299       case '\r':
300         Sizes << "\\r";
301         break;
302       case '\v':
303         Sizes << "\\v";
304         break;
305       case ':':
306         // ':' cannot be scanned by Flex, as it is defined as a delimiter
307         // Replace it with it's octal representation \72
308         Sizes << "\\72";
309         break;
310       default:
311         Sizes << C;
312         break;
313       }
314     }
315 
316     // Insert the printf_alloc call
317     Builder.SetInsertPoint(CI);
318     Builder.SetCurrentDebugLocation(CI->getDebugLoc());
319 
320     AttributeList Attr = AttributeList::get(Ctx, AttributeList::FunctionIndex,
321                                             Attribute::NoUnwind);
322 
323     Type *SizetTy = Type::getInt32Ty(Ctx);
324 
325     Type *Tys_alloc[1] = {SizetTy};
326     Type *I8Ty = Type::getInt8Ty(Ctx);
327     Type *I8Ptr = PointerType::get(I8Ty, 1);
328     FunctionType *FTy_alloc = FunctionType::get(I8Ptr, Tys_alloc, false);
329     FunctionCallee PrintfAllocFn =
330         M.getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr);
331 
332     LLVM_DEBUG(dbgs() << "Printf metadata = " << Sizes.str() << '\n');
333     std::string fmtstr = itostr(++UniqID) + ":" + Sizes.str();
334     MDString *fmtStrArray = MDString::get(Ctx, fmtstr);
335 
336     // Instead of creating global variables, the
337     // printf format strings are extracted
338     // and passed as metadata. This avoids
339     // polluting llvm's symbol tables in this module.
340     // Metadata is going to be extracted
341     // by the backend passes and inserted
342     // into the OpenCL binary as appropriate.
343     StringRef amd("llvm.printf.fmts");
344     NamedMDNode *metaD = M.getOrInsertNamedMetadata(amd);
345     MDNode *myMD = MDNode::get(Ctx, fmtStrArray);
346     metaD->addOperand(myMD);
347     Value *sumC = ConstantInt::get(SizetTy, Sum, false);
348     SmallVector<Value *, 1> alloc_args;
349     alloc_args.push_back(sumC);
350     CallInst *pcall =
351         CallInst::Create(PrintfAllocFn, alloc_args, "printf_alloc_fn", CI);
352 
353     //
354     // Insert code to split basicblock with a
355     // piece of hammock code.
356     // basicblock splits after buffer overflow check
357     //
358     ConstantPointerNull *zeroIntPtr =
359         ConstantPointerNull::get(PointerType::get(I8Ty, 1));
360     auto *cmp = cast<ICmpInst>(Builder.CreateICmpNE(pcall, zeroIntPtr, ""));
361     if (!CI->use_empty()) {
362       Value *result =
363           Builder.CreateSExt(Builder.CreateNot(cmp), I32Ty, "printf_res");
364       CI->replaceAllUsesWith(result);
365     }
366     SplitBlock(CI->getParent(), cmp);
367     Instruction *Brnch =
368         SplitBlockAndInsertIfThen(cmp, cmp->getNextNode(), false);
369 
370     Builder.SetInsertPoint(Brnch);
371 
372     // store unique printf id in the buffer
373     //
374     GetElementPtrInst *BufferIdx = GetElementPtrInst::Create(
375         I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 0)), "PrintBuffID", Brnch);
376 
377     Type *idPointer = PointerType::get(I32Ty, AMDGPUAS::GLOBAL_ADDRESS);
378     Value *id_gep_cast =
379         new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", Brnch);
380 
381     new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast, Brnch);
382 
383     // 1st 4 bytes hold the printf_id
384     // the following GEP is the buffer pointer
385     BufferIdx = GetElementPtrInst::Create(I8Ty, pcall,
386                                           ConstantInt::get(Ctx, APInt(32, 4)),
387                                           "PrintBuffGep", Brnch);
388 
389     Type *Int32Ty = Type::getInt32Ty(Ctx);
390     Type *Int64Ty = Type::getInt64Ty(Ctx);
391     for (unsigned ArgCount = 1;
392          ArgCount < CI->arg_size() && ArgCount <= OpConvSpecifiers.size();
393          ArgCount++) {
394       Value *Arg = CI->getArgOperand(ArgCount);
395       Type *ArgType = Arg->getType();
396       SmallVector<Value *, 32> WhatToStore;
397       if (ArgType->isFPOrFPVectorTy() && !isa<VectorType>(ArgType)) {
398         Type *IType = (ArgType->isFloatTy()) ? Int32Ty : Int64Ty;
399         if (OpConvSpecifiers[ArgCount - 1] == 'f') {
400           if (auto *FpCons = dyn_cast<ConstantFP>(Arg)) {
401             APFloat Val(FpCons->getValueAPF());
402             bool Lost = false;
403             Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
404                         &Lost);
405             Arg = ConstantFP::get(Ctx, Val);
406             IType = Int32Ty;
407           } else if (auto *FpExt = dyn_cast<FPExtInst>(Arg)) {
408             if (FpExt->getType()->isDoubleTy() &&
409                 FpExt->getOperand(0)->getType()->isFloatTy()) {
410               Arg = FpExt->getOperand(0);
411               IType = Int32Ty;
412             }
413           }
414         }
415         Arg = new BitCastInst(Arg, IType, "PrintArgFP", Brnch);
416         WhatToStore.push_back(Arg);
417       } else if (ArgType->getTypeID() == Type::PointerTyID) {
418         if (shouldPrintAsStr(OpConvSpecifiers[ArgCount - 1], ArgType)) {
419           StringRef S = NonLiteralStr;
420           if (auto *ConstExpr = dyn_cast<ConstantExpr>(Arg)) {
421             auto *GV = dyn_cast<GlobalVariable>(ConstExpr->getOperand(0));
422             if (GV && GV->hasInitializer()) {
423               Constant *Init = GV->getInitializer();
424               bool IsZeroValue = Init->isZeroValue();
425               auto *CA = dyn_cast<ConstantDataArray>(Init);
426               if (IsZeroValue || (CA && CA->isString())) {
427                 S = IsZeroValue ? "" : CA->getAsCString();
428               }
429             }
430           }
431 
432           if (!S.empty()) {
433             const size_t NSizeStr = S.size() + 1;
434             const uint64_t ReadSize = 4;
435 
436             BinaryByteStream Streamer(S, support::little);
437 
438             for (uint64_t Offset = 0; Offset < NSizeStr; Offset += ReadSize) {
439               ArrayRef<uint8_t> ReadBytes;
440               if (Error Err = Streamer.readBytes(
441                       Offset, std::min(ReadSize, S.size() - Offset), ReadBytes))
442                 cantFail(std::move(Err),
443                          "failed to read bytes from constant array");
444 
445               APInt IntVal(8 * ReadBytes.size(), 0);
446               LoadIntFromMemory(IntVal, ReadBytes.data(), ReadBytes.size());
447 
448               // TODO: Should not bothering aligning up.
449               if (ReadBytes.size() < ReadSize)
450                 IntVal = IntVal.zext(8 * ReadSize);
451 
452               Type *IntTy = Type::getIntNTy(Ctx, IntVal.getBitWidth());
453               WhatToStore.push_back(ConstantInt::get(IntTy, IntVal));
454             }
455           } else {
456             // Empty string, give a hint to RT it is no NULL
457             Value *ANumV = ConstantInt::get(Int32Ty, 0xFFFFFF00, false);
458             WhatToStore.push_back(ANumV);
459           }
460         } else {
461           uint64_t Size = TD->getTypeAllocSizeInBits(ArgType);
462           assert((Size == 32 || Size == 64) && "unsupported size");
463           Type *DstType = (Size == 32) ? Int32Ty : Int64Ty;
464           Arg = new PtrToIntInst(Arg, DstType, "PrintArgPtr", Brnch);
465           WhatToStore.push_back(Arg);
466         }
467       } else if (isa<FixedVectorType>(ArgType)) {
468         Type *IType = nullptr;
469         uint32_t EleCount = cast<FixedVectorType>(ArgType)->getNumElements();
470         uint32_t EleSize = ArgType->getScalarSizeInBits();
471         uint32_t TotalSize = EleCount * EleSize;
472         if (EleCount == 3) {
473           ShuffleVectorInst *Shuffle =
474               new ShuffleVectorInst(Arg, Arg, ArrayRef<int>{0, 1, 2, 2});
475           Shuffle->insertBefore(Brnch);
476           Arg = Shuffle;
477           ArgType = Arg->getType();
478           TotalSize += EleSize;
479         }
480         switch (EleSize) {
481         default:
482           EleCount = TotalSize / 64;
483           IType = Type::getInt64Ty(ArgType->getContext());
484           break;
485         case 8:
486           if (EleCount >= 8) {
487             EleCount = TotalSize / 64;
488             IType = Type::getInt64Ty(ArgType->getContext());
489           } else if (EleCount >= 3) {
490             EleCount = 1;
491             IType = Type::getInt32Ty(ArgType->getContext());
492           } else {
493             EleCount = 1;
494             IType = Type::getInt16Ty(ArgType->getContext());
495           }
496           break;
497         case 16:
498           if (EleCount >= 3) {
499             EleCount = TotalSize / 64;
500             IType = Type::getInt64Ty(ArgType->getContext());
501           } else {
502             EleCount = 1;
503             IType = Type::getInt32Ty(ArgType->getContext());
504           }
505           break;
506         }
507         if (EleCount > 1) {
508           IType = FixedVectorType::get(IType, EleCount);
509         }
510         Arg = new BitCastInst(Arg, IType, "PrintArgVect", Brnch);
511         WhatToStore.push_back(Arg);
512       } else {
513         WhatToStore.push_back(Arg);
514       }
515       for (unsigned I = 0, E = WhatToStore.size(); I != E; ++I) {
516         Value *TheBtCast = WhatToStore[I];
517         unsigned ArgSize = TD->getTypeAllocSize(TheBtCast->getType());
518         SmallVector<Value *, 1> BuffOffset;
519         BuffOffset.push_back(ConstantInt::get(I32Ty, ArgSize));
520 
521         Type *ArgPointer = PointerType::get(TheBtCast->getType(), 1);
522         Value *CastedGEP =
523             new BitCastInst(BufferIdx, ArgPointer, "PrintBuffPtrCast", Brnch);
524         StoreInst *StBuff = new StoreInst(TheBtCast, CastedGEP, Brnch);
525         LLVM_DEBUG(dbgs() << "inserting store to printf buffer:\n"
526                           << *StBuff << '\n');
527         (void)StBuff;
528         if (I + 1 == E && ArgCount + 1 == CI->arg_size())
529           break;
530         BufferIdx = GetElementPtrInst::Create(I8Ty, BufferIdx, BuffOffset,
531                                               "PrintBuffNextPtr", Brnch);
532         LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:\n"
533                           << *BufferIdx << '\n');
534       }
535     }
536   }
537 
538   // erase the printf calls
539   for (auto *CI : Printfs)
540     CI->eraseFromParent();
541 
542   Printfs.clear();
543   return true;
544 }
545 
546 bool AMDGPUPrintfRuntimeBindingImpl::run(Module &M) {
547   Triple TT(M.getTargetTriple());
548   if (TT.getArch() == Triple::r600)
549     return false;
550 
551   auto PrintfFunction = M.getFunction("printf");
552   if (!PrintfFunction)
553     return false;
554 
555   for (auto &U : PrintfFunction->uses()) {
556     if (auto *CI = dyn_cast<CallInst>(U.getUser())) {
557       if (CI->isCallee(&U))
558         Printfs.push_back(CI);
559     }
560   }
561 
562   if (Printfs.empty())
563     return false;
564 
565   TD = &M.getDataLayout();
566 
567   return lowerPrintfForGpu(M);
568 }
569 
570 bool AMDGPUPrintfRuntimeBinding::runOnModule(Module &M) {
571   auto GetDT = [this](Function &F) -> DominatorTree & {
572     return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
573   };
574   auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
575     return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
576   };
577 
578   return AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M);
579 }
580 
581 PreservedAnalyses
582 AMDGPUPrintfRuntimeBindingPass::run(Module &M, ModuleAnalysisManager &AM) {
583   FunctionAnalysisManager &FAM =
584       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
585   auto GetDT = [&FAM](Function &F) -> DominatorTree & {
586     return FAM.getResult<DominatorTreeAnalysis>(F);
587   };
588   auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
589     return FAM.getResult<TargetLibraryAnalysis>(F);
590   };
591   bool Changed = AMDGPUPrintfRuntimeBindingImpl(GetDT, GetTLI).run(M);
592   return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
593 }
594