RuntimeDebugBuilder.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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->getPointerElementType() == Builder.getInt8Ty() &&
  112. Ty->getPointerAddressSpace() == 4) {
  113. Val = Builder.CreateGEP(Builder.getInt8Ty(), Val, Builder.getInt64(0));
  114. } else {
  115. Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty());
  116. }
  117. } else {
  118. llvm_unreachable("Unknown type");
  119. }
  120. Ty = Val->getType();
  121. if (Ty->isFloatingPointTy())
  122. FormatString += "%f";
  123. else if (Ty->isIntegerTy())
  124. FormatString += "%ld";
  125. else
  126. FormatString += "%s";
  127. ValuesToPrint.push_back(Val);
  128. }
  129. return std::make_tuple(FormatString, ValuesToPrint);
  130. }
  131. void RuntimeDebugBuilder::createCPUPrinterT(PollyIRBuilder &Builder,
  132. ArrayRef<Value *> Values) {
  133. std::string FormatString;
  134. std::vector<Value *> ValuesToPrint;
  135. std::tie(FormatString, ValuesToPrint) =
  136. prepareValuesForPrinting(Builder, Values);
  137. createPrintF(Builder, FormatString, ValuesToPrint);
  138. createFlush(Builder);
  139. }
  140. void RuntimeDebugBuilder::createGPUPrinterT(PollyIRBuilder &Builder,
  141. ArrayRef<Value *> Values) {
  142. std::string str;
  143. auto *Zero = Builder.getInt64(0);
  144. auto ToPrint = getGPUThreadIdentifiers(Builder);
  145. ToPrint.push_back(Builder.CreateGlobalStringPtr("\n ", "", 4));
  146. ToPrint.insert(ToPrint.end(), Values.begin(), Values.end());
  147. const DataLayout &DL = Builder.GetInsertBlock()->getModule()->getDataLayout();
  148. // Allocate print buffer (assuming 2*32 bit per element)
  149. auto T = ArrayType::get(Builder.getInt32Ty(), ToPrint.size() * 2);
  150. Value *Data = new AllocaInst(
  151. T, DL.getAllocaAddrSpace(), "polly.vprint.buffer",
  152. &Builder.GetInsertBlock()->getParent()->getEntryBlock().front());
  153. auto *DataPtr = Builder.CreateGEP(T, Data, {Zero, Zero});
  154. int Offset = 0;
  155. for (auto Val : ToPrint) {
  156. auto Ptr = Builder.CreateGEP(Builder.getInt32Ty(), DataPtr,
  157. Builder.getInt64(Offset));
  158. Type *Ty = Val->getType();
  159. if (Ty->isFloatingPointTy()) {
  160. if (!Ty->isDoubleTy())
  161. Val = Builder.CreateFPExt(Val, Builder.getDoubleTy());
  162. } else if (Ty->isIntegerTy()) {
  163. if (Ty->getIntegerBitWidth() < 64) {
  164. Val = Builder.CreateSExt(Val, Builder.getInt64Ty());
  165. } else {
  166. assert(Ty->getIntegerBitWidth() == 64 &&
  167. "Integer types larger 64 bit not supported");
  168. // fallthrough
  169. }
  170. } else if (auto PtTy = dyn_cast<PointerType>(Ty)) {
  171. if (PtTy->getAddressSpace() == 4) {
  172. // Pointers in constant address space are printed as strings
  173. Val = Builder.CreateGEP(Ty->getPointerElementType(), Val,
  174. Builder.getInt64(0));
  175. auto F = RuntimeDebugBuilder::getAddressSpaceCast(Builder, 4, 0);
  176. Val = Builder.CreateCall(F, Val);
  177. } else {
  178. Val = Builder.CreatePtrToInt(Val, Builder.getInt64Ty());
  179. }
  180. } else {
  181. llvm_unreachable("Unknown type");
  182. }
  183. Ty = Val->getType();
  184. Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr, Ty->getPointerTo(5));
  185. Builder.CreateAlignedStore(Val, Ptr, Align(4));
  186. if (Ty->isFloatingPointTy())
  187. str += "%f";
  188. else if (Ty->isIntegerTy())
  189. str += "%ld";
  190. else
  191. str += "%s";
  192. Offset += 2;
  193. }
  194. Value *Format = Builder.CreateGlobalStringPtr(str, "polly.vprintf.buffer", 4);
  195. Format = Builder.CreateCall(getAddressSpaceCast(Builder, 4, 0), Format);
  196. Data = Builder.CreateBitCast(Data, Builder.getInt8PtrTy());
  197. Builder.CreateCall(getVPrintF(Builder), {Format, Data});
  198. }
  199. Function *RuntimeDebugBuilder::getPrintF(PollyIRBuilder &Builder) {
  200. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  201. const char *Name = "printf";
  202. Function *F = M->getFunction(Name);
  203. if (!F) {
  204. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  205. FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true);
  206. F = Function::Create(Ty, Linkage, Name, M);
  207. }
  208. return F;
  209. }
  210. void RuntimeDebugBuilder::createPrintF(PollyIRBuilder &Builder,
  211. std::string Format,
  212. ArrayRef<Value *> Values) {
  213. Value *FormatString = Builder.CreateGlobalStringPtr(Format);
  214. std::vector<Value *> Arguments;
  215. Arguments.push_back(FormatString);
  216. Arguments.insert(Arguments.end(), Values.begin(), Values.end());
  217. Builder.CreateCall(getPrintF(Builder), Arguments);
  218. }
  219. void RuntimeDebugBuilder::createFlush(PollyIRBuilder &Builder) {
  220. Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  221. const char *Name = "fflush";
  222. Function *F = M->getFunction(Name);
  223. if (!F) {
  224. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  225. FunctionType *Ty =
  226. FunctionType::get(Builder.getInt32Ty(), Builder.getInt8PtrTy(), false);
  227. F = Function::Create(Ty, Linkage, Name, M);
  228. }
  229. // fflush(NULL) flushes _all_ open output streams.
  230. //
  231. // fflush is declared as 'int fflush(FILE *stream)'. As we only pass on a NULL
  232. // pointer, the type we point to does conceptually not matter. However, if
  233. // fflush is already declared in this translation unit, we use the very same
  234. // type to ensure that LLVM does not complain about mismatching types.
  235. Builder.CreateCall(F, Constant::getNullValue(F->arg_begin()->getType()));
  236. }