forked from intel/opencl-clang
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add clang patches to make globals used for array initialization codeg…
…en constant (intel#441) Backport llvm/llvm-project@7a85aa9 and llvm/llvm-project@4a2757d
- Loading branch information
Showing
1 changed file
with
268 additions
and
0 deletions.
There are no files selected for viewing
268 changes: 268 additions & 0 deletions
268
patches/clang/0008-Make-globals-used-for-array-initialization-codegen-c.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,268 @@ | ||
From 1ad05dc3517a7cf8224c2866c0f7fb09246d4ee3 Mon Sep 17 00:00:00 2001 | ||
From: Haonan Yang <haonan.yang@intel.com> | ||
Date: Wed, 17 May 2023 12:48:42 +0800 | ||
Subject: [PATCH] Make globals used for array initialization codegen constant | ||
|
||
This combines https://reviews.llvm.org/D146211 and https://reviews.llvm.org/D145369 | ||
|
||
1. Emit const globals with constexpr destructor as constant LLVM values | ||
This follows 2b4fa53 which made Clang not emit destructor calls for such | ||
objects. However, they would still not get emitted as constants since | ||
CodeGenModule::isTypeConstant() returns false if the destructor is | ||
constexpr. This change adds a param to make isTypeConstant() ignore the | ||
dtor, allowing the caller to check it instead. | ||
2. Make globals used for array initialization codegen constant | ||
As pointed out in D133835 these globals will never be written to | ||
(they're only used for trivially copyable types), so they can always be | ||
constant. | ||
--- | ||
clang/lib/CodeGen/CGDecl.cpp | 11 +++++++---- | ||
clang/lib/CodeGen/CGDeclCXX.cpp | 4 +++- | ||
clang/lib/CodeGen/CGExpr.cpp | 2 +- | ||
clang/lib/CodeGen/CGExprAgg.cpp | 4 ++-- | ||
clang/lib/CodeGen/CGExprConstant.cpp | 12 ++++++------ | ||
clang/lib/CodeGen/CodeGenModule.cpp | 16 +++++++++------- | ||
clang/lib/CodeGen/CodeGenModule.h | 2 +- | ||
clang/lib/CodeGen/TargetInfo.cpp | 2 +- | ||
clang/test/CodeGen/init.c | 2 +- | ||
clang/test/CodeGen/label-array-aggregate-init.c | 2 +- | ||
clang/test/CodeGenCXX/const-init-cxx2a.cpp | 4 ++-- | ||
11 files changed, 34 insertions(+), 27 deletions(-) | ||
|
||
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp | ||
index 1729c7ed3c31..76a8d24af147 100644 | ||
--- a/clang/lib/CodeGen/CGDecl.cpp | ||
+++ b/clang/lib/CodeGen/CGDecl.cpp | ||
@@ -367,13 +367,14 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, | ||
OldGV->eraseFromParent(); | ||
} | ||
|
||
- GV->setConstant(CGM.isTypeConstant(D.getType(), true)); | ||
+ bool NeedsDtor = | ||
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; | ||
+ GV->setConstant(CGM.isTypeConstant(D.getType(), true, !NeedsDtor)); | ||
GV->setInitializer(Init); | ||
|
||
emitter.finalize(GV); | ||
|
||
- if (D.needsDestruction(getContext()) == QualType::DK_cxx_destructor && | ||
- HaveInsertPoint()) { | ||
+ if (NeedsDtor && HaveInsertPoint()) { | ||
// We have a constant initializer, but a nontrivial destructor. We still | ||
// need to perform a guarded "initialization" in order to register the | ||
// destructor. | ||
@@ -1433,10 +1434,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { | ||
// emit it as a global instead. | ||
// Exception is if a variable is located in non-constant address space | ||
// in OpenCL. | ||
+ bool NeedsDtor = | ||
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; | ||
if ((!getLangOpts().OpenCL || | ||
Ty.getAddressSpace() == LangAS::opencl_constant) && | ||
(CGM.getCodeGenOpts().MergeAllConstants && !NRVO && | ||
- !isEscapingByRef && CGM.isTypeConstant(Ty, true))) { | ||
+ !isEscapingByRef && CGM.isTypeConstant(Ty, true, !NeedsDtor))) { | ||
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); | ||
|
||
// Signal this condition to later callbacks. | ||
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp | ||
index 5a8500364295..7fd77d17e4b0 100644 | ||
--- a/clang/lib/CodeGen/CGDeclCXX.cpp | ||
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp | ||
@@ -211,9 +211,11 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, | ||
&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), | ||
PerformInit, this); | ||
} | ||
+ bool NeedsDtor = | ||
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor; | ||
if (PerformInit) | ||
EmitDeclInit(*this, D, DeclAddr); | ||
- if (CGM.isTypeConstant(D.getType(), true)) | ||
+ if (CGM.isTypeConstant(D.getType(), true, !NeedsDtor)) | ||
EmitDeclInvariant(*this, D, DeclPtr); | ||
else | ||
EmitDeclDestroy(*this, D, DeclAddr); | ||
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp | ||
index 9e8770573d70..2abf472e499d 100644 | ||
--- a/clang/lib/CodeGen/CGExpr.cpp | ||
+++ b/clang/lib/CodeGen/CGExpr.cpp | ||
@@ -394,7 +394,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, | ||
QualType Ty = Inner->getType(); | ||
if (CGF.CGM.getCodeGenOpts().MergeAllConstants && | ||
(Ty->isArrayType() || Ty->isRecordType()) && | ||
- CGF.CGM.isTypeConstant(Ty, true)) | ||
+ CGF.CGM.isTypeConstant(Ty, true, false)) | ||
if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) { | ||
if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) { | ||
auto AS = AddrSpace.getValue(); | ||
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp | ||
index fb96d70732e8..10b8ba7f5301 100644 | ||
--- a/clang/lib/CodeGen/CGExprAgg.cpp | ||
+++ b/clang/lib/CodeGen/CGExprAgg.cpp | ||
@@ -502,8 +502,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, | ||
if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) { | ||
auto GV = new llvm::GlobalVariable( | ||
CGM.getModule(), C->getType(), | ||
- CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true), | ||
- llvm::GlobalValue::PrivateLinkage, C, "constinit", | ||
+ /* isConstant= */ true, llvm::GlobalValue::PrivateLinkage, C, | ||
+ "constinit", | ||
/* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal, | ||
CGM.getContext().getTargetAddressSpace(AS)); | ||
Emitter.finalize(GV); | ||
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp | ||
index c6b2930faece..48c5911cd42a 100644 | ||
--- a/clang/lib/CodeGen/CGExprConstant.cpp | ||
+++ b/clang/lib/CodeGen/CGExprConstant.cpp | ||
@@ -912,12 +912,12 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, | ||
return ConstantAddress::invalid(); | ||
} | ||
|
||
- auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), | ||
- CGM.isTypeConstant(E->getType(), true), | ||
- llvm::GlobalValue::InternalLinkage, | ||
- C, ".compoundliteral", nullptr, | ||
- llvm::GlobalVariable::NotThreadLocal, | ||
- CGM.getContext().getTargetAddressSpace(addressSpace)); | ||
+ auto GV = new llvm::GlobalVariable( | ||
+ CGM.getModule(), C->getType(), | ||
+ CGM.isTypeConstant(E->getType(), true, false), | ||
+ llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr, | ||
+ llvm::GlobalVariable::NotThreadLocal, | ||
+ CGM.getContext().getTargetAddressSpace(addressSpace)); | ||
emitter.finalize(GV); | ||
GV->setAlignment(Align.getAsAlign()); | ||
CGM.setAddrOfConstantCompoundLiteral(E, GV); | ||
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp | ||
index 4ae8ce7e5ccf..a596607e5370 100644 | ||
--- a/clang/lib/CodeGen/CodeGenModule.cpp | ||
+++ b/clang/lib/CodeGen/CodeGenModule.cpp | ||
@@ -2430,7 +2430,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { | ||
// codegen for global variables, because they may be marked as threadprivate. | ||
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && | ||
getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) && | ||
- !isTypeConstant(Global->getType(), false) && | ||
+ !isTypeConstant(Global->getType(), false, false) && | ||
!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global)) | ||
return false; | ||
|
||
@@ -3436,8 +3436,9 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, | ||
/// | ||
/// If ExcludeCtor is true, the duration when the object's constructor runs | ||
/// will not be considered. The caller will need to verify that the object is | ||
-/// not written to during its construction. | ||
-bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { | ||
+/// not written to during its construction. ExcludeDtor works similarly. | ||
+bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor, | ||
+ bool ExcludeDtor) { | ||
if (!Ty.isConstant(Context) && !Ty->isReferenceType()) | ||
return false; | ||
|
||
@@ -3445,7 +3446,7 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { | ||
if (const CXXRecordDecl *Record | ||
= Context.getBaseElementType(Ty)->getAsCXXRecordDecl()) | ||
return ExcludeCtor && !Record->hasMutableFields() && | ||
- Record->hasTrivialDestructor(); | ||
+ (Record->hasTrivialDestructor() || ExcludeDtor); | ||
} | ||
|
||
return true; | ||
@@ -3555,7 +3556,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, | ||
|
||
// FIXME: This code is overly simple and should be merged with other global | ||
// handling. | ||
- GV->setConstant(isTypeConstant(D->getType(), false)); | ||
+ GV->setConstant(isTypeConstant(D->getType(), false, false)); | ||
|
||
GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); | ||
|
||
@@ -4123,7 +4124,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, | ||
|
||
// If it is safe to mark the global 'constant', do so now. | ||
GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor && | ||
- isTypeConstant(D->getType(), true)); | ||
+ isTypeConstant(D->getType(), true, true)); | ||
|
||
// If it is in a read-only section, mark it 'constant'. | ||
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) { | ||
@@ -5160,7 +5161,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( | ||
emitter.emplace(*this); | ||
InitialValue = emitter->emitForInitializer(*Value, AddrSpace, | ||
MaterializedType); | ||
- Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); | ||
+ Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/ Value, | ||
+ /*ExcludeDtor*/ false); | ||
Type = InitialValue->getType(); | ||
} else { | ||
// No initializer, the initialization will be provided when we | ||
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h | ||
index a6c4a1f7b278..b4021d587eee 100644 | ||
--- a/clang/lib/CodeGen/CodeGenModule.h | ||
+++ b/clang/lib/CodeGen/CodeGenModule.h | ||
@@ -758,7 +758,7 @@ public: | ||
return getTBAAAccessInfo(AccessType); | ||
} | ||
|
||
- bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); | ||
+ bool isTypeConstant(QualType QTy, bool ExcludeCtor, bool ExcludeDtor); | ||
|
||
bool isPaddedAtomicType(QualType type); | ||
bool isPaddedAtomicType(const AtomicType *type); | ||
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp | ||
index a061651d8b21..e41f1620939d 100644 | ||
--- a/clang/lib/CodeGen/TargetInfo.cpp | ||
+++ b/clang/lib/CodeGen/TargetInfo.cpp | ||
@@ -9059,7 +9059,7 @@ AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, | ||
if (AddrSpace != LangAS::Default) | ||
return AddrSpace; | ||
|
||
- if (CGM.isTypeConstant(D->getType(), false)) { | ||
+ if (CGM.isTypeConstant(D->getType(), false, false)) { | ||
if (auto ConstAS = CGM.getTarget().getConstantAddressSpace()) | ||
return ConstAS.getValue(); | ||
} | ||
diff --git a/clang/test/CodeGen/init.c b/clang/test/CodeGen/init.c | ||
index 71aba39b1244..a1ce9e6779b3 100644 | ||
--- a/clang/test/CodeGen/init.c | ||
+++ b/clang/test/CodeGen/init.c | ||
@@ -10,7 +10,7 @@ unsigned v2[2][3] = {[0 ... 1][0 ... 1] = 2222, 3333}; | ||
|
||
// CHECK-DAG: [1 x %struct.M] [%struct.M { [2 x %struct.I] [%struct.I { [3 x i32] [i32 4, i32 4, i32 0] }, %struct.I { [3 x i32] [i32 4, i32 4, i32 5] }] }], | ||
// CHECK-DAG: [2 x [3 x i32]] {{[[][[]}}3 x i32] [i32 2222, i32 2222, i32 0], [3 x i32] [i32 2222, i32 2222, i32 3333]], | ||
-// CHECK-DAG: [[INIT14:.*]] = private global [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4 | ||
+// CHECK-DAG: [[INIT14:.*]] = private constant [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4 | ||
|
||
void f1() { | ||
// Scalars in braces. | ||
diff --git a/clang/test/CodeGen/label-array-aggregate-init.c b/clang/test/CodeGen/label-array-aggregate-init.c | ||
index 5cefd8d270c0..3175c2a6a292 100644 | ||
--- a/clang/test/CodeGen/label-array-aggregate-init.c | ||
+++ b/clang/test/CodeGen/label-array-aggregate-init.c | ||
@@ -1,6 +1,6 @@ | ||
// RUN: %clang -cc1 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s | ||
|
||
-// CHECK: @constinit = private global [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null] | ||
+// CHECK: @constinit = private constant [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null] | ||
|
||
void receivePtrs(void **); | ||
|
||
diff --git a/clang/test/CodeGenCXX/const-init-cxx2a.cpp b/clang/test/CodeGenCXX/const-init-cxx2a.cpp | ||
index 1195b912c255..abe3eb2d0c60 100644 | ||
--- a/clang/test/CodeGenCXX/const-init-cxx2a.cpp | ||
+++ b/clang/test/CodeGenCXX/const-init-cxx2a.cpp | ||
@@ -11,10 +11,10 @@ struct B { | ||
constexpr ~B() { n *= 5; } | ||
int n = 123; | ||
}; | ||
-// CHECK: @b = global {{.*}} i32 123 | ||
+// CHECK: @b = constant {{.*}} i32 123 | ||
extern constexpr B b = B(); | ||
|
||
-// CHECK: @_ZL1c = internal global {{.*}} i32 123 | ||
+// CHECK: @_ZL1c = internal constant {{.*}} i32 123 | ||
const B c; | ||
int use_c() { return c.n; } | ||
|
||
-- | ||
2.31.1 | ||
|