llvm.org GIT mirror llvm / 50e9ef1
Merging r227300: ------------------------------------------------------------------------ r227300 | chandlerc | 2015-01-28 01:52:14 -0800 (Wed, 28 Jan 2015) | 34 lines [LPM] Rip all of ManagedStatic and ThreadLocal out of the pretty stack tracing code. Managed static was just insane overhead for this. We took memory fences and external function calls in every path that pushed a pretty stack frame. This includes a multitude of layers setting up and tearing down passes, the parser in Clang, everywhere. For the regression test suite or low-overhead JITs, this was contributing to really significant overhead. Even the LLVM ThreadLocal is really overkill here because it uses pthread_{set,get}_specific logic, and has careful code to both allocate and delete the thread local data. We don't actually want any of that, and this code in particular has problems coping with deallocation. What we want is a single TLS pointer that is valid to use during global construction and during global destruction, any time we want. That is exactly what every host compiler and OS we use has implemented for a long time, and what was standardized in C++11. Even though not all of our host compilers support the thread_local keyword, we can directly use the platform-specific keywords to get the minimal functionality needed. Provided this limited trial survives the build bots, I will move this to Compiler.h so it is more widely available as a light weight if limited alternative to the ThreadLocal class. Many thanks to David Majnemer for helping me think through the implications across platforms and craft the MSVC-compatible syntax. The end result is *substantially* faster. When running llc in a tight loop over a small IR file targeting the aarch64 backend, this improves its performance by over 10% for me. It also seems likely to fix the remaining regressions seen by JIT users with threading enabled. This may actually have more impact on real-world compile times due to the use of the pretty stack tracing utility throughout the rest of Clang or LLVM, but I've not collected any detailed measurements. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_36@227332 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 4 years ago
1 changed file(s) with 18 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
1515 #include "llvm-c/Core.h"
1616 #include "llvm/ADT/SmallString.h"
1717 #include "llvm/Config/config.h" // Get autoconf configuration settings
18 #include "llvm/Support/ManagedStatic.h"
1918 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/ThreadLocal.h"
2119 #include "llvm/Support/Watchdog.h"
2220 #include "llvm/Support/raw_ostream.h"
2321
2725
2826 using namespace llvm;
2927
30 static ManagedStatic > PrettyStackTraceHead;
28 // We need a thread local pointer to manage the stack of our stack trace
29 // objects, but we *really* cannot tolerate destructors running and do not want
30 // to pay any overhead of synchronizing. As a consequence, we use a raw
31 // thread-local variable. Some day, we should be able to use a limited subset
32 // of C++11's thread_local, but compilers aren't up for it today.
33 // FIXME: This should be moved to a Compiler.h abstraction.
34 #ifdef _MSC_VER // MSVC supports this with a __declspec.
35 static __declspec(thread) const PrettyStackTraceEntry
36 *PrettyStackTraceHead = nullptr;
37 #else // Clang, GCC, and all compatible compilers tend to use __thread.
38 static __thread const PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
39 #endif
3140
3241 static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
3342 unsigned NextID = 0;
4554 /// PrintCurStackTrace - Print the current stack trace to the specified stream.
4655 static void PrintCurStackTrace(raw_ostream &OS) {
4756 // Don't print an empty trace.
48 if (!PrettyStackTraceHead->get()) return;
57 if (!PrettyStackTraceHead) return;
4958
5059 // If there are pretty stack frames registered, walk and emit them.
5160 OS << "Stack dump:\n";
5261
53 PrintStack(PrettyStackTraceHead->get(), OS);
62 PrintStack(PrettyStackTraceHead, OS);
5463 OS.flush();
5564 }
5665
100109
101110 PrettyStackTraceEntry::PrettyStackTraceEntry() {
102111 // Link ourselves.
103 NextEntry = PrettyStackTraceHead->get();
104 PrettyStackTraceHead->set(this);
112 NextEntry = PrettyStackTraceHead;
113 PrettyStackTraceHead = this;
105114 }
106115
107116 PrettyStackTraceEntry::~PrettyStackTraceEntry() {
108 // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen
109 // if a shutdown occurred after we created the PrettyStackTraceEntry. That
110 // does occur in the following idiom:
111 //
112 // PrettyStackTraceProgram X(...);
113 // llvm_shutdown_obj Y;
114 //
115 // Without this check, we may end up removing ourselves from the stack trace
116 // after PrettyStackTraceHead has already been destroyed.
117 if (!PrettyStackTraceHead.isConstructed())
118 return;
119
120 assert(PrettyStackTraceHead->get() == this &&
117 assert(PrettyStackTraceHead == this &&
121118 "Pretty stack trace entry destruction is out of order");
122 PrettyStackTraceHead->set(getNextEntry());
119 PrettyStackTraceHead = getNextEntry();
123120 }
124121
125122 void PrettyStackTraceString::print(raw_ostream &OS) const {