[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