Coverage Report

Created: 2019-02-20 07:29

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