aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-17 07:31:37 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-17 07:31:37 +0000
commitabb943284cabd9131586c2758a4f02baba668ace (patch)
tree42efe3c363a750781cc565152093a39f80b99b1f /lib/CodeGen/CGDeclCXX.cpp
parent1e009d594325390eda1e3c89e4930b30d8b828dc (diff)
The clang half of r150794: after the construction of a global or static const
variable ends, if the variable has a trivial destructor and no mutable subobjects then emit an llvm.invariant.start call for it. globalopt knows to make the variable const when evaluating this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150798 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDeclCXX.cpp')
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp18
1 files changed, 17 insertions, 1 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 189760821b..75bb7dedd9 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -101,6 +101,19 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
CGF.EmitCXXGlobalDtorRegistration(function, argument);
}
+/// Emit code to cause the variable at the given address to be considered as
+/// constant from this point onwards.
+static void EmitDeclInvariant(CodeGenFunction &CGF, llvm::Constant *Addr) {
+ // Grab the llvm.invariant.start intrinsic.
+ llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
+ llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID);
+
+ // Emit a call, with size -1 signifying the whole object.
+ llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, -1),
+ llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)};
+ CGF.Builder.CreateCall(InvariantStart, Args);
+}
+
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
llvm::Constant *DeclPtr,
bool PerformInit) {
@@ -111,7 +124,10 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
if (!T->isReferenceType()) {
if (PerformInit)
EmitDeclInit(*this, D, DeclPtr);
- EmitDeclDestroy(*this, D, DeclPtr);
+ if (CGM.isTypeConstant(D.getType(), true))
+ EmitDeclInvariant(*this, DeclPtr);
+ else
+ EmitDeclDestroy(*this, D, DeclPtr);
return;
}