RuntimeDebugBuilder.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. //===--- RuntimeDebugBuilder.cpp - Helper to insert prints into LLVM-IR ---===//
  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. //
  9. //===----------------------------------------------------------------------===//
  10. #include "polly/CodeGen/RuntimeDebugBuilder.h"
  11. #include "llvm/IR/IntrinsicsNVPTX.h"
  12. #include "llvm/IR/Module.h"
  13. #include <string>
  14. #include <vector>
  15. using namespace llvm;
  16. using namespace polly;
  17. Function *RuntimeDebugBuilder::getVPrintF(PollyIRBuilder &Builder) {
  18. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  19. const char *Name = "vprintf";
  20. Function *F = M->getFunction(Name);
  21. if (!F) {
  22. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  23. FunctionType *Ty = FunctionType::get(
  24. Builder.getInt32Ty(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()},
  25. false);
  26. F = Function::Create(Ty, Linkage, Name, M);
  27. }
  28. return F;
  29. }
  30. Function *RuntimeDebugBuilder::getAddressSpaceCast(PollyIRBuilder &Builder,
  31. unsigned Src, unsigned Dst,
  32. unsigned SrcBits,
  33. unsigned DstBits) {
  34. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  35. auto Name = std::string("llvm.nvvm.ptr.constant.to.gen.p") +
  36. std::to_string(Dst) + "i" + std::to_string(DstBits) + ".p" +
  37. std::to_string(Src) + "i" + std::to_string(SrcBits);
  38. Function *F = M->getFunction(Name);
  39. if (!F) {
  40. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  41. FunctionType *Ty = FunctionType::get(
  42. PointerType::get(Builder.getIntNTy(DstBits), Dst),
  43. PointerType::get(Builder.getIntNTy(SrcBits), Src), false);
  44. F = Function::Create(Ty, Linkage, Name, M);
  45. }
  46. return F;
  47. }
  48. std::vector<Value *>
  49. RuntimeDebugBuilder::getGPUThreadIdentifiers(PollyIRBuilder &Builder) {
  50. std::vector<Value *> Identifiers;
  51. auto M = Builder.GetInsertBlock()->getParent()->getParent();
  52. std::vector<Function *> BlockIDs = {
  53. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_ctaid_x),
  54. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_ctaid_y),
  55. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_ctaid_z),
  56. };
  57. Identifiers.push_back(Builder.CreateGlobalStringPtr("> block-id: ", "", 4));
  58. for (auto GetID : BlockIDs) {
  59. Value *Id = Builder.CreateCall(GetID, {});
  60. Id = Builder.CreateIntCast(Id, Builder.getInt64Ty(), false);
  61. Identifiers.push_back(Id);
  62. Identifiers.push_back(Builder.CreateGlobalStringPtr(" ", "", 4));
  63. }
  64. Identifiers.push_back(Builder.CreateGlobalStringPtr("| ", "", 4));
  65. std::vector<Function *> ThreadIDs = {
  66. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_tid_x),
  67. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_tid_y),
  68. Intrinsic::getDeclaration(M, Intrinsic::nvvm_read_ptx_sreg_tid_z),
  69. };
  70. Identifiers.push_back(Builder.CreateGlobalStringPtr("thread-id: ", "", 4));
  71. for (auto GetId : ThreadIDs) {
  72. Value *Id = Builder.CreateCall(GetId, {});
  73. Id = Builder.CreateIntCast(Id, Builder.getInt64Ty(), false);
  74. Identifiers.push_back(Id);
  75. Identifiers.push_back(Builder.CreateGlobalStringPtr(" ", "", 4));
  76. }
  77. return Identifiers;
  78. }
  79. void RuntimeDebugBuilder::createPrinter(PollyIRBuilder &Builder, bool IsGPU,
  80. ArrayRef<Value *> Values) {
  81. if (IsGPU)
  82. createGPUPrinterT(Builder, Values);
  83. else
  84. createCPUPrinterT(Builder, Values);
  85. }
  86. bool RuntimeDebugBuilder::isPrintable(Type *Ty) {
  87. if (Ty->isFloatingPointTy())
  88. return true;
  89. if (Ty->isIntegerTy())
  90. return Ty->getIntegerBitWidth() <= 64;
  91. if (isa<PointerType>(Ty))
  92. return true;
  93. return false;
  94. }
  95. static std::tuple<std::string, std::vector<Value *>>
  96. prepareValuesForPrinting(PollyIRBuilder &Builder, ArrayRef<Value *> Values) {
  97. std::string FormatString;
  98. std::vector<Value *> ValuesToPrint;
  99. for (auto Val : Values) {
  100. Type *Ty = Val->getType();
  101. if (Ty->isFloatingPointTy()) {
  102. if (!Ty->isDoubleTy())
  103. Val = Builder.CreateFPExt(Val, Builder.getDoubleTy());
  104. } else if (Ty->isIntegerTy()) {
  105. if (Ty->getIntegerBitWidth() < 64)
  106. Val = Builder.CreateSExt(Val, Builder.getInt64Ty());
  107. else
  108. assert(Ty->getIntegerBitWidth() &&
  109. "Integer types larger 64 bit not supported");
  110. } else if (isa<PointerType>(Ty)) {
  111. if (Ty == Builder.getInt8PtrTy(4)) {
  112. Val = Builder.CreateGEP(Builder.getInt8Ty(), Val, Builder.getInt64(0));
  113. } else {
  114. Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty());
  115. }
  116. } else {
  117. llvm_unreachable("Unknown type");
  118. }
  119. Ty = Val->getType();
  120. if (Ty->isFloatingPointTy())
  121. FormatString += "%f";
  122. else if (Ty->isIntegerTy())
  123. FormatString += "%ld";
  124. else
  125. FormatString += "%s";
  126. ValuesToPrint.push_back(Val);
  127. }
  128. return std::make_tuple(FormatString, ValuesToPrint);
  129. }
  130. void RuntimeDebugBuilder::createCPUPrinterT(PollyIRBuilder &Builder,
  131. ArrayRef<Value *> Values) {
  132. std::string FormatString;
  133. std::vector<Value *> ValuesToPrint;
  134. std::tie(FormatString, ValuesToPrint) =
  135. prepareValuesForPrinting(Builder, Values);
  136. createPrintF(Builder, FormatString, ValuesToPrint);
  137. createFlush(Builder);
  138. }
  139. void RuntimeDebugBuilder::createGPUPrinterT(PollyIRBuilder &Builder,
  140. ArrayRef<Value *> Values) {
  141. std::string str;
  142. auto *Zero = Builder.getInt64(0);
  143. auto ToPrint = getGPUThreadIdentifiers(Builder);
  144. ToPrint.push_back(Builder.CreateGlobalStringPtr("\n ", "", 4));
  145. ToPrint.insert(ToPrint.end(), Values.begin(), Values.end());
  146. const DataLayout &DL = Builder.GetInsertBlock()->getModule()->getDataLayout();
  147. // Allocate print buffer (assuming 2*32 bit per element)
  148. auto T = ArrayType::get(Builder.getInt32Ty(), ToPrint.size() * 2);
  149. Value *Data = new AllocaInst(
  150. T, DL.getAllocaAddrSpace(), "polly.vprint.buffer",
  151. &Builder.GetInsertBlock()->getParent()->getEntryBlock().front());
  152. auto *DataPtr = Builder.CreateGEP(T, Data, {Zero, Zero});
  153. int Offset = 0;
  154. for (auto Val : ToPrint) {
  155. auto Ptr = Builder.CreateGEP(Builder.getInt32Ty(), DataPtr,
  156. Builder.getInt64(Offset));
  157. Type *Ty = Val->getType();
  158. if (Ty->isFloatingPointTy()) {
  159. if (!Ty->isDoubleTy())
  160. Val = Builder.CreateFPExt(Val, Builder.getDoubleTy());
  161. } else if (Ty->isIntegerTy()) {
  162. if (Ty->getIntegerBitWidth() < 64) {
  163. Val = Builder.CreateSExt(Val, Builder.getInt64Ty());
  164. } else {
  165. assert(Ty->getIntegerBitWidth() == 64 &&
  166. "Integer types larger 64 bit not supported");
  167. // fallthrough
  168. }
  169. } else if (isa<PointerType>(Ty)) {
  170. if (Ty == Builder.getInt8PtrTy(4)) {
  171. // Pointers in constant address space are printed as strings
  172. Val = Builder.CreateGEP(Builder.getInt8Ty(), Val, Builder.getInt64(0));
  173. auto F = RuntimeDebugBuilder::getAddressSpaceCast(Builder, 4, 0);
  174. Val = Builder.CreateCall(F, Val);
  175. } else {
  176. Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty());
  177. }
  178. } else {
  179. llvm_unreachable("Unknown type");
  180. }
  181. Ty = Val->getType();
  182. Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr, Ty->getPointerTo(5));
  183. Builder.CreateAlignedStore(Val, Ptr, Align(4));
  184. if (Ty->isFloatingPointTy())
  185. str += "%f";
  186. else if (Ty->isIntegerTy())
  187. str += "%ld";
  188. else
  189. str += "%s";
  190. Offset += 2;
  191. }
  192. Value *Format = Builder.CreateGlobalStringPtr(str, "polly.vprintf.buffer", 4);
  193. Format = Builder.CreateCall(getAddressSpaceCast(Builder, 4, 0), Format);
  194. Data = Builder.CreateBitCast(Data, Builder.getInt8PtrTy());
  195. Builder.CreateCall(getVPrintF(Builder), {Format, Data});
  196. }
  197. Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
  198. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  199. const char *Name = "printf";
  200. Function *F = M->getFunction(Name);
  201. if (!F) {
  202. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  203. FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true);
  204. F = Function::Create(Ty, Linkage, Name, M);
  205. }
  206. return F;
  207. }
  208. void RuntimeDebugBuilder::createPrintF(PollyIRBuilder &Builder,
  209. std::string Format,
  210. ArrayRef<Value *> Values) {
  211. Value *FormatString = Builder.CreateGlobalStringPtr(Format);
  212. std::vector<Value *> Arguments;
  213. Arguments.push_back(FormatString);
  214. Arguments.insert(Arguments.end(), Values.begin(), Values.end());
  215. Builder.CreateCall(getPrintF(Builder), Arguments);
  216. }
  217. void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
  218. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  219. const char *Name = "fflush";
  220. Function *F = M->getFunction(Name);
  221. if (!F) {
  222. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  223. FunctionType *Ty =
  224. FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), false);
  225. F = Function::Create(Ty, Linkage, Name, M);
  226. }
  227. // fflush(NULL) flushes _all_ open output streams.
  228. //
  229. // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
  230. // pointer, the type we point to does conceptually not matter. However, if
  231. // fflush is already declared in this translation unit, we use the very same
  232. // type to ensure that LLVM does not complain about mismatching types.
  233. Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
  234. }