Skip to content

Commit c2f03fc

Browse files
authored
Add clang patches to make globals used for array initialization codegen constant (#440)
Backport llvm/llvm-project@7a85aa9 and llvm/llvm-project@4a2757d
1 parent 1ff9a7a commit c2f03fc

File tree

1 file changed

+269
-0
lines changed

1 file changed

+269
-0
lines changed
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
From df42d75b28f4e7a34cb231eab934b537b006a627 Mon Sep 17 00:00:00 2001
2+
From: Haonan Yang <[email protected]>
3+
Date: Wed, 17 May 2023 11:53:42 +0800
4+
Subject: [PATCH] Make globals used for array initialization codegen constant
5+
6+
This combines https://reviews.llvm.org/D145369 and https://reviews.llvm.org/D146211
7+
8+
1. Emit const globals with constexpr destructor as constant LLVM values
9+
This follows 2b4fa53 which made Clang not emit destructor calls for such
10+
objects. However, they would still not get emitted as constants since
11+
CodeGenModule::isTypeConstant() returns false if the destructor is
12+
constexpr. This change adds a param to make isTypeConstant() ignore the
13+
dtor, allowing the caller to check it instead.
14+
2. Make globals used for array initialization codegen constant
15+
As pointed out in D133835 these globals will never be written to
16+
(they're only used for trivially copyable types), so they can always be
17+
constant.
18+
---
19+
clang/lib/CodeGen/CGDecl.cpp | 12 ++++++++----
20+
clang/lib/CodeGen/CGDeclCXX.cpp | 4 +++-
21+
clang/lib/CodeGen/CGExpr.cpp | 2 +-
22+
clang/lib/CodeGen/CGExprAgg.cpp | 4 ++--
23+
clang/lib/CodeGen/CGExprConstant.cpp | 12 ++++++------
24+
clang/lib/CodeGen/CodeGenModule.cpp | 16 +++++++++-------
25+
clang/lib/CodeGen/CodeGenModule.h | 2 +-
26+
clang/lib/CodeGen/TargetInfo.cpp | 2 +-
27+
clang/test/CodeGen/init.c | 2 +-
28+
clang/test/CodeGen/label-array-aggregate-init.c | 2 +-
29+
clang/test/CodeGenCXX/const-init-cxx2a.cpp | 4 ++--
30+
11 files changed, 35 insertions(+), 27 deletions(-)
31+
32+
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
33+
index 60f1dba7c768..2e9e6927d0f8 100644
34+
--- a/clang/lib/CodeGen/CGDecl.cpp
35+
+++ b/clang/lib/CodeGen/CGDecl.cpp
36+
@@ -362,13 +362,15 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
37+
OldGV->eraseFromParent();
38+
}
39+
40+
- GV->setConstant(CGM.isTypeConstant(D.getType(), true));
41+
+ bool NeedsDtor =
42+
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
43+
+
44+
+ GV->setConstant(CGM.isTypeConstant(D.getType(), true, !NeedsDtor));
45+
GV->setInitializer(Init);
46+
47+
emitter.finalize(GV);
48+
49+
- if (D.needsDestruction(getContext()) == QualType::DK_cxx_destructor &&
50+
- HaveInsertPoint()) {
51+
+ if (NeedsDtor && HaveInsertPoint()) {
52+
// We have a constant initializer, but a nontrivial destructor. We still
53+
// need to perform a guarded "initialization" in order to register the
54+
// destructor.
55+
@@ -1426,10 +1428,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
56+
// emit it as a global instead.
57+
// Exception is if a variable is located in non-constant address space
58+
// in OpenCL.
59+
+ bool NeedsDtor =
60+
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
61+
if ((!getLangOpts().OpenCL ||
62+
Ty.getAddressSpace() == LangAS::opencl_constant) &&
63+
(CGM.getCodeGenOpts().MergeAllConstants && !NRVO &&
64+
- !isEscapingByRef && CGM.isTypeConstant(Ty, true))) {
65+
+ !isEscapingByRef && CGM.isTypeConstant(Ty, true, !NeedsDtor))) {
66+
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
67+
68+
// Signal this condition to later callbacks.
69+
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
70+
index 3baa0a080f5d..165547216844 100644
71+
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
72+
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
73+
@@ -210,9 +210,11 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
74+
&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
75+
PerformInit, this);
76+
}
77+
+ bool NeedsDtor =
78+
+ D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
79+
if (PerformInit)
80+
EmitDeclInit(*this, D, DeclAddr);
81+
- if (CGM.isTypeConstant(D.getType(), true))
82+
+ if (CGM.isTypeConstant(D.getType(), true, !NeedsDtor))
83+
EmitDeclInvariant(*this, D, DeclPtr);
84+
else
85+
EmitDeclDestroy(*this, D, DeclAddr);
86+
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
87+
index 8e0604181fb1..0ea23b4f5048 100644
88+
--- a/clang/lib/CodeGen/CGExpr.cpp
89+
+++ b/clang/lib/CodeGen/CGExpr.cpp
90+
@@ -382,7 +382,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
91+
QualType Ty = Inner->getType();
92+
if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
93+
(Ty->isArrayType() || Ty->isRecordType()) &&
94+
- CGF.CGM.isTypeConstant(Ty, true))
95+
+ CGF.CGM.isTypeConstant(Ty, true, false))
96+
if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) {
97+
if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) {
98+
auto AS = AddrSpace.getValue();
99+
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
100+
index 8de609a2ccd9..d9aad08429c4 100644
101+
--- a/clang/lib/CodeGen/CGExprAgg.cpp
102+
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
103+
@@ -498,8 +498,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
104+
if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) {
105+
auto GV = new llvm::GlobalVariable(
106+
CGM.getModule(), C->getType(),
107+
- CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true),
108+
- llvm::GlobalValue::PrivateLinkage, C, "constinit",
109+
+ /* isConstant= */ true, llvm::GlobalValue::PrivateLinkage, C,
110+
+ "constinit",
111+
/* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal,
112+
CGM.getContext().getTargetAddressSpace(AS));
113+
Emitter.finalize(GV);
114+
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
115+
index 46ed90a20264..7e065693829c 100644
116+
--- a/clang/lib/CodeGen/CGExprConstant.cpp
117+
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
118+
@@ -901,12 +901,12 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM,
119+
return ConstantAddress::invalid();
120+
}
121+
122+
- auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
123+
- CGM.isTypeConstant(E->getType(), true),
124+
- llvm::GlobalValue::InternalLinkage,
125+
- C, ".compoundliteral", nullptr,
126+
- llvm::GlobalVariable::NotThreadLocal,
127+
- CGM.getContext().getTargetAddressSpace(addressSpace));
128+
+ auto GV = new llvm::GlobalVariable(
129+
+ CGM.getModule(), C->getType(),
130+
+ CGM.isTypeConstant(E->getType(), true, false),
131+
+ llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr,
132+
+ llvm::GlobalVariable::NotThreadLocal,
133+
+ CGM.getContext().getTargetAddressSpace(addressSpace));
134+
emitter.finalize(GV);
135+
GV->setAlignment(Align.getAsAlign());
136+
CGM.setAddrOfConstantCompoundLiteral(E, GV);
137+
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
138+
index a735bdd814ed..ac44098ed782 100644
139+
--- a/clang/lib/CodeGen/CodeGenModule.cpp
140+
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
141+
@@ -2382,7 +2382,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
142+
// codegen for global variables, because they may be marked as threadprivate.
143+
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
144+
getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global) &&
145+
- !isTypeConstant(Global->getType(), false) &&
146+
+ !isTypeConstant(Global->getType(), false, false) &&
147+
!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Global))
148+
return false;
149+
150+
@@ -3413,8 +3413,9 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
151+
///
152+
/// If ExcludeCtor is true, the duration when the object's constructor runs
153+
/// will not be considered. The caller will need to verify that the object is
154+
-/// not written to during its construction.
155+
-bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
156+
+/// not written to during its construction. ExcludeDtor works similarly.
157+
+bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor,
158+
+ bool ExcludeDtor) {
159+
if (!Ty.isConstant(Context) && !Ty->isReferenceType())
160+
return false;
161+
162+
@@ -3422,7 +3423,7 @@ bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
163+
if (const CXXRecordDecl *Record
164+
= Context.getBaseElementType(Ty)->getAsCXXRecordDecl())
165+
return ExcludeCtor && !Record->hasMutableFields() &&
166+
- Record->hasTrivialDestructor();
167+
+ (Record->hasTrivialDestructor() || ExcludeDtor);
168+
}
169+
170+
return true;
171+
@@ -3532,7 +3533,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
172+
173+
// FIXME: This code is overly simple and should be merged with other global
174+
// handling.
175+
- GV->setConstant(isTypeConstant(D->getType(), false));
176+
+ GV->setConstant(isTypeConstant(D->getType(), false, false));
177+
178+
GV->setAlignment(getContext().getDeclAlign(D).getAsAlign());
179+
180+
@@ -4071,7 +4072,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
181+
182+
// If it is safe to mark the global 'constant', do so now.
183+
GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
184+
- isTypeConstant(D->getType(), true));
185+
+ isTypeConstant(D->getType(), true, true));
186+
187+
// If it is in a read-only section, mark it 'constant'.
188+
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
189+
@@ -5105,7 +5106,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
190+
emitter.emplace(*this);
191+
InitialValue = emitter->emitForInitializer(*Value, AddrSpace,
192+
MaterializedType);
193+
- Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
194+
+ Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/ Value,
195+
+ /*ExcludeDtor*/ false);
196+
Type = InitialValue->getType();
197+
} else {
198+
// No initializer, the initialization will be provided when we
199+
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
200+
index 115e754bb392..9c143df711ea 100644
201+
--- a/clang/lib/CodeGen/CodeGenModule.h
202+
+++ b/clang/lib/CodeGen/CodeGenModule.h
203+
@@ -754,7 +754,7 @@ public:
204+
return getTBAAAccessInfo(AccessType);
205+
}
206+
207+
- bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);
208+
+ bool isTypeConstant(QualType QTy, bool ExcludeCtor, bool ExcludeDtor);
209+
210+
bool isPaddedAtomicType(QualType type);
211+
bool isPaddedAtomicType(const AtomicType *type);
212+
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
213+
index e2380f5581ca..a3a0042ba0bd 100644
214+
--- a/clang/lib/CodeGen/TargetInfo.cpp
215+
+++ b/clang/lib/CodeGen/TargetInfo.cpp
216+
@@ -8137,7 +8137,7 @@ AMDGPUTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
217+
if (AddrSpace != LangAS::Default)
218+
return AddrSpace;
219+
220+
- if (CGM.isTypeConstant(D->getType(), false)) {
221+
+ if (CGM.isTypeConstant(D->getType(), false, false)) {
222+
if (auto ConstAS = CGM.getTarget().getConstantAddressSpace())
223+
return ConstAS.getValue();
224+
}
225+
diff --git a/clang/test/CodeGen/init.c b/clang/test/CodeGen/init.c
226+
index 71aba39b1244..a1ce9e6779b3 100644
227+
--- a/clang/test/CodeGen/init.c
228+
+++ b/clang/test/CodeGen/init.c
229+
@@ -10,7 +10,7 @@ unsigned v2[2][3] = {[0 ... 1][0 ... 1] = 2222, 3333};
230+
231+
// 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] }] }],
232+
// 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]],
233+
-// 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
234+
+// 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
235+
236+
void f1() {
237+
// Scalars in braces.
238+
diff --git a/clang/test/CodeGen/label-array-aggregate-init.c b/clang/test/CodeGen/label-array-aggregate-init.c
239+
index 5cefd8d270c0..3175c2a6a292 100644
240+
--- a/clang/test/CodeGen/label-array-aggregate-init.c
241+
+++ b/clang/test/CodeGen/label-array-aggregate-init.c
242+
@@ -1,6 +1,6 @@
243+
// RUN: %clang -cc1 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s
244+
245+
-// CHECK: @constinit = private global [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null]
246+
+// CHECK: @constinit = private constant [3 x i8*] [i8* blockaddress(@main, %L), i8* null, i8* null]
247+
248+
void receivePtrs(void **);
249+
250+
diff --git a/clang/test/CodeGenCXX/const-init-cxx2a.cpp b/clang/test/CodeGenCXX/const-init-cxx2a.cpp
251+
index 1195b912c255..abe3eb2d0c60 100644
252+
--- a/clang/test/CodeGenCXX/const-init-cxx2a.cpp
253+
+++ b/clang/test/CodeGenCXX/const-init-cxx2a.cpp
254+
@@ -11,10 +11,10 @@ struct B {
255+
constexpr ~B() { n *= 5; }
256+
int n = 123;
257+
};
258+
-// CHECK: @b = global {{.*}} i32 123
259+
+// CHECK: @b = constant {{.*}} i32 123
260+
extern constexpr B b = B();
261+
262+
-// CHECK: @_ZL1c = internal global {{.*}} i32 123
263+
+// CHECK: @_ZL1c = internal constant {{.*}} i32 123
264+
const B c;
265+
int use_c() { return c.n; }
266+
267+
--
268+
2.31.1
269+

0 commit comments

Comments
 (0)