Chromium Code Reviews| 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 |