r221559 - ARM ABI: simplify decisions on whether args can be expanded.
Tim Northover
tnorthover at apple.com
Fri Nov 7 14:30:51 PST 2014
Author: tnorthover
Date: Fri Nov 7 16:30:50 2014
New Revision: 221559
URL: http://llvm.org/viewvc/llvm-project?rev=221559&view=rev
Log:
ARM ABI: simplify decisions on whether args can be expanded.
Homogeneous aggregates on AAPCS_VFP ARM need to be passed *without* being
flattened (e.g. [2 x float] rather than "float, float") for various weird ABI
reasons. However, this isn't the case for anything else; further, we know at
the ABIArgInfo::getDirect callsites whether this flattening is allowed.
So, we can get more unified ARM code, with a simpler Clang, by just using that
knowledge directly.
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/arm-aapcs-vfp.c
cfe/trunk/test/CodeGen/arm-arguments.c
cfe/trunk/test/CodeGen/arm-homogenous.c
cfe/trunk/test/CodeGenCXX/homogeneous-aggregates.cpp
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=221559&r1=221558&r2=221559&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Nov 7 16:30:50 2014
@@ -4546,9 +4546,6 @@ void ARMABIInfo::computeInfo(CGFunctionI
// unallocated are marked as unavailable.
resetAllocatedRegs();
- const bool isAAPCS_VFP =
- getABIKind() == ARMABIInfo::AAPCS_VFP && !FI.isVariadic();
-
if (getCXXABI().classifyReturnType(FI)) {
if (FI.getReturnInfo().isIndirect())
markAllocatedGPRs(1, 1);
@@ -4578,11 +4575,11 @@ void ARMABIInfo::computeInfo(CGFunctionI
llvm::Type *PaddingTy = llvm::ArrayType::get(
llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
if (I.info.canHaveCoerceToType()) {
- I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */, 0 /* offset */,
- PaddingTy, !isAAPCS_VFP);
+ I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */,
+ 0 /* offset */, PaddingTy, true);
} else {
I.info = ABIArgInfo::getDirect(nullptr /* type */, 0 /* offset */,
- PaddingTy, !isAAPCS_VFP);
+ PaddingTy, true);
}
}
}
@@ -4693,9 +4690,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
// with a Base Type of a single- or double-precision floating-point type,
// 64-bit containerized vectors or 128-bit containerized vectors with one
// to four Elements.
-
- const bool isAAPCS_VFP =
- getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic;
+ bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic;
// Handle illegal vector types here.
if (isIllegalVectorType(Ty)) {
@@ -4704,7 +4699,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
llvm::Type *ResType =
llvm::Type::getInt32Ty(getVMContext());
markAllocatedGPRs(1, 1);
- return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(ResType);
}
if (Size == 64) {
llvm::Type *ResType = llvm::VectorType::get(
@@ -4715,7 +4710,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
markAllocatedVFPs(2, 2);
IsCPRC = true;
}
- return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(ResType);
}
if (Size == 128) {
llvm::Type *ResType = llvm::VectorType::get(
@@ -4726,7 +4721,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
markAllocatedVFPs(4, 4);
IsCPRC = true;
}
- return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(ResType);
}
markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
@@ -4765,9 +4760,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
unsigned Size = getContext().getTypeSize(Ty);
if (!IsCPRC)
markAllocatedGPRs(Size > 32 ? 2 : 1, (Size + 31) / 32);
- return (Ty->isPromotableIntegerType()
- ? ABIArgInfo::getExtend()
- : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP));
+ return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend()
+ : ABIArgInfo::getDirect());
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
@@ -4779,7 +4773,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
- if (isAAPCS_VFP) {
+ if (IsEffectivelyAAPCS_VFP) {
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
// into VFP registers.
const Type *Base = nullptr;
@@ -4800,7 +4794,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
markAllocatedVFPs(2, Members * 2);
}
IsCPRC = true;
- return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
}
}
@@ -4838,9 +4832,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
markAllocatedGPRs(2, SizeRegs * 2);
}
- llvm::Type *STy =
- llvm::StructType::get(llvm::ArrayType::get(ElemTy, SizeRegs), NULL);
- return ABIArgInfo::getDirect(STy, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs));
}
static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
@@ -4930,8 +4922,7 @@ static bool isIntegerLikeType(QualType T
ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
bool isVariadic) const {
- const bool isAAPCS_VFP =
- getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic;
+ bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic;
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -4947,9 +4938,8 @@ ABIArgInfo ARMABIInfo::classifyReturnTyp
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType()
- ? ABIArgInfo::getExtend()
- : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP));
+ return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend()
+ : ABIArgInfo::getDirect();
}
// Are we following APCS?
@@ -4987,13 +4977,13 @@ ABIArgInfo ARMABIInfo::classifyReturnTyp
return ABIArgInfo::getIgnore();
// Check for homogeneous aggregates with AAPCS-VFP.
- if (getABIKind() == AAPCS_VFP && !isVariadic) {
+ if (IsEffectivelyAAPCS_VFP) {
const Type *Base = nullptr;
uint64_t Members;
if (isHomogeneousAggregate(RetTy, Base, Members)) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
- return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
}
}
@@ -5003,18 +4993,14 @@ ABIArgInfo ARMABIInfo::classifyReturnTyp
if (Size <= 32) {
if (getDataLayout().isBigEndian())
// Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
- return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0,
- nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
// Return in the smallest viable integer type.
if (Size <= 8)
- return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()), 0,
- nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
if (Size <= 16)
- return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()), 0,
- nullptr, !isAAPCS_VFP);
- return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0,
- nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
}
markAllocatedGPRs(1, 1);
Modified: cfe/trunk/test/CodeGen/arm-aapcs-vfp.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-aapcs-vfp.c?rev=221559&r1=221558&r2=221559&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm-aapcs-vfp.c (original)
+++ cfe/trunk/test/CodeGen/arm-aapcs-vfp.c Fri Nov 7 16:30:50 2014
@@ -72,7 +72,7 @@ struct big_struct {
float f3;
float f4;
};
-// CHECK: define arm_aapcs_vfpcc void @test_big({ [5 x i32] } %{{.*}})
+// CHECK: define arm_aapcs_vfpcc void @test_big([5 x i32] %{{.*}})
// CHECK64: define void @test_big(%struct.big_struct* %{{.*}})
// CHECK64: call void @llvm.memcpy
// CHECK64: call void @big_callee(%struct.big_struct*
@@ -88,7 +88,7 @@ struct heterogeneous_struct {
float f1;
int i2;
};
-// CHECK: define arm_aapcs_vfpcc void @test_hetero({ [2 x i32] } %{{.*}})
+// CHECK: define arm_aapcs_vfpcc void @test_hetero([2 x i32] %{{.*}})
// CHECK64: define void @test_hetero(i64 %{{.*}})
extern void hetero_callee(struct heterogeneous_struct);
void test_hetero(struct heterogeneous_struct arg) {
@@ -125,25 +125,25 @@ typedef struct { long long x; int y; } s
// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_1(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i64 %k, i32 %l)
void test_vfp_stack_gpr_split_1(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, long long k, int l) {}
-// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], { [2 x i64] } %k.coerce)
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], [2 x i64] %k.coerce)
void test_vfp_stack_gpr_split_2(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_long_long_int k) {}
-// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [3 x i32], { [2 x i64] } %k.coerce)
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [3 x i32], [2 x i64] %k.coerce)
struct_long_long_int test_vfp_stack_gpr_split_3(double a, double b, double c, double d, double e, double f, double g, double h, double i, struct_long_long_int k) {}
typedef struct { int a; int b:4; int c; } struct_int_bitfield_int;
-// CHECK: define arm_aapcs_vfpcc void @test_test_vfp_stack_gpr_split_bitfield(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i32 %k, [2 x i32], { [3 x i32] } %l.coerce)
+// CHECK: define arm_aapcs_vfpcc void @test_test_vfp_stack_gpr_split_bitfield(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i32 %k, [2 x i32], [3 x i32] %l.coerce)
void test_test_vfp_stack_gpr_split_bitfield(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, int k, struct_int_bitfield_int l) {}
// Note: this struct requires internal padding
typedef struct { int x; long long y; } struct_int_long_long;
-// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_4(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], { [2 x i64] } %k.coerce)
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_4(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], [2 x i64] %k.coerce)
void test_vfp_stack_gpr_split_4(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_int_long_long k) {}
// This very large struct (passed byval) uses up the GPRs, so no padding is needed
typedef struct { int x[17]; } struct_seventeen_ints;
typedef struct { int x[4]; } struct_four_ints;
-// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_5(%struct.struct_seventeen_ints* byval align 4 %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, double %j, { [4 x i32] } %k.coerce)
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_5(%struct.struct_seventeen_ints* byval align 4 %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, double %j, [4 x i32] %k.coerce)
void test_vfp_stack_gpr_split_5(struct_seventeen_ints a, double b, double c, double d, double e, double f, double g, double h, double i, double j, struct_four_ints k) {}
// Here, parameter k would need padding to prevent it from being split, but it
Modified: cfe/trunk/test/CodeGen/arm-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-arguments.c?rev=221559&r1=221558&r2=221559&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm-arguments.c (original)
+++ cfe/trunk/test/CodeGen/arm-arguments.c Fri Nov 7 16:30:50 2014
@@ -183,14 +183,9 @@ void f33(struct s33 s) { }
struct s34 { char c; };
void f34(struct s34 s);
void g34(struct s34 *s) { f34(*s); }
-// APCS-GNU: @g34(%struct.s34* %s)
-// APCS-GNU: %[[a:.*]] = alloca { [1 x i32] }
-// APCS-GNU: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0
-// APCS-GNU: load [1 x i32]* %[[gep]]
// AAPCS: @g34(%struct.s34* %s)
-// AAPCS: %[[a:.*]] = alloca { [1 x i32] }
-// AAPCS: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0
-// AAPCS: load [1 x i32]* %[[gep]]
+// AAPCS: %[[a:.*]] = alloca [1 x i32]
+// AAPCS: load [1 x i32]* %[[a]]
// rdar://12596507
struct s35
Modified: cfe/trunk/test/CodeGen/arm-homogenous.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-homogenous.c?rev=221559&r1=221558&r2=221559&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm-homogenous.c (original)
+++ cfe/trunk/test/CodeGen/arm-homogenous.c Fri Nov 7 16:30:50 2014
@@ -22,7 +22,7 @@ extern union_with_first_floats returns_u
void test_union_with_first_floats(void) {
takes_union_with_first_floats(g_u_f);
}
-// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats({ [4 x i32] })
+// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats([4 x i32])
void test_return_union_with_first_floats(void) {
g_u_f = returns_union_with_first_floats();
@@ -42,7 +42,7 @@ extern union_with_non_first_floats retur
void test_union_with_non_first_floats(void) {
takes_union_with_non_first_floats(g_u_nf_f);
}
-// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats({ [4 x i32] })
+// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats([4 x i32])
void test_return_union_with_non_first_floats(void) {
g_u_nf_f = returns_union_with_non_first_floats();
@@ -62,7 +62,7 @@ extern struct_with_union_with_first_floa
void test_struct_with_union_with_first_floats(void) {
takes_struct_with_union_with_first_floats(g_s_f);
}
-// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats({ [5 x i32] })
+// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats([5 x i32])
void test_return_struct_with_union_with_first_floats(void) {
g_s_f = returns_struct_with_union_with_first_floats();
@@ -82,7 +82,7 @@ extern struct_with_union_with_non_first_
void test_struct_with_union_with_non_first_floats(void) {
takes_struct_with_union_with_non_first_floats(g_s_nf_f);
}
-// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats({ [5 x i32] })
+// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats([5 x i32])
void test_return_struct_with_union_with_non_first_floats(void) {
g_s_nf_f = returns_struct_with_union_with_non_first_floats();
Modified: cfe/trunk/test/CodeGenCXX/homogeneous-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/homogeneous-aggregates.cpp?rev=221559&r1=221558&r2=221559&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/homogeneous-aggregates.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/homogeneous-aggregates.cpp Fri Nov 7 16:30:50 2014
@@ -39,7 +39,7 @@ struct I3 : Base2 {};
struct D5 : I1, I2, I3 {}; // homogeneous aggregate
// PPC: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce)
-// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, { [3 x i64] } %x.coerce)
+// ARM32: define arm_aapcs_vfpcc void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, [3 x i64] %x.coerce)
// ARM64: define void @_Z7func_D12D1(%struct.D1* noalias sret %agg.result, %struct.D1* %x)
// X64: define x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(%struct.D1* noalias sret %agg.result, %struct.D1* %x)
D1 CC func_D1(D1 x) { return x; }
@@ -51,7 +51,7 @@ D1 CC func_D1(D1 x) { return x; }
D2 CC func_D2(D2 x) { return x; }
// PPC: define void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, [4 x i64] %x.coerce)
-// ARM32: define arm_aapcs_vfpcc void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, { [4 x i64] } %x.coerce)
+// ARM32: define arm_aapcs_vfpcc void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, [4 x i64] %x.coerce)
// ARM64: define void @_Z7func_D32D3(%struct.D3* noalias sret %agg.result, %struct.D3* %x)
D3 CC func_D3(D3 x) { return x; }
More information about the cfe-commits
mailing list