Skip to content

Commit 9ff01ee

Browse files
committed
Add empty test and change recursion
1 parent c507cb7 commit 9ff01ee

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
489489
// If the Aggregate is made up of pointers, use an array of pointers for the
490490
// coerced type. This prevents having to convert ptr2int->int2ptr through
491491
// the call, allowing alias analysis to produce better code.
492-
std::function<bool(QualType Ty)> ContainsOnlyPointers = [&](QualType Ty) {
492+
auto ContainsOnlyPointers = [&](const auto &Self, QualType Ty) {
493493
if (isEmptyRecord(getContext(), Ty, true))
494494
return false;
495495
const RecordType *RT = Ty->getAs<RecordType>();
@@ -498,7 +498,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
498498
const RecordDecl *RD = RT->getDecl();
499499
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
500500
for (const auto &I : CXXRD->bases())
501-
if (!ContainsOnlyPointers(I.getType()))
501+
if (!Self(Self, I.getType()))
502502
return false;
503503
}
504504
return all_of(RD->fields(), [&](FieldDecl *FD) {
@@ -507,21 +507,16 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
507507
FDTy = getContext().getBaseElementType(FDTy);
508508
return (FDTy->isPointerOrReferenceType() &&
509509
getContext().getTypeSize(FDTy) == 64) ||
510-
ContainsOnlyPointers(FDTy);
510+
Self(Self, FDTy);
511511
});
512512
};
513-
if (Alignment <= 64 && ContainsOnlyPointers(Ty)) {
514-
assert((Size == 64 || Size == 128) &&
515-
"Expected a 64 or 128bit struct containing pointers");
516-
llvm::Type *PtrTy = llvm::PointerType::getUnqual(getVMContext());
517-
if (Size == 128)
518-
PtrTy = llvm::ArrayType::get(PtrTy, 2);
519-
return ABIArgInfo::getDirect(PtrTy);
520-
}
521513

522514
// We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
523515
// For aggregates with 16-byte alignment, we use i128.
524516
llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);
517+
if ((Size == 64 || Size == 128) && Alignment == 64 &&
518+
ContainsOnlyPointers(ContainsOnlyPointers, Ty))
519+
BaseTy = llvm::PointerType::getUnqual(getVMContext());
525520
return ABIArgInfo::getDirect(
526521
Size == Alignment ? BaseTy
527522
: llvm::ArrayType::get(BaseTy, Size / Alignment));

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,50 @@ struct SSpp_align16 {
571571
//
572572
void TSpp_align16(SSpp_align16 s) { *s.a.x = 1; }
573573

574+
575+
struct Sempty {
576+
};
577+
// CHECK-A64-LABEL: define dso_local void @_Z6Tempty6Sempty(
578+
// CHECK-A64-SAME: i8 [[S_COERCE:%.*]]) #[[ATTR0]] {
579+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
580+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SEMPTY:%.*]], align 1
581+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SEMPTY]], ptr [[S]], i32 0, i32 0
582+
// CHECK-A64-NEXT: store i8 [[S_COERCE]], ptr [[COERCE_DIVE]], align 1
583+
// CHECK-A64-NEXT: ret void
584+
//
585+
// CHECK-A64_32-LABEL: define void @_Z6Tempty6Sempty(
586+
// CHECK-A64_32-SAME: i8 [[S_COERCE:%.*]]) #[[ATTR0]] {
587+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
588+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SEMPTY:%.*]], align 1
589+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SEMPTY]], ptr [[S]], i32 0, i32 0
590+
// CHECK-A64_32-NEXT: store i8 [[S_COERCE]], ptr [[COERCE_DIVE]], align 1
591+
// CHECK-A64_32-NEXT: ret void
592+
//
593+
void Tempty(Sempty s) { }
594+
595+
596+
struct SpSempty {
597+
Sempty y;
598+
int *x;
599+
};
600+
// CHECK-A64-LABEL: define dso_local void @_Z8TpSempty8SpSempty(
601+
// CHECK-A64-SAME: [2 x i64] [[S_COERCE:%.*]]) #[[ATTR0]] {
602+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
603+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SPSEMPTY:%.*]], align 8
604+
// CHECK-A64-NEXT: store [2 x i64] [[S_COERCE]], ptr [[S]], align 8
605+
// CHECK-A64-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPSEMPTY]], ptr [[S]], i32 0, i32 1
606+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8
607+
// CHECK-A64-NEXT: store i32 1, ptr [[TMP0]], align 4
608+
// CHECK-A64-NEXT: ret void
609+
//
610+
// CHECK-A64_32-LABEL: define void @_Z8TpSempty8SpSempty(
611+
// CHECK-A64_32-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
612+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
613+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SPSEMPTY:%.*]], align 4
614+
// CHECK-A64_32-NEXT: store i64 [[S_COERCE]], ptr [[S]], align 4
615+
// CHECK-A64_32-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPSEMPTY]], ptr [[S]], i32 0, i32 1
616+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 4
617+
// CHECK-A64_32-NEXT: store i32 1, ptr [[TMP0]], align 4
618+
// CHECK-A64_32-NEXT: ret void
619+
//
620+
void TpSempty(SpSempty s) { *s.x = 1; }

0 commit comments

Comments
 (0)