Coverage Report

Created: 2017-06-28 17:40

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