| Index: src/IceGlobalContext.cpp
|
| diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
|
| index 319e18a9d6a3c6ecac74d7bc3454b44eed6bbaad..14d51e717afa2c47b1927d1edff772108047909e 100644
|
| --- a/src/IceGlobalContext.cpp
|
| +++ b/src/IceGlobalContext.cpp
|
| @@ -115,6 +115,93 @@ public:
|
| UndefPool Undefs;
|
| };
|
|
|
| +class TimerStack {
|
| + TimerStack(const TimerStack &) LLVM_DELETED_FUNCTION;
|
| + TimerStack &operator=(const TimerStack &) LLVM_DELETED_FUNCTION;
|
| +
|
| +public:
|
| + TimerStack(const IceString &TopLevelName)
|
| + : FirstTimestamp(timestamp()), LastTimestamp(FirstTimestamp) {
|
| + push(TopLevelName);
|
| + }
|
| + void push(const IceString &Name) {
|
| + update();
|
| + Stack.push_back(Name);
|
| + // Construct the new node's recursive name by appending .Name to
|
| + // the previous top-of-stack's recursive name.
|
| + IceString Prefix = "";
|
| + if (!FullNames.empty())
|
| + Prefix = FullNames.back() + ".";
|
| + FullNames.push_back(Prefix + Name);
|
| + }
|
| + void pop(const IceString &Name) {
|
| + update();
|
| + assert(!Stack.empty());
|
| + assert(Stack.back() == Name);
|
| + Stack.pop_back();
|
| + FullNames.pop_back();
|
| + }
|
| + void dump(Ostream &Str);
|
| +
|
| +private:
|
| + typedef std::map<IceString, double> MapType;
|
| + void update();
|
| + void dumpHelper(Ostream &Str, const MapType &Map, double TotalTime);
|
| + static double timestamp() {
|
| + // TODO: Implement in terms of std::chrono for C++11.
|
| + return llvm::TimeRecord::getCurrentTime(false).getWallTime();
|
| + }
|
| + const double FirstTimestamp;
|
| + volatile double LastTimestamp;
|
| + std::vector<IceString> Stack;
|
| + std::vector<IceString> FullNames;
|
| + MapType RecursiveTime;
|
| + MapType LeafTime;
|
| +};
|
| +
|
| +void TimerStack::update() {
|
| + // Whenever the stack is about to change, we grab the time delta
|
| + // since the last change and add it to all active recursive elements
|
| + // and to the non-recursive element for the top of the stack.
|
| + double Current = timestamp();
|
| + double Delta = Current - LastTimestamp;
|
| + LastTimestamp = Current;
|
| + for (size_t i = 0; i < FullNames.size(); ++i) {
|
| + RecursiveTime[FullNames[i]] += Delta;
|
| + }
|
| + if (!Stack.empty()) {
|
| + LeafTime[Stack.back()] += Delta;
|
| + }
|
| +}
|
| +
|
| +void TimerStack::dumpHelper(Ostream &Str, const MapType &Map,
|
| + double TotalTime) {
|
| + // Dump the items in reverse order of their time contribution.
|
| + typedef std::multimap<double, IceString> RMapType;
|
| + RMapType MultiMap;
|
| + for (MapType::const_iterator I = Map.begin(), E = Map.end(); I != E; ++I) {
|
| + MultiMap.insert(std::make_pair(I->second, I->first));
|
| + }
|
| + for (RMapType::const_reverse_iterator I = MultiMap.rbegin(),
|
| + E = MultiMap.rend();
|
| + I != E; ++I) {
|
| + char buf[80];
|
| + snprintf(buf, llvm::array_lengthof(buf), " %10.6f (%4.1f%%): ", I->first,
|
| + I->first * 100 / TotalTime);
|
| + Str << buf << I->second << "\n";
|
| + }
|
| +}
|
| +
|
| +void TimerStack::dump(Ostream &Str) {
|
| + update();
|
| + double TotalTime = LastTimestamp - FirstTimestamp;
|
| + assert(TotalTime);
|
| + Str << "Recursive function times:\n";
|
| + dumpHelper(Str, RecursiveTime, TotalTime);
|
| + Str << "Non-recursive function times:\n";
|
| + dumpHelper(Str, LeafTime, TotalTime);
|
| +}
|
| +
|
| GlobalContext::GlobalContext(llvm::raw_ostream *OsDump,
|
| llvm::raw_ostream *OsEmit, VerboseMask Mask,
|
| TargetArch Arch, OptLevel Opt,
|
| @@ -122,7 +209,7 @@ GlobalContext::GlobalContext(llvm::raw_ostream *OsDump,
|
| : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask),
|
| ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt),
|
| TestPrefix(TestPrefix), Flags(Flags), HasEmittedFirstMethod(false),
|
| - RNG("") {}
|
| + RNG(""), Timers(new TimerStack("main")) {}
|
|
|
| // Scan a string for S[0-9A-Z]*_ patterns and replace them with
|
| // S<num>_ where <num> is the next base-36 value. If a type name
|
| @@ -384,6 +471,12 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const {
|
| llvm_unreachable("Unknown type");
|
| }
|
|
|
| +void GlobalContext::pushTimer(const IceString &Name) {
|
| + Timers.get()->push(Name);
|
| +}
|
| +
|
| +void GlobalContext::popTimer(const IceString &Name) { Timers.get()->pop(Name); }
|
| +
|
| void GlobalContext::dumpStats(const IceString &Name, bool Final) {
|
| if (Flags.DumpStats) {
|
| if (Final) {
|
| @@ -395,12 +488,6 @@ void GlobalContext::dumpStats(const IceString &Name, bool Final) {
|
| }
|
| }
|
|
|
| -void Timer::printElapsedUs(GlobalContext *Ctx, const IceString &Tag) const {
|
| - if (Ctx->isVerbose(IceV_Timing)) {
|
| - // Prefixing with '#' allows timing strings to be included
|
| - // without error in textual assembly output.
|
| - Ctx->getStrDump() << "# " << getElapsedUs() << " usec " << Tag << "\n";
|
| - }
|
| -}
|
| +void GlobalContext::dumpTimers() { Timers.get()->dump(getStrDump()); }
|
|
|
| } // end of namespace Ice
|
|
|