Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c116767

Browse filesBrowse files
committed
[AArch64] Change the coercion type of structs with pointer members.
The aim here is to avoid a ptrtoint->inttoptr round-trip throught the function argument whilst keeping the calling convention the same. Given a struct which is <= 128bits in size, which can only contain either 1 or 2 pointers, we convert to a ptr or [2 x ptr] as opposed to the old coercion that uses i64 or [2 x i64].
1 parent 6825a7d commit c116767
Copy full SHA for c116767

File tree

3 files changed

+31
-17
lines changed
Filter options

3 files changed

+31
-17
lines changed

‎clang/lib/CodeGen/Targets/AArch64.cpp

Copy file name to clipboardExpand all lines: clang/lib/CodeGen/Targets/AArch64.cpp
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,24 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
485485
}
486486
Size = llvm::alignTo(Size, Alignment);
487487

488+
// If the Aggregate is made up of pointers, use an array of pointers for the
489+
// coerced type. This prevents having to convert ptr2int->int2ptr through
490+
// the call, allowing alias analysis to produce better code.
491+
if (const RecordType *RT = Ty->getAs<RecordType>()) {
492+
if (const RecordDecl *RD = RT->getDecl()) {
493+
if (all_of(RD->fields(), [](FieldDecl *FD) {
494+
return FD->getType()->isPointerOrReferenceType();
495+
})) {
496+
assert((Size == 64 || Size == 128) &&
497+
"Expected a 64 or 128bit struct containing pointers");
498+
llvm::Type *PtrTy = llvm::PointerType::getUnqual(getVMContext());
499+
if (Size == 128)
500+
PtrTy = llvm::ArrayType::get(PtrTy, 2);
501+
return ABIArgInfo::getDirect(PtrTy);
502+
}
503+
}
504+
}
505+
488506
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
489507
// For aggregates with 16-byte alignment, we use i128.
490508
llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);

‎clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp

Copy file name to clipboardExpand all lines: clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp
+8-9Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ struct Sp {
55
int *x;
66
};
77
// CHECK-LABEL: define dso_local void @_Z2Tp2Sp(
8-
// CHECK-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
8+
// CHECK-SAME: ptr [[S_COERCE:%.*]]) #[[ATTR0:[0-9]+]] {
99
// CHECK-NEXT: [[ENTRY:.*:]]
1010
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SP:%.*]], align 8
1111
// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SP]], ptr [[S]], i32 0, i32 0
12-
// CHECK-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[S_COERCE]] to ptr
13-
// CHECK-NEXT: store ptr [[COERCE_VAL_IP]], ptr [[COERCE_DIVE]], align 8
12+
// CHECK-NEXT: store ptr [[S_COERCE]], ptr [[COERCE_DIVE]], align 8
1413
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SP]], ptr [[S]], i32 0, i32 0
1514
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8
1615
// CHECK-NEXT: store i32 1, ptr [[TMP0]], align 4
@@ -22,10 +21,10 @@ struct Spp {
2221
int *x, *y;
2322
};
2423
// CHECK-LABEL: define dso_local void @_Z3Tpp3Spp(
25-
// CHECK-SAME: [2 x i64] [[S_COERCE:%.*]]) #[[ATTR0]] {
24+
// CHECK-SAME: [2 x ptr] [[S_COERCE:%.*]]) #[[ATTR0]] {
2625
// CHECK-NEXT: [[ENTRY:.*:]]
2726
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SPP:%.*]], align 8
28-
// CHECK-NEXT: store [2 x i64] [[S_COERCE]], ptr [[S]], align 8
27+
// CHECK-NEXT: store [2 x ptr] [[S_COERCE]], ptr [[S]], align 8
2928
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPP]], ptr [[S]], i32 0, i32 0
3029
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8
3130
// CHECK-NEXT: store i32 1, ptr [[TMP0]], align 4
@@ -67,10 +66,10 @@ struct Srp {
6766
int &x, *y;
6867
};
6968
// CHECK-LABEL: define dso_local void @_Z3Trp3Srp(
70-
// CHECK-SAME: [2 x i64] [[S_COERCE:%.*]]) #[[ATTR0]] {
69+
// CHECK-SAME: [2 x ptr] [[S_COERCE:%.*]]) #[[ATTR0]] {
7170
// CHECK-NEXT: [[ENTRY:.*:]]
7271
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SRP:%.*]], align 8
73-
// CHECK-NEXT: store [2 x i64] [[S_COERCE]], ptr [[S]], align 8
72+
// CHECK-NEXT: store [2 x ptr] [[S_COERCE]], ptr [[S]], align 8
7473
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SRP]], ptr [[S]], i32 0, i32 0
7574
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8
7675
// CHECK-NEXT: store i32 1, ptr [[TMP0]], align 4
@@ -82,10 +81,10 @@ struct __attribute__((__packed__)) Spp_packed {
8281
int *x, *y;
8382
};
8483
// CHECK-LABEL: define dso_local void @_Z10Tpp_packed10Spp_packed(
85-
// CHECK-SAME: [2 x i64] [[S_COERCE:%.*]]) #[[ATTR0]] {
84+
// CHECK-SAME: [2 x ptr] [[S_COERCE:%.*]]) #[[ATTR0]] {
8685
// CHECK-NEXT: [[ENTRY:.*:]]
8786
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SPP_PACKED:%.*]], align 1
88-
// CHECK-NEXT: store [2 x i64] [[S_COERCE]], ptr [[S]], align 1
87+
// CHECK-NEXT: store [2 x ptr] [[S_COERCE]], ptr [[S]], align 1
8988
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPP_PACKED]], ptr [[S]], i32 0, i32 0
9089
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 1
9190
// CHECK-NEXT: store i32 1, ptr [[TMP0]], align 4

‎clang/test/CodeGenCXX/trivial_abi.cpp

Copy file name to clipboardExpand all lines: clang/test/CodeGenCXX/trivial_abi.cpp
+5-8Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,10 @@ struct D0 : B0, B1 {
6868

6969
Small D0::m0() { return {}; }
7070

71-
// CHECK: define{{.*}} void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
71+
// CHECK: define{{.*}} void @_Z14testParamSmall5Small(ptr %[[A_COERCE:.*]])
7272
// CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
7373
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[A]], i32 0, i32 0
74-
// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to ptr
75-
// CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8
74+
// CHECK: store ptr %[[A_COERCE]], ptr %[[COERCE_DIVE]], align 8
7675
// CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[A]])
7776
// CHECK: ret void
7877
// CHECK: }
@@ -101,8 +100,7 @@ Small testReturnSmall() {
101100
// CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN5SmallC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(8) %[[T]])
102101
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP]], i32 0, i32 0
103102
// CHECK: %[[V0:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8
104-
// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V0]] to i64
105-
// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
103+
// CHECK: call void @_Z14testParamSmall5Small(ptr %[[V0]])
106104
// CHECK: %[[CALL2:.*]] = call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[T]])
107105
// CHECK: ret void
108106
// CHECK: }
@@ -120,8 +118,7 @@ void testCallSmall0() {
120118
// CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8
121119
// CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP]], i32 0, i32 0
122120
// CHECK: %[[V0:.*]] = load ptr, ptr %[[COERCE_DIVE1]], align 8
123-
// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V0]] to i64
124-
// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
121+
// CHECK: call void @_Z14testParamSmall5Small(ptr %[[V0]])
125122
// CHECK: ret void
126123
// CHECK: }
127124

@@ -226,7 +223,7 @@ NonTrivial testReturnHasNonTrivial() {
226223
// CHECK: call noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[AGG_TMP]])
227224
// CHECK: invoke noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[AGG_TMP1]])
228225

229-
// CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}})
226+
// CHECK: call void @_Z20calleeExceptionSmall5SmallS_(ptr %{{.*}}, ptr %{{.*}})
230227
// CHECK-NEXT: ret void
231228

232229
// CHECK: landingpad { ptr, i32 }

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.