blob: c40b53c1b54d825e0afddb1d2d1d61e6af9c8310 [file] [log] [blame]
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001//===--- RuntimeDebugBuilder.h --- 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
11#ifndef RUNTIME_DEBUG_BUILDER_H
12#define RUNTIME_DEBUG_BUILDER_H
13
14#include "polly/CodeGen/IRBuilder.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/StringRef.h"
17#include <vector>
18
19namespace llvm {
20class Value;
21class Function;
22} // namespace llvm
23
24namespace polly {
25
26/// Insert function calls that print certain LLVM values at run time.
27///
28/// This class inserts libc function calls to print certain LLVM values at
29/// run time.
30struct RuntimeDebugBuilder {
31
32 /// Generate a constant string into the builder's llvm::Module which can be
33 /// passed to createGPUPrinter() or createGPUPrinter().
34 ///
35 /// @param Builder The builder used to emit the printer calls.
36 /// @param Str The string to be printed.
37
38 /// @return A global containing @p Str.
39 static llvm::Value *getPrintableString(PollyIRBuilder &Builder,
40 llvm::StringRef Str) {
41 // TODO: Get rid of magic number 4. It it NVPTX's constant address space and
42 // works on X86 (CPU) only because its backend ignores the address space.
43 return Builder.CreateGlobalStringPtr(Str, "", 4);
44 }
45
46 /// Return whether an llvm::Value of the type @p Ty is printable for
47 /// debugging.
48 ///
49 /// That is, whether such a value can be passed to createGPUPrinter() or
50 /// createGPUPrinter() to be dumped as runtime. If false is returned, those
51 /// functions will fail.
52 static bool isPrintable(llvm::Type *Ty);
53
54 /// Print a set of LLVM-IR Values or StringRefs via printf
55 ///
56 /// This function emits a call to printf that will print the given arguments.
57 /// It is useful for debugging CPU programs. All arguments given in this list
58 /// will be automatically concatenated and the resulting string will be
59 /// printed atomically. We also support ArrayRef arguments, which can be used
60 /// to provide of id values.
61 ///
62 /// @param Builder The builder used to emit the printer calls.
63 /// @param Args The list of values to print.
64 template <typename... Args>
65 static void createCPUPrinter(PollyIRBuilder &Builder, Args... args) {
66 std::vector<llvm::Value *> Vector;
67 createPrinter(Builder, /* CPU */ false, Vector, args...);
68 }
69
70 /// Print a set of LLVM-IR Values or StringRefs on an NVIDIA GPU.
71 ///
72 /// This function emits a call to vprintf that will print the given
73 /// arguments from within a kernel thread. It is useful for debugging
74 /// CUDA program kernels. All arguments given in this list will be
75 /// automatically concatenated and the resulting string will be printed
76 /// atomically. We also support ArrayRef arguments, which can be used to
77 /// provide for example a list of thread-id values.
78 ///
79 /// @param Builder The builder used to emit the printer calls.
80 /// @param Args The list of values to print.
81 template <typename... Args>
82 static void createGPUPrinter(PollyIRBuilder &Builder, Args... args) {
83 std::vector<llvm::Value *> Vector;
84 createPrinter(Builder, /* GPU */ true, Vector, args...);
85 }
86
87private:
88 /// Handle Values.
89 template <typename... Args>
90 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
91 std::vector<llvm::Value *> &Values,
92 llvm::Value *Value, Args... args) {
93 Values.push_back(Value);
94 createPrinter(Builder, UseGPU, Values, args...);
95 }
96
97 /// Handle StringRefs.
98 template <typename... Args>
99 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
100 std::vector<llvm::Value *> &Values,
101 llvm::StringRef String, Args... args) {
102 Values.push_back(getPrintableString(Builder, String));
103 createPrinter(Builder, UseGPU, Values, args...);
104 }
105
106 /// Handle ArrayRefs.
107 template <typename... Args>
108 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
109 std::vector<llvm::Value *> &Values,
110 llvm::ArrayRef<llvm::Value *> Array, Args... args) {
111 Values.insert(Values.end(), Array.begin(), Array.end());
112 createPrinter(Builder, UseGPU, Values, args...);
113 }
114
115 /// Print a list of Values.
116 static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
117 llvm::ArrayRef<llvm::Value *> Values);
118
119 /// Print a list of Values on a GPU.
120 static void createGPUPrinterT(PollyIRBuilder &Builder,
121 llvm::ArrayRef<llvm::Value *> Values);
122
123 /// Print a list of Values on a CPU.
124 static void createCPUPrinterT(PollyIRBuilder &Builder,
125 llvm::ArrayRef<llvm::Value *> Values);
126
127 /// Get a reference to the 'printf' function.
128 ///
129 /// If the current module does not yet contain a reference to printf, we
130 /// insert a reference to it. Otherwise the existing reference is returned.
131 static llvm::Function *getPrintF(PollyIRBuilder &Builder);
132
133 /// Call printf
134 ///
135 /// @param Builder The builder used to insert the code.
136 /// @param Format The format string.
137 /// @param Values The set of values to print.
138 static void createPrintF(PollyIRBuilder &Builder, std::string Format,
139 llvm::ArrayRef<llvm::Value *> Values);
140
141 /// Get (and possibly insert) a vprintf declaration into the module.
142 static llvm::Function *getVPrintF(PollyIRBuilder &Builder);
143
144 /// Call fflush
145 ///
146 /// @parma Builder The builder used to insert the code.
147 static void createFlush(PollyIRBuilder &Builder);
148
149 /// Get (and possibly insert) a NVIDIA address space cast call.
150 static llvm::Function *getAddressSpaceCast(PollyIRBuilder &Builder,
151 unsigned Src, unsigned Dst,
152 unsigned SrcBits = 8,
153 unsigned DstBits = 8);
154
155 /// Get identifiers that describe the currently executed GPU thread.
156 ///
157 /// The result will be a vector that if passed to the GPU printer will result
158 /// into a string (initialized to values corresponding to the printing
159 /// thread):
160 ///
161 /// "> block-id: bidx bid1y bidz | thread-id: tidx tidy tidz "
162 static std::vector<llvm::Value *>
163 getGPUThreadIdentifiers(PollyIRBuilder &Builder);
164};
165} // namespace polly
166
167extern bool PollyDebugPrinting;
168
169#endif