Skip to content

Commit bba5ee5

Browse files
committed
[CodeGen] Add TBAA struct path info for array members
This enables the LLVM optimizer to view accesses to distinct struct members as independent, also for array members. For example, the following two stores no longer alias: struct S { int a[10]; int b; }; void test(S *p, int i) { p->a[i] = ...; p->b = ...; } Array members were already added to TBAA struct type nodes in commit 57493e2. Here, we extend a path tag for an array subscript expression.
1 parent d63c8fe commit bba5ee5

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4503,7 +4503,32 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
45034503
E->getType(), !getLangOpts().PointerOverflowDefined, SignedIndices,
45044504
E->getExprLoc(), &arrayType, E->getBase());
45054505
EltBaseInfo = ArrayLV.getBaseInfo();
4506-
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
4506+
if (!CGM.getCodeGenOpts().NewStructPathTBAA) {
4507+
// Since CodeGenTBAA::getTypeInfoHelper only handles array types for
4508+
// new struct path TBAA, we must a use a plain access.
4509+
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType());
4510+
} else if (ArrayLV.getTBAAInfo().isMayAlias()) {
4511+
EltTBAAInfo = TBAAAccessInfo::getMayAliasInfo();
4512+
} else if (ArrayLV.getTBAAInfo().isIncomplete()) {
4513+
EltTBAAInfo = CGM.getTBAAAccessInfo(E->getType());
4514+
} else {
4515+
// Extend struct path from base lvalue, similar to EmitLValueForField.
4516+
// If no base type has been assigned for the array access, then try to
4517+
// generate one.
4518+
EltTBAAInfo = ArrayLV.getTBAAInfo();
4519+
if (!EltTBAAInfo.BaseType) {
4520+
EltTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(ArrayLV.getType());
4521+
assert(!EltTBAAInfo.Offset &&
4522+
"Nonzero offset for an access with no base type!");
4523+
}
4524+
// The index into the array is a runtime value. We use the same struct
4525+
// path for all array elements (that of the element at index 0). So we
4526+
// set the access type and size, but do not have to adjust
4527+
// EltTBAAInfo.Offset.
4528+
EltTBAAInfo.AccessType = CGM.getTBAATypeInfo(E->getType());
4529+
EltTBAAInfo.Size =
4530+
getContext().getTypeSizeInChars(E->getType()).getQuantity();
4531+
}
45074532
} else {
45084533
// The base must be a pointer; emit it with an estimate of its alignment.
45094534
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);

clang/test/CodeGen/tbaa-array.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
struct A { int i; };
1111
struct B { A a[1]; };
1212
struct C { int i; int x[3]; };
13+
struct D { int n; int arr[]; }; // flexible array member
14+
extern int AA[]; // incomplete array type
1315

1416
int foo(B *b) {
1517
// CHECK-LABEL: _Z3fooP1B
@@ -28,16 +30,30 @@ int bar(C *c) {
2830

2931
int bar2(C *c) {
3032
// CHECK-NEW-LABEL: _Z4bar2P1C
31-
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
33+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_C_x:!.*]]
3234
return c->x[2];
3335
}
3436

3537
int bar3(C *c, int j) {
3638
// CHECK-NEW-LABEL: _Z4bar3P1Ci
37-
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
39+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_C_x]]
3840
return c->x[j];
3941
}
4042

43+
int bar4(D *d) {
44+
// CHECK-NEW-LABEL: _Z4bar4P1D
45+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
46+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
47+
return d->arr[d->n];
48+
}
49+
50+
int bar5(int j) {
51+
// CHECK-NEW-LABEL: _Z4bar5i
52+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
53+
// CHECK-NEW: load i32, {{.*}}, !tbaa [[TAG_int:!.*]]
54+
return AA[2] + AA[j];
55+
}
56+
4157
// CHECK-DAG: [[TAG_A_i]] = !{[[TYPE_A:!.*]], [[TYPE_int:!.*]], i64 0}
4258
// CHECK-DAG: [[TYPE_A]] = !{!"_ZTS1A", !{{.*}}, i64 0}
4359
// CHECK-DAG: [[TYPE_int]] = !{!"int", !{{.*}}, i64 0}
@@ -49,3 +65,4 @@ int bar3(C *c, int j) {
4965
// CHECK-NEW-DAG: [[TAG_A_i]] = !{[[TYPE_A]], [[TYPE_int]], i64 0, i64 4}
5066
// CHECK-NEW-DAG: [[TYPE_C:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1C", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 4, i64 12}
5167
// CHECK-NEW-DAG: [[TAG_C_i]] = !{[[TYPE_C:!.*]], [[TYPE_int:!.*]], i64 0, i64 4}
68+
// CHECK-NEW-DAG: [[TAG_C_x]] = !{[[TYPE_C:!.*]], [[TYPE_int:!.*]], i64 4, i64 4}

0 commit comments

Comments
 (0)