11
11
12
12
#include " polly/CodeGen/PerfMonitor.h"
13
13
#include " polly/CodeGen/RuntimeDebugBuilder.h"
14
+ #include " polly/ScopInfo.h"
14
15
#include " llvm/ADT/Triple.h"
15
16
#include " llvm/IR/Intrinsics.h"
17
+ #include < sstream>
16
18
17
19
using namespace llvm ;
18
20
using namespace polly ;
@@ -60,51 +62,73 @@ Function *PerfMonitor::getRDTSCP() {
60
62
return Intrinsic::getDeclaration (M, Intrinsic::x86_rdtscp);
61
63
}
62
64
63
- PerfMonitor::PerfMonitor (Module *M) : M(M), Builder(M->getContext ()) {
65
+ PerfMonitor::PerfMonitor (const Scop &S, Module *M)
66
+ : M(M), Builder(M->getContext ()), S(S) {
64
67
if (Triple (M->getTargetTriple ()).getArch () == llvm::Triple::x86_64)
65
68
Supported = true ;
66
69
else
67
70
Supported = false ;
68
71
}
69
72
70
- void PerfMonitor::addGlobalVariables () {
71
- auto TryRegisterGlobal = [=](const char *Name, Constant *InitialValue,
72
- Value **Location) {
73
- *Location = M->getGlobalVariable (Name);
73
+ static void TryRegisterGlobal (Module *M, const char *Name,
74
+ Constant *InitialValue, Value **Location) {
75
+ *Location = M->getGlobalVariable (Name);
76
+
77
+ if (!*Location)
78
+ *Location = new GlobalVariable (
79
+ *M, InitialValue->getType (), true , GlobalValue::WeakAnyLinkage,
80
+ InitialValue, Name, nullptr , GlobalVariable::InitialExecTLSModel);
81
+ };
82
+
83
+ // Generate a unique name that is usable as a LLVM name for a scop to name its
84
+ // performance counter.
85
+ static std::string GetScopUniqueVarname (const Scop &S) {
86
+ std::stringstream Name;
87
+ std::string EntryString, ExitString;
88
+ std::tie (EntryString, ExitString) = S.getEntryExitStr ();
89
+
90
+ Name << " __polly_perf_cycles_in_" << std::string (S.getFunction ().getName ())
91
+ << " _from__" << EntryString << " __to__" << ExitString;
92
+ return Name.str ();
93
+ }
74
94
75
- if (!*Location)
76
- *Location = new GlobalVariable (
77
- * M, InitialValue-> getType (), true , GlobalValue::WeakAnyLinkage ,
78
- InitialValue, Name, nullptr , GlobalVariable::InitialExecTLSModel );
79
- };
95
+ void PerfMonitor::addScopCounter () {
96
+ const std::string varname = GetScopUniqueVarname (S);
97
+ TryRegisterGlobal ( M, varname. c_str (), Builder. getInt64 ( 0 ) ,
98
+ &CyclesInCurrentScopPtr );
99
+ }
80
100
81
- TryRegisterGlobal (" __polly_perf_cycles_total_start" , Builder.getInt64 (0 ),
101
+ void PerfMonitor::addGlobalVariables () {
102
+ TryRegisterGlobal (M, " __polly_perf_cycles_total_start" , Builder.getInt64 (0 ),
82
103
&CyclesTotalStartPtr);
83
104
84
- TryRegisterGlobal (" __polly_perf_initialized" , Builder.getInt1 (0 ),
105
+ TryRegisterGlobal (M, " __polly_perf_initialized" , Builder.getInt1 (0 ),
85
106
&AlreadyInitializedPtr);
86
107
87
- TryRegisterGlobal (" __polly_perf_cycles_in_scops" , Builder.getInt64 (0 ),
108
+ TryRegisterGlobal (M, " __polly_perf_cycles_in_scops" , Builder.getInt64 (0 ),
88
109
&CyclesInScopsPtr);
89
110
90
- TryRegisterGlobal (" __polly_perf_cycles_in_scop_start" , Builder.getInt64 (0 ),
111
+ TryRegisterGlobal (M, " __polly_perf_cycles_in_scop_start" , Builder.getInt64 (0 ),
91
112
&CyclesInScopStartPtr);
92
113
93
- TryRegisterGlobal (" __polly_perf_write_loation" , Builder.getInt32 (0 ),
114
+ TryRegisterGlobal (M, " __polly_perf_write_loation" , Builder.getInt32 (0 ),
94
115
&RDTSCPWriteLocation);
95
116
}
96
117
97
118
static const char *InitFunctionName = " __polly_perf_init" ;
98
119
static const char *FinalReportingFunctionName = " __polly_perf_final" ;
99
120
121
+ static BasicBlock *FinalStartBB = nullptr ;
122
+ static ReturnInst *ReturnFromFinal = nullptr ;
123
+
100
124
Function *PerfMonitor::insertFinalReporting () {
101
125
// Create new function.
102
126
GlobalValue::LinkageTypes Linkage = Function::WeakODRLinkage;
103
127
FunctionType *Ty = FunctionType::get (Builder.getVoidTy (), {}, false );
104
128
Function *ExitFn =
105
129
Function::Create (Ty, Linkage, FinalReportingFunctionName, M);
106
- BasicBlock *Start = BasicBlock::Create (M->getContext (), " start" , ExitFn);
107
- Builder.SetInsertPoint (Start );
130
+ FinalStartBB = BasicBlock::Create (M->getContext (), " start" , ExitFn);
131
+ Builder.SetInsertPoint (FinalStartBB );
108
132
109
133
if (!Supported) {
110
134
RuntimeDebugBuilder::createCPUPrinter (
@@ -128,23 +152,42 @@ Function *PerfMonitor::insertFinalReporting() {
128
152
RuntimeDebugBuilder::createCPUPrinter (Builder, " Total: " , CyclesTotal, " \n " );
129
153
RuntimeDebugBuilder::createCPUPrinter (Builder, " Scops: " , CyclesInScops,
130
154
" \n " );
131
-
132
- // Finalize function.
133
- Builder.CreateRetVoid ();
155
+ ReturnFromFinal = Builder.CreateRetVoid ();
134
156
return ExitFn;
135
157
}
136
158
159
+ void PerfMonitor::AppendScopReporting () {
160
+ Builder.SetInsertPoint (FinalStartBB);
161
+ ReturnFromFinal->eraseFromParent ();
162
+
163
+ Value *CyclesInCurrentScop =
164
+ Builder.CreateLoad (this ->CyclesInCurrentScopPtr , true );
165
+ std::string EntryName, ExitName;
166
+ std::tie (EntryName, ExitName) = S.getEntryExitStr ();
167
+
168
+ RuntimeDebugBuilder::createCPUPrinter (
169
+ Builder, " Scop(" , S.getFunction ().getName (), " |from: " , EntryName,
170
+ " |to: " , ExitName, " ): " , CyclesInCurrentScop, " \n " );
171
+
172
+ ReturnFromFinal = Builder.CreateRetVoid ();
173
+ }
174
+
175
+ static Function *FinalReporting = nullptr ;
176
+
137
177
void PerfMonitor::initialize () {
138
178
addGlobalVariables ();
179
+ addScopCounter ();
139
180
140
- Function *F = M->getFunction (InitFunctionName);
141
- if (F)
142
- return ;
181
+ // Ensure that we only add the final reporting function once.
182
+ // On later invocations, append to the reporting function.
183
+ if (!FinalReporting) {
184
+ FinalReporting = insertFinalReporting ();
185
+
186
+ Function *InitFn = insertInitFunction (FinalReporting);
187
+ addToGlobalConstructors (InitFn);
188
+ }
143
189
144
- // initialize
145
- Function *FinalReporting = insertFinalReporting ();
146
- Function *InitFn = insertInitFunction (FinalReporting);
147
- addToGlobalConstructors (InitFn);
190
+ AppendScopReporting ();
148
191
}
149
192
150
193
Function *PerfMonitor::insertInitFunction (Function *FinalReporting) {
@@ -223,4 +266,8 @@ void PerfMonitor::insertRegionEnd(Instruction *InsertBefore) {
223
266
Value *CyclesInScops = Builder.CreateLoad (CyclesInScopsPtr, true );
224
267
CyclesInScops = Builder.CreateAdd (CyclesInScops, CyclesInScop);
225
268
Builder.CreateStore (CyclesInScops, CyclesInScopsPtr, true );
269
+
270
+ Value *CyclesInCurrentScop = Builder.CreateLoad (CyclesInCurrentScopPtr, true );
271
+ CyclesInCurrentScop = Builder.CreateAdd (CyclesInCurrentScop, CyclesInScop);
272
+ Builder.CreateStore (CyclesInCurrentScop, CyclesInCurrentScopPtr, true );
226
273
}
0 commit comments