Skip to content

Commit 79f0dcc

Browse files
authored
[Clang][CodeGen] Add metadata for load from reference (#98746)
This patch adds `!nonnull/!align` for load from reference to improve codegen.
1 parent 18fced4 commit 79f0dcc

29 files changed

+4827
-4713
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ C++ Specific Potentially Breaking Changes
6161
- A workaround for libstdc++4.7 has been removed. Note that 4.8.3 remains the oldest
6262
supported libstdc++ version.
6363

64+
- Added ``!nonnull/!align`` metadata to load of references for better codegen.
65+
6466
ABI Changes in This Version
6567
---------------------------
6668

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,9 +2938,31 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
29382938
llvm::LoadInst *Load =
29392939
Builder.CreateLoad(RefLVal.getAddress(), RefLVal.isVolatile());
29402940
CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo());
2941-
return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(),
2942-
CharUnits(), /*ForPointeeType=*/true,
2943-
PointeeBaseInfo, PointeeTBAAInfo);
2941+
QualType PTy = RefLVal.getType()->getPointeeType();
2942+
CharUnits Align = CGM.getNaturalTypeAlignment(
2943+
PTy, PointeeBaseInfo, PointeeTBAAInfo, /*ForPointeeType=*/true);
2944+
if (!PTy->isIncompleteType()) {
2945+
llvm::LLVMContext &Ctx = getLLVMContext();
2946+
llvm::MDBuilder MDB(Ctx);
2947+
// Emit !nonnull metadata
2948+
if (CGM.getTypes().getTargetAddressSpace(PTy) == 0 &&
2949+
!CGM.getCodeGenOpts().NullPointerIsValid)
2950+
Load->setMetadata(llvm::LLVMContext::MD_nonnull,
2951+
llvm::MDNode::get(Ctx, {}));
2952+
// Emit !align metadata
2953+
if (PTy->isObjectType()) {
2954+
auto AlignVal = Align.getQuantity();
2955+
if (AlignVal > 1) {
2956+
Load->setMetadata(
2957+
llvm::LLVMContext::MD_align,
2958+
llvm::MDNode::get(Ctx, MDB.createConstant(llvm::ConstantInt::get(
2959+
Builder.getInt64Ty(), AlignVal))));
2960+
}
2961+
}
2962+
}
2963+
return makeNaturalAddressForPointer(Load, PTy, Align,
2964+
/*ForPointeeType=*/true, PointeeBaseInfo,
2965+
PointeeTBAAInfo);
29442966
}
29452967

29462968
LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -std=c++11 -O1 -disable-llvm-passes %s -o - | FileCheck %s
3+
4+
struct alignas(32) F { int x; };
5+
6+
struct S {
7+
char &a;
8+
int &b;
9+
F &c;
10+
};
11+
12+
// CHECK-LABEL: define dso_local void @_Z4testR1S(
13+
// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[S:%.*]]) #[[ATTR0:[0-9]+]] {
14+
// CHECK-NEXT: [[ENTRY:.*:]]
15+
// CHECK-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
16+
// CHECK-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8, !tbaa [[TBAA2:![0-9]+]]
17+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !tbaa [[TBAA2]], !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]]
18+
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 0
19+
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A]], align 8, !tbaa [[TBAA9:![0-9]+]], !nonnull [[META7]]
20+
// CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1, !tbaa [[TBAA14:![0-9]+]]
21+
// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !tbaa [[TBAA2]], !nonnull [[META7]], !align [[META8]]
22+
// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
23+
// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[B]], align 8, !tbaa [[TBAA15:![0-9]+]], !nonnull [[META7]], !align [[META16:![0-9]+]]
24+
// CHECK-NEXT: store i32 0, ptr [[TMP3]], align 4, !tbaa [[TBAA17:![0-9]+]]
25+
// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !tbaa [[TBAA2]], !nonnull [[META7]], !align [[META8]]
26+
// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 2
27+
// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[C]], align 8, !tbaa [[TBAA19:![0-9]+]], !nonnull [[META7]], !align [[META20:![0-9]+]]
28+
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_F:%.*]], ptr [[TMP5]], i32 0, i32 0
29+
// CHECK-NEXT: store i32 0, ptr [[X]], align 32, !tbaa [[TBAA21:![0-9]+]]
30+
// CHECK-NEXT: ret void
31+
//
32+
void test(S &s) {
33+
s.a = 0;
34+
s.b = 0;
35+
s.c.x = 0;
36+
}
37+
38+
struct A { alignas(32) char x[32]; };
39+
struct B : virtual A { long long b; char c; };
40+
extern B& b;
41+
extern B (&bb)[2];
42+
// CHECK-LABEL: define dso_local void @_Z13test_externalv(
43+
// CHECK-SAME: ) #[[ATTR0]] {
44+
// CHECK-NEXT: [[ENTRY:.*:]]
45+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @b, align 8, !tbaa [[TBAA23:![0-9]+]], !nonnull [[META7]], !align [[META8]]
46+
// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_B:%.*]], ptr [[TMP0]], i32 0, i32 2
47+
// CHECK-NEXT: store i8 0, ptr [[C]], align 8, !tbaa [[TBAA25:![0-9]+]]
48+
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @bb, align 8, !tbaa [[TBAA23]], !nonnull [[META7]], !align [[META20]]
49+
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x %struct.B], ptr [[TMP1]], i64 0, i64 0
50+
// CHECK-NEXT: [[C1:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[ARRAYIDX]], i32 0, i32 2
51+
// CHECK-NEXT: store i8 0, ptr [[C1]], align 16, !tbaa [[TBAA25]]
52+
// CHECK-NEXT: ret void
53+
//
54+
void test_external() {
55+
b.c = 0; // align 8
56+
bb[0].c = 0; // align 32
57+
}
58+
59+
// CHECK-LABEL: define dso_local noundef ptr @_Z15test_deref_onlyR1B(
60+
// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(17) [[S:%.*]]) #[[ATTR0]] {
61+
// CHECK-NEXT: [[ENTRY:.*:]]
62+
// CHECK-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
63+
// CHECK-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8, !tbaa [[TBAA23]]
64+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !tbaa [[TBAA23]], !nonnull [[META7]], !align [[META8]]
65+
// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_B:%.*]], ptr [[TMP0]], i32 0, i32 2
66+
// CHECK-NEXT: ret ptr [[C]]
67+
//
68+
char* test_deref_only(B &s) {
69+
return &s.c;
70+
}
71+
//.
72+
// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
73+
// CHECK: [[META3]] = !{!"p1 _ZTS1S", [[META4:![0-9]+]], i64 0}
74+
// CHECK: [[META4]] = !{!"any pointer", [[META5:![0-9]+]], i64 0}
75+
// CHECK: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0}
76+
// CHECK: [[META6]] = !{!"Simple C++ TBAA"}
77+
// CHECK: [[META7]] = !{}
78+
// CHECK: [[META8]] = !{i64 8}
79+
// CHECK: [[TBAA9]] = !{[[META10:![0-9]+]], [[META11:![0-9]+]], i64 0}
80+
// CHECK: [[META10]] = !{!"_ZTS1S", [[META11]], i64 0, [[META12:![0-9]+]], i64 8, [[META13:![0-9]+]], i64 16}
81+
// CHECK: [[META11]] = !{!"p1 omnipotent char", [[META4]], i64 0}
82+
// CHECK: [[META12]] = !{!"p1 int", [[META4]], i64 0}
83+
// CHECK: [[META13]] = !{!"p1 _ZTS1F", [[META4]], i64 0}
84+
// CHECK: [[TBAA14]] = !{[[META5]], [[META5]], i64 0}
85+
// CHECK: [[TBAA15]] = !{[[META10]], [[META12]], i64 8}
86+
// CHECK: [[META16]] = !{i64 4}
87+
// CHECK: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0}
88+
// CHECK: [[META18]] = !{!"int", [[META5]], i64 0}
89+
// CHECK: [[TBAA19]] = !{[[META10]], [[META13]], i64 16}
90+
// CHECK: [[META20]] = !{i64 32}
91+
// CHECK: [[TBAA21]] = !{[[META22:![0-9]+]], [[META18]], i64 0}
92+
// CHECK: [[META22]] = !{!"_ZTS1F", [[META18]], i64 0}
93+
// CHECK: [[TBAA23]] = !{[[META24:![0-9]+]], [[META24]], i64 0}
94+
// CHECK: [[META24]] = !{!"p1 _ZTS1B", [[META4]], i64 0}
95+
// CHECK: [[TBAA25]] = !{[[META26:![0-9]+]], [[META5]], i64 16}
96+
// CHECK: [[META26]] = !{!"_ZTS1B", [[META27:![0-9]+]], i64 8, [[META5]], i64 16}
97+
// CHECK: [[META27]] = !{!"long long", [[META5]], i64 0}
98+
//.

clang/test/CodeGenCXX/matrix-type-operators.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,11 @@ void insert(MyMatrix<EltTy, Rows, Columns> &Mat, EltTy e, unsigned i, unsigned j
215215

216216
void test_insert_template1(MyMatrix<unsigned, 2, 2> &Mat, unsigned e, unsigned i, unsigned j) {
217217
// CHECK-LABEL: @_Z21test_insert_template1R8MyMatrixIjLj2ELj2EEjjj(
218-
// NOOPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8{{$}}
218+
// NOOPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8,
219219
// NOOPT-NEXT: [[E:%.*]] = load i32, ptr %e.addr, align 4{{$}}
220220
// NOOPT-NEXT: [[I:%.*]] = load i32, ptr %i.addr, align 4{{$}}
221221
// NOOPT-NEXT: [[J:%.*]] = load i32, ptr %j.addr, align 4{{$}}
222-
// OPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8, !tbaa !{{[0-9]+}}{{$}}
222+
// OPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8, !tbaa !{{[0-9]+}},
223223
// OPT-NEXT: [[E:%.*]] = load i32, ptr %e.addr, align 4, !tbaa !{{[0-9]+}}{{$}}
224224
// OPT-NEXT: [[I:%.*]] = load i32, ptr %i.addr, align 4, !tbaa !{{[0-9]+}}{{$}}
225225
// OPT-NEXT: [[J:%.*]] = load i32, ptr %j.addr, align 4, !tbaa !{{[0-9]+}}{{$}}
@@ -249,9 +249,9 @@ void test_insert_template1(MyMatrix<unsigned, 2, 2> &Mat, unsigned e, unsigned i
249249

250250
void test_insert_template2(MyMatrix<float, 3, 8> &Mat, float e) {
251251
// CHECK-LABEL: @_Z21test_insert_template2R8MyMatrixIfLj3ELj8EEf(
252-
// NOOPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8{{$}}
252+
// NOOPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8,
253253
// NOOPT-NEXT: [[E:%.*]] = load float, ptr %e.addr, align 4{{$}}
254-
// OPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8, !tbaa !{{[0-9]+}}{{$}}
254+
// OPT: [[MAT_ADDR:%.*]] = load ptr, ptr %Mat.addr, align 8, !tbaa !{{[0-9]+}},
255255
// OPT-NEXT: [[E:%.*]] = load float, ptr %e.addr, align 4, !tbaa !{{[0-9]+}}{{$}}
256256
// CHECK-NEXT: call void @_Z6insertIfLj3ELj8EEvR8MyMatrixIT_XT0_EXT1_EES1_jj(ptr noundef nonnull align 4 dereferenceable(96) [[MAT_ADDR]], float noundef [[E]], i32 noundef 2, i32 noundef 5)
257257
// CHECK-NEXT: ret void
@@ -350,11 +350,11 @@ double extract_IntWrapper_idx(double4x4 &m, IntWrapper i, UnsignedWrapper j) {
350350
// CHECK-NEXT: [[J_SUB_EXT:%.*]] = zext i32 [[J_SUB]] to i64
351351
// CHECK-NEXT: [[IDX1:%.*]] = mul i64 [[J_SUB_EXT]], 4
352352
// CHECK-NEXT: [[IDX2:%.*]] = add i64 [[IDX1]], [[I_ADD_EXT]]
353-
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8{{$}}
353+
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8,
354354
// NOOPT-NEXT: [[MAT:%.*]] = load <16 x double>, ptr [[MAT_ADDR]], align 8{{$}}
355355
// OPT-NEXT: [[CMP:%.*]] = icmp ult i64 [[IDX2]], 16
356356
// OPT-NEXT: call void @llvm.assume(i1 [[CMP]])
357-
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}}{{$}}
357+
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}},
358358
// OPT-NEXT: [[MAT:%.*]] = load <16 x double>, ptr [[MAT_ADDR]], align 8, !tbaa !{{[0-9]+}}{{$}}
359359
// CHECK-NEXT: [[MATEXT:%.*]] = extractelement <16 x double> [[MAT]], i64 [[IDX2]]
360360
// CHECK-NEXT: ret double [[MATEXT]]
@@ -381,8 +381,8 @@ void test_constexpr1(matrix_type<float, 4, 4> &m) {
381381
// OPT: [[MAT:%.*]] = load <16 x float>, ptr {{.*}}, align 4, !tbaa !{{[0-9]+}}{{$}}
382382
// CHECK-NEXT: [[IM:%.*]] = call noundef <16 x float> @_ZNK13identmatrix_tcvu11matrix_typeIXT0_EXT0_ET_EIfLj4EEEv(ptr {{[^,]*}} @_ZL11identmatrix)
383383
// CHECK-NEXT: [[ADD:%.*]] = fadd <16 x float> [[MAT]], [[IM]]
384-
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8{{$}}
385-
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}}{{$}}
384+
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8,
385+
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}},
386386
// CHECK-NEXT: store <16 x float> [[ADD]], ptr [[MAT_ADDR]], align 4
387387
// CHECK-NEXT: ret voi
388388

@@ -412,8 +412,8 @@ void test_constexpr2(matrix_type<int, 5, 5> &m) {
412412
// OPT: [[MAT:%.*]] = load <25 x i32>, ptr {{.*}}, align 4, !tbaa !{{[0-9]+}}{{$}}
413413
// CHECK-NEXT: [[SUB:%.*]] = sub <25 x i32> [[IM]], [[MAT]]
414414
// CHECK-NEXT: [[SUB2:%.*]] = add <25 x i32> [[SUB]], splat (i32 1)
415-
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8{{$}}
416-
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}}{{$}}
415+
// NOOPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8,
416+
// OPT-NEXT: [[MAT_ADDR:%.*]] = load ptr, ptr %m.addr, align 8, !tbaa !{{[0-9]+}},
417417
// CHECK-NEXT: store <25 x i32> [[SUB2]], ptr [[MAT_ADDR]], align 4
418418
// CHECK-NEXT: ret void
419419
//

clang/test/CodeGenCXX/reference-field.cpp

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)