summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGDeclCXX.cpp41
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h8
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp5
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp10
4 files changed, 57 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index d8768bee2cd..98d9e364d9c 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -18,6 +18,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/MDBuilder.h"
#include "llvm/Support/Path.h"
using namespace clang;
@@ -259,6 +260,43 @@ void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
}
+void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
+ llvm::BasicBlock *InitBlock,
+ llvm::BasicBlock *NoInitBlock,
+ GuardKind Kind,
+ const VarDecl *D) {
+ assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable");
+
+ // A guess at how many times we will enter the initialization of a
+ // variable, depending on the kind of variable.
+ static const uint64_t InitsPerTLSVar = 1024;
+ static const uint64_t InitsPerLocalVar = 1024 * 1024;
+
+ llvm::MDNode *Weights;
+ if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) {
+ // For non-local variables, don't apply any weighting for now. Due to our
+ // use of COMDATs, we expect there to be at most one initialization of the
+ // variable per DSO, but we have no way to know how many DSOs will try to
+ // initialize the variable.
+ Weights = nullptr;
+ } else {
+ uint64_t NumInits;
+ // FIXME: For the TLS case, collect and use profiling information to
+ // determine a more accurate brach weight.
+ if (Kind == GuardKind::TlsGuard || D->getTLSKind())
+ NumInits = InitsPerTLSVar;
+ else
+ NumInits = InitsPerLocalVar;
+
+ // The probability of us entering the initializer is
+ // 1 / (total number of times we attempt to initialize the variable).
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+ Weights = MDHelper.createBranchWeights(1, NumInits - 1);
+ }
+
+ Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights);
+}
+
llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,
SourceLocation Loc, bool TLS) {
@@ -539,7 +577,8 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
"guard.uninitialized");
llvm::BasicBlock *InitBlock = createBasicBlock("init");
ExitBlock = createBasicBlock("exit");
- Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
+ EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,
+ GuardKind::TlsGuard, nullptr);
EmitBlock(InitBlock);
// Mark as initialized before initializing anything else. If the
// initializers use previously-initialized thread_local vars, that's
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 753dd92f307..2e31be8c686 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3496,6 +3496,14 @@ public:
void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr,
bool PerformInit);
+ enum class GuardKind { VariableGuard, TlsGuard };
+
+ /// Emit a branch to select whether or not to perform guarded initialization.
+ void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
+ llvm::BasicBlock *InitBlock,
+ llvm::BasicBlock *NoInitBlock,
+ GuardKind Kind, const VarDecl *D);
+
/// GenerateCXXGlobalInitFunc - Generates code for initializing global
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index d1f47b6d1a4..de9fd042a9e 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2113,13 +2113,14 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
(UseARMGuardVarABI && !useInt8GuardVariable)
? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
: LI;
- llvm::Value *isInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+ llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
// Check if the first byte of the guard variable is zero.
- Builder.CreateCondBr(isInitialized, InitCheckBlock, EndBlock);
+ CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
CGF.EmitBlock(InitCheckBlock);
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 78b510bb466..409bad72ee5 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2463,11 +2463,12 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// Test our bit from the guard variable.
llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
- llvm::Value *IsInitialized =
- Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
+ llvm::Value *NeedsInit =
+ Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
- Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+ CGF.EmitCXXGuardedInitBranch(NeedsInit, InitBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
// Set our bit in the guard variable and emit the initializer and add a global
// destructor if appropriate.
@@ -2502,7 +2503,8 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
llvm::BasicBlock *AttemptInitBlock = CGF.createBasicBlock("init.attempt");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
- Builder.CreateCondBr(IsUninitialized, AttemptInitBlock, EndBlock);
+ CGF.EmitCXXGuardedInitBranch(IsUninitialized, AttemptInitBlock, EndBlock,
+ CodeGenFunction::GuardKind::VariableGuard, &D);
// This BasicBlock attempts to determine whether or not this thread is
// responsible for doing the initialization.
OpenPOWER on IntegriCloud