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