[cfe-commits] r133250 - in /cfe/trunk: lib/CodeGen/ItaniumCXXABI.cpp test/CodeGenCXX/static-init.cpp

John McCall rjmccall at apple.com
Fri Jun 17 00:33:57 PDT 2011


Author: rjmccall
Date: Fri Jun 17 02:33:57 2011
New Revision: 133250

URL: http://llvm.org/viewvc/llvm-project?rev=133250&view=rev
Log:
Perform an acquire memory barrier on the fast path of a thread-safe
static initializer check, as required by the Itanium ABI.


Modified:
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/static-init.cpp

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=133250&r1=133249&r2=133250&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Jun 17 02:33:57 2011
@@ -24,6 +24,7 @@
 #include "CodeGenModule.h"
 #include <clang/AST/Mangle.h>
 #include <clang/AST/Type.h>
+#include <llvm/Intrinsics.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Value.h>
 
@@ -1088,19 +1089,19 @@
 
   // We only need to use thread-safe statics for local variables;
   // global initialization is always single-threaded.
-  bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics &&
-                            D.isLocalVarDecl());
+  bool threadsafe =
+    (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl());
 
   const llvm::IntegerType *GuardTy;
 
   // If we have a global variable with internal linkage and thread-safe statics
   // are disabled, we can just let the guard variable be of type i8.
-  bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage();
-  if (UseInt8GuardVariable)
-    GuardTy = Builder.getInt8Ty();
-  else {
+  bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage();
+  if (useInt8GuardVariable) {
+    GuardTy = CGF.Int8Ty;
+  } else {
     // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
-    GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty());
+    GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty);
   }
   const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
 
@@ -1132,7 +1133,7 @@
   //       if (__cxa_guard_acquire(&obj_guard))
   //         ...
   //     }
-  if (IsARM && !UseInt8GuardVariable) {
+  if (IsARM && !useInt8GuardVariable) {
     llvm::Value *V = Builder.CreateLoad(GuardVariable);
     V = Builder.CreateAnd(V, Builder.getInt32(1));
     IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
@@ -1163,13 +1164,16 @@
   llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
   llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
 
+  llvm::BasicBlock *NoCheckBlock = EndBlock;
+  if (threadsafe) NoCheckBlock = CGF.createBasicBlock("init.barrier");
+
   // Check if the first byte of the guard variable is zero.
-  Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+  Builder.CreateCondBr(IsInitialized, InitCheckBlock, NoCheckBlock);
 
   CGF.EmitBlock(InitCheckBlock);
 
   // Variables used when coping with thread-safe statics and exceptions.
-  if (ThreadsafeStatics) {    
+  if (threadsafe) {    
     // Call __cxa_guard_acquire.
     llvm::Value *V
       = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
@@ -1188,7 +1192,7 @@
   // Emit the initializer and add a global destructor if appropriate.
   CGF.EmitCXXGlobalVarDeclInit(D, GV);
 
-  if (ThreadsafeStatics) {
+  if (threadsafe) {
     // Pop the guard-abort cleanup if we pushed one.
     CGF.PopCleanupBlock();
 
@@ -1198,5 +1202,23 @@
     Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
   }
 
+  // Emit an acquire memory barrier if using thread-safe statics:
+  // Itanium ABI:
+  //   An implementation supporting thread-safety on multiprocessor
+  //   systems must also guarantee that references to the initialized
+  //   object do not occur before the load of the initialization flag.
+  if (threadsafe) {
+    Builder.CreateBr(EndBlock);
+    CGF.EmitBlock(NoCheckBlock);
+
+    llvm::Value *_false = Builder.getFalse();
+    llvm::Value *_true = Builder.getTrue();
+
+    Builder.CreateCall5(CGM.getIntrinsic(llvm::Intrinsic::memory_barrier),
+                        /* load-load, load-store */ _true, _true,
+                        /* store-load, store-store */ _false, _false,
+                        /* device or I/O */ _false);
+  }
+
   CGF.EmitBlock(EndBlock);
 }

Modified: cfe/trunk/test/CodeGenCXX/static-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-init.cpp?rev=133250&r1=133249&r2=133250&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-init.cpp Fri Jun 17 02:33:57 2011
@@ -16,6 +16,9 @@
   // CHECK: call void @_ZN1AC1Ev
   // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
   // CHECK: call void @__cxa_guard_release
+
+  // rdar://problem/9496726
+  // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 false, i1 false, i1 false)
   static A a;
 }
 





More information about the cfe-commits mailing list