Coverage Report

Created: 2019-04-21 11:35

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