Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/IceGlobalContext.cpp

Issue 610813002: Subzero: Rewrite the pass timing infrastructure. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Bug fixes and performance improvements Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===// 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs ---*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file defines aspects of the compilation that persist across 10 // This file defines aspects of the compilation that persist across
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 public: 108 public:
109 ConstantPool() {} 109 ConstantPool() {}
110 TypePool<float, ConstantFloat, true> Floats; 110 TypePool<float, ConstantFloat, true> Floats;
111 TypePool<double, ConstantDouble, true> Doubles; 111 TypePool<double, ConstantDouble, true> Doubles;
112 TypePool<uint32_t, ConstantInteger32> Integers32; 112 TypePool<uint32_t, ConstantInteger32> Integers32;
113 TypePool<uint64_t, ConstantInteger64> Integers64; 113 TypePool<uint64_t, ConstantInteger64> Integers64;
114 TypePool<RelocatableTuple, ConstantRelocatable> Relocatables; 114 TypePool<RelocatableTuple, ConstantRelocatable> Relocatables;
115 UndefPool Undefs; 115 UndefPool Undefs;
116 }; 116 };
117 117
118 class TimerStack {
119 TimerStack(const TimerStack &) LLVM_DELETED_FUNCTION;
120 TimerStack &operator=(const TimerStack &) LLVM_DELETED_FUNCTION;
121
122 public:
123 TimerStack(const IceString &TopLevelName)
124 : FirstTimestamp(timestamp()), LastTimestamp(FirstTimestamp),
125 StateChanges(0) {
126 push(TopLevelName);
127 }
128 void push(const IceString &Name) {
129 update();
130 Stack.push_back(Name);
131 // Construct the new node's recursive name by appending .Name to
132 // the previous top-of-stack's recursive name.
133 IceString Prefix = "";
134 if (!FullNames.empty())
135 Prefix = FullNames.back() + ".";
136 FullNames.push_back(Prefix + Name);
Karl 2014/09/29 16:55:07 Minor nit. There is a lot of string building going
Jim Stichnoth 2014/09/30 17:50:50 Good point, and it does turn into a real performan
137 }
138 void pop(const IceString &Name) {
139 update();
140 assert(!Stack.empty());
141 assert(Stack.back() == Name);
142 (void)Name;
143 Stack.pop_back();
144 FullNames.pop_back();
145 }
146 void dump(Ostream &Str);
147
148 private:
149 typedef std::map<IceString, double> MapType;
Karl 2014/09/29 16:55:07 Using string as the key can be quite expensive. Co
Jim Stichnoth 2014/09/30 17:50:50 Done, see the comment above.
150 void update();
151 void dumpHelper(Ostream &Str, const MapType &Map, double TotalTime);
152 static double timestamp() {
153 // TODO: Implement in terms of std::chrono for C++11.
154 return llvm::TimeRecord::getCurrentTime(false).getWallTime();
155 }
156 const double FirstTimestamp;
157 volatile double LastTimestamp;
158 std::vector<IceString> Stack;
159 std::vector<IceString> FullNames;
160 MapType RecursiveTime;
161 MapType LeafTime;
162 uint64_t StateChanges;
163 };
164
165 void TimerStack::update() {
166 ++StateChanges;
167 // Whenever the stack is about to change, we grab the time delta
168 // since the last change and add it to all active recursive elements
169 // and to the non-recursive element for the top of the stack.
170 double Current = timestamp();
171 double Delta = Current - LastTimestamp;
172 LastTimestamp = Current;
173 for (size_t i = 0; i < FullNames.size(); ++i) {
174 RecursiveTime[FullNames[i]] += Delta;
175 }
176 if (!Stack.empty()) {
177 LeafTime[Stack.back()] += Delta;
178 }
179 }
180
181 void TimerStack::dumpHelper(Ostream &Str, const MapType &Map,
182 double TotalTime) {
183 // Dump the items in reverse order of their time contribution.
184 typedef std::multimap<double, IceString> RMapType;
185 RMapType MultiMap;
186 for (MapType::const_iterator I = Map.begin(), E = Map.end(); I != E; ++I) {
187 MultiMap.insert(std::make_pair(I->second, I->first));
188 }
189 for (RMapType::const_reverse_iterator I = MultiMap.rbegin(),
190 E = MultiMap.rend();
191 I != E; ++I) {
192 char buf[80];
193 snprintf(buf, llvm::array_lengthof(buf), " %10.6f (%4.1f%%): ", I->first,
194 I->first * 100 / TotalTime);
195 Str << buf << I->second << "\n";
196 }
197 }
198
199 void TimerStack::dump(Ostream &Str) {
200 update();
201 double TotalTime = LastTimestamp - FirstTimestamp;
202 assert(TotalTime);
203 Str << "Recursive function times:\n";
204 dumpHelper(Str, RecursiveTime, TotalTime);
205 Str << "Non-recursive function times:\n";
206 dumpHelper(Str, LeafTime, TotalTime);
207 Str << "Number of timer updates: " << StateChanges << "\n";
208 }
209
118 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump, 210 GlobalContext::GlobalContext(llvm::raw_ostream *OsDump,
119 llvm::raw_ostream *OsEmit, VerboseMask Mask, 211 llvm::raw_ostream *OsEmit, VerboseMask Mask,
120 TargetArch Arch, OptLevel Opt, 212 TargetArch Arch, OptLevel Opt,
121 IceString TestPrefix, const ClFlags &Flags) 213 IceString TestPrefix, const ClFlags &Flags)
122 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), 214 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask),
123 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), 215 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt),
124 TestPrefix(TestPrefix), Flags(Flags), HasEmittedFirstMethod(false), 216 TestPrefix(TestPrefix), Flags(Flags), HasEmittedFirstMethod(false),
125 RNG("") {} 217 RNG(""), Timers(new TimerStack("main")) {}
126 218
127 // Scan a string for S[0-9A-Z]*_ patterns and replace them with 219 // Scan a string for S[0-9A-Z]*_ patterns and replace them with
128 // S<num>_ where <num> is the next base-36 value. If a type name 220 // S<num>_ where <num> is the next base-36 value. If a type name
129 // legitimately contains that pattern, then the substitution will be 221 // legitimately contains that pattern, then the substitution will be
130 // made in error and most likely the link will fail. In this case, 222 // made in error and most likely the link will fail. In this case,
131 // the test classes can be rewritten not to use that pattern, which is 223 // the test classes can be rewritten not to use that pattern, which is
132 // much simpler and more reliable than implementing a full demangling 224 // much simpler and more reliable than implementing a full demangling
133 // parser. Another substitution-in-error may occur if a type 225 // parser. Another substitution-in-error may occur if a type
134 // identifier ends with the pattern S[0-9A-Z]*, because an immediately 226 // identifier ends with the pattern S[0-9A-Z]*, because an immediately
135 // following substitution string like "S1_" or "PS1_" may be combined 227 // following substitution string like "S1_" or "PS1_" may be combined
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 BaseOS << "Unsupported constant type: " << Ty; 469 BaseOS << "Unsupported constant type: " << Ty;
378 llvm_unreachable(BaseOS.str().c_str()); 470 llvm_unreachable(BaseOS.str().c_str());
379 } break; 471 } break;
380 case IceType_void: 472 case IceType_void:
381 case IceType_NUM: 473 case IceType_NUM:
382 break; 474 break;
383 } 475 }
384 llvm_unreachable("Unknown type"); 476 llvm_unreachable("Unknown type");
385 } 477 }
386 478
479 void GlobalContext::pushTimer(const IceString &Name) {
480 Timers.get()->push(Name);
481 }
482
483 void GlobalContext::popTimer(const IceString &Name) { Timers.get()->pop(Name); }
484
387 void GlobalContext::dumpStats(const IceString &Name, bool Final) { 485 void GlobalContext::dumpStats(const IceString &Name, bool Final) {
388 if (Flags.DumpStats) { 486 if (Flags.DumpStats) {
389 if (Final) { 487 if (Final) {
390 StatsCumulative.dump(Name, getStrDump()); 488 StatsCumulative.dump(Name, getStrDump());
391 } else { 489 } else {
392 StatsFunction.dump(Name, getStrDump()); 490 StatsFunction.dump(Name, getStrDump());
393 StatsCumulative.dump("_TOTAL_", getStrDump()); 491 StatsCumulative.dump("_TOTAL_", getStrDump());
394 } 492 }
395 } 493 }
396 } 494 }
397 495
398 void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const { 496 void GlobalContext::dumpTimers() { Timers.get()->dump(getStrDump()); }
399 if (Ctx->isVerbose(IceV_Timing)) {
400 // Prefixing with '#' allows timing strings to be included
401 // without error in textual assembly output.
402 Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n";
403 }
404 }
405 497
406 } // end of namespace Ice 498 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698