OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |