Coverage Report

Created: 2017-04-27 19:33

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/polly/lib/CodeGen/PerfMonitor.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------ PerfMonitor.cpp - Generate a run-time performance monitor. -======//
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/PerfMonitor.h"
13
#include "polly/CodeGen/RuntimeDebugBuilder.h"
14
#include "llvm/ADT/Triple.h"
15
#include "llvm/IR/Intrinsics.h"
16
17
using namespace llvm;
18
using namespace polly;
19
20
1
Function *PerfMonitor::getAtExit() {
21
1
  const char *Name = "atexit";
22
1
  Function *F = M->getFunction(Name);
23
1
24
1
  if (
!F1
)
{1
25
1
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
26
1
    FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(),
27
1
                                         {Builder.getInt8PtrTy()}, false);
28
1
    F = Function::Create(Ty, Linkage, Name, M);
29
1
  }
30
1
31
1
  return F;
32
1
}
33
34
1
void PerfMonitor::addToGlobalConstructors(Function *Fn) {
35
1
  const char *Name = "llvm.global_ctors";
36
1
  GlobalVariable *GV = M->getGlobalVariable(Name);
37
1
  std::vector<Constant *> V;
38
1
39
1
  if (
GV1
)
{0
40
0
    Constant *Array = GV->getInitializer();
41
0
    for (Value *X : Array->operand_values())
42
0
      V.push_back(cast<Constant>(X));
43
0
    GV->eraseFromParent();
44
0
  }
45
1
46
1
  StructType *ST = StructType::get(Builder.getInt32Ty(), Fn->getType(),
47
1
                                   Builder.getInt8PtrTy(), nullptr);
48
1
49
1
  V.push_back(ConstantStruct::get(
50
1
      ST, Builder.getInt32(10), Fn,
51
1
      ConstantPointerNull::get(Builder.getInt8PtrTy()), nullptr));
52
1
  ArrayType *Ty = ArrayType::get(ST, V.size());
53
1
54
1
  GV = new GlobalVariable(*M, Ty, true, GlobalValue::AppendingLinkage,
55
1
                          ConstantArray::get(Ty, V), Name, nullptr,
56
1
                          GlobalVariable::NotThreadLocal);
57
1
}
58
59
4
Function *PerfMonitor::getRDTSCP() {
60
4
  return Intrinsic::getDeclaration(M, Intrinsic::x86_rdtscp);
61
4
}
62
63
1
PerfMonitor::PerfMonitor(Module *M) : M(M), Builder(M->getContext()) {
64
1
  if (Triple(M->getTargetTriple()).getArch() == llvm::Triple::x86_64)
65
1
    Supported = true;
66
1
  else
67
0
    Supported = false;
68
1
}
69
70
1
void PerfMonitor::addGlobalVariables() {
71
1
  auto TryRegisterGlobal = [=](const char *Name, Constant *InitialValue,
72
5
                               Value **Location) {
73
5
    *Location = M->getGlobalVariable(Name);
74
5
75
5
    if (!*Location)
76
5
      *Location = new GlobalVariable(
77
5
          *M, InitialValue->getType(), true, GlobalValue::WeakAnyLinkage,
78
5
          InitialValue, Name, nullptr, GlobalVariable::InitialExecTLSModel);
79
5
  };
80
1
81
1
  TryRegisterGlobal("__polly_perf_cycles_total_start", Builder.getInt64(0),
82
1
                    &CyclesTotalStartPtr);
83
1
84
1
  TryRegisterGlobal("__polly_perf_initialized", Builder.getInt1(0),
85
1
                    &AlreadyInitializedPtr);
86
1
87
1
  TryRegisterGlobal("__polly_perf_cycles_in_scops", Builder.getInt64(0),
88
1
                    &CyclesInScopsPtr);
89
1
90
1
  TryRegisterGlobal("__polly_perf_cycles_in_scop_start", Builder.getInt64(0),
91
1
                    &CyclesInScopStartPtr);
92
1
93
1
  TryRegisterGlobal("__polly_perf_write_loation", Builder.getInt32(0),
94
1
                    &RDTSCPWriteLocation);
95
1
}
96
97
static const char *InitFunctionName = "__polly_perf_init";
98
static const char *FinalReportingFunctionName = "__polly_perf_final";
99
100
1
Function *PerfMonitor::insertFinalReporting() {
101
1
  // Create new function.
102
1
  GlobalValue::LinkageTypes Linkage = Function::WeakODRLinkage;
103
1
  FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), {}, false);
104
1
  Function *ExitFn =
105
1
      Function::Create(Ty, Linkage, FinalReportingFunctionName, M);
106
1
  BasicBlock *Start = BasicBlock::Create(M->getContext(), "start", ExitFn);
107
1
  Builder.SetInsertPoint(Start);
108
1
109
1
  if (
!Supported1
)
{0
110
0
    RuntimeDebugBuilder::createCPUPrinter(
111
0
        Builder, "Polly runtime information generation not supported\n");
112
0
    Builder.CreateRetVoid();
113
0
    return ExitFn;
114
0
  }
115
1
116
1
  // Measure current cycles and compute final timings.
117
1
  Function *RDTSCPFn = getRDTSCP();
118
1
  Value *CurrentCycles = Builder.CreateCall(
119
1
      RDTSCPFn,
120
1
      Builder.CreatePointerCast(RDTSCPWriteLocation, Builder.getInt8PtrTy()));
121
1
  Value *CyclesStart = Builder.CreateLoad(CyclesTotalStartPtr, true);
122
1
  Value *CyclesTotal = Builder.CreateSub(CurrentCycles, CyclesStart);
123
1
  Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true);
124
1
125
1
  // Print the runtime information.
126
1
  RuntimeDebugBuilder::createCPUPrinter(Builder, "Polly runtime information\n");
127
1
  RuntimeDebugBuilder::createCPUPrinter(Builder, "-------------------------\n");
128
1
  RuntimeDebugBuilder::createCPUPrinter(Builder, "Total: ", CyclesTotal, "\n");
129
1
  RuntimeDebugBuilder::createCPUPrinter(Builder, "Scops: ", CyclesInScops,
130
1
                                        "\n");
131
1
132
1
  // Finalize function.
133
1
  Builder.CreateRetVoid();
134
1
  return ExitFn;
135
1
}
136
137
1
void PerfMonitor::initialize() {
138
1
  addGlobalVariables();
139
1
140
1
  Function *F = M->getFunction(InitFunctionName);
141
1
  if (F)
142
0
    return;
143
1
144
1
  // initialize
145
1
  Function *FinalReporting = insertFinalReporting();
146
1
  Function *InitFn = insertInitFunction(FinalReporting);
147
1
  addToGlobalConstructors(InitFn);
148
1
}
149
150
1
Function *PerfMonitor::insertInitFunction(Function *FinalReporting) {
151
1
  // Insert function definition and BBs.
152
1
  GlobalValue::LinkageTypes Linkage = Function::WeakODRLinkage;
153
1
  FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), {}, false);
154
1
  Function *InitFn = Function::Create(Ty, Linkage, InitFunctionName, M);
155
1
  BasicBlock *Start = BasicBlock::Create(M->getContext(), "start", InitFn);
156
1
  BasicBlock *EarlyReturn =
157
1
      BasicBlock::Create(M->getContext(), "earlyreturn", InitFn);
158
1
  BasicBlock *InitBB = BasicBlock::Create(M->getContext(), "initbb", InitFn);
159
1
160
1
  Builder.SetInsertPoint(Start);
161
1
162
1
  // Check if this function was already run. If yes, return.
163
1
  //
164
1
  // In case profiling has been enabled in multiple translation units, the
165
1
  // initializer function will be added to the global constructors list of
166
1
  // each translation unit. When merging translation units, the global
167
1
  // constructor lists are just appended, such that the initializer will appear
168
1
  // multiple times. To avoid initializations being run multiple times (and
169
1
  // especially to avoid that atExitFn is called more than once), we bail
170
1
  // out if the intializer is run more than once.
171
1
  Value *HasRunBefore = Builder.CreateLoad(AlreadyInitializedPtr);
172
1
  Builder.CreateCondBr(HasRunBefore, EarlyReturn, InitBB);
173
1
  Builder.SetInsertPoint(EarlyReturn);
174
1
  Builder.CreateRetVoid();
175
1
176
1
  // Keep track that this function has been run once.
177
1
  Builder.SetInsertPoint(InitBB);
178
1
  Value *True = Builder.getInt1(true);
179
1
  Builder.CreateStore(True, AlreadyInitializedPtr);
180
1
181
1
  // Register the final reporting function with atexit().
182
1
  Value *FinalReportingPtr =
183
1
      Builder.CreatePointerCast(FinalReporting, Builder.getInt8PtrTy());
184
1
  Function *AtExitFn = getAtExit();
185
1
  Builder.CreateCall(AtExitFn, {FinalReportingPtr});
186
1
187
1
  if (
Supported1
)
{1
188
1
    // Read the currently cycle counter and store the result for later.
189
1
    Function *RDTSCPFn = getRDTSCP();
190
1
    Value *CurrentCycles = Builder.CreateCall(
191
1
        RDTSCPFn,
192
1
        Builder.CreatePointerCast(RDTSCPWriteLocation, Builder.getInt8PtrTy()));
193
1
    Builder.CreateStore(CurrentCycles, CyclesTotalStartPtr, true);
194
1
  }
195
1
  Builder.CreateRetVoid();
196
1
197
1
  return InitFn;
198
1
}
199
200
1
void PerfMonitor::insertRegionStart(Instruction *InsertBefore) {
201
1
  if (!Supported)
202
0
    return;
203
1
204
1
  Builder.SetInsertPoint(InsertBefore);
205
1
  Function *RDTSCPFn = getRDTSCP();
206
1
  Value *CurrentCycles = Builder.CreateCall(
207
1
      RDTSCPFn,
208
1
      Builder.CreatePointerCast(RDTSCPWriteLocation, Builder.getInt8PtrTy()));
209
1
  Builder.CreateStore(CurrentCycles, CyclesInScopStartPtr, true);
210
1
}
211
212
1
void PerfMonitor::insertRegionEnd(Instruction *InsertBefore) {
213
1
  if (!Supported)
214
0
    return;
215
1
216
1
  Builder.SetInsertPoint(InsertBefore);
217
1
  Function *RDTSCPFn = getRDTSCP();
218
1
  LoadInst *CyclesStart = Builder.CreateLoad(CyclesInScopStartPtr, true);
219
1
  Value *CurrentCycles = Builder.CreateCall(
220
1
      RDTSCPFn,
221
1
      Builder.CreatePointerCast(RDTSCPWriteLocation, Builder.getInt8PtrTy()));
222
1
  Value *CyclesInScop = Builder.CreateSub(CurrentCycles, CyclesStart);
223
1
  Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true);
224
1
  CyclesInScops = Builder.CreateAdd(CyclesInScops, CyclesInScop);
225
1
  Builder.CreateStore(CyclesInScops, CyclesInScopsPtr, true);
226
1
}