Hi t.p.northover, rengolin,

r211898 introduced a regression where a large struct, which would normally be 
passed ByVal, was causing padding to be inserted to prevent the backend from 
using some GPRs, in order to follow the AAPCS. However, the type of the 
argument was not being set correctly, so the backend cannot align 8-byte 
aligned struct types on the stack.
    
The fix is to not insert the padding arguments when the argument is being 
passed ByVal.

http://reviews.llvm.org/D4541

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/arm-aapcs-vfp.c

Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -3996,8 +3996,12 @@
     // GPRs from being used. In this situation, the current argument could
     // only be allocated by rule C.8, so rule C.6 would mark these GPRs as
     // unusable anyway.
+    // We do not have to do this if the argument is being passed ByVal, as the
+    // backend can handle that situation correctly.
     const bool StackUsed = PreAllocationGPRs > NumGPRs || PreAllocationVFPs > 
NumVFPs;
-    if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs && 
StackUsed) {
+    const bool IsByVal = I.info.isIndirect() && I.info.getIndirectByVal();
+    if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs &&
+        StackUsed && !IsByVal) {
       llvm::Type *PaddingTy = llvm::ArrayType::get(
           llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
       if (I.info.canHaveCoerceToType()) {
Index: test/CodeGen/arm-aapcs-vfp.c
===================================================================
--- test/CodeGen/arm-aapcs-vfp.c
+++ test/CodeGen/arm-aapcs-vfp.c
@@ -145,3 +145,8 @@
 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)
 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
+// is passed ByVal (due to being > 64 bytes), so the backend handles this 
instead.
+void test_vfp_stack_gpr_split_6(double a, double b, double c, double d, double 
e, double f, double g, double h, double i, int j, struct_seventeen_ints k) {}
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_6(double %a, 
double %b, double %c, double %d, double %e, double %f, double %g, double %h, 
double %i, i32 %j, %struct.struct_seventeen_ints* byval align 4 %k)
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -3996,8 +3996,12 @@
     // GPRs from being used. In this situation, the current argument could
     // only be allocated by rule C.8, so rule C.6 would mark these GPRs as
     // unusable anyway.
+    // We do not have to do this if the argument is being passed ByVal, as the
+    // backend can handle that situation correctly.
     const bool StackUsed = PreAllocationGPRs > NumGPRs || PreAllocationVFPs > NumVFPs;
-    if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs && StackUsed) {
+    const bool IsByVal = I.info.isIndirect() && I.info.getIndirectByVal();
+    if (!IsCPRC && PreAllocationGPRs < NumGPRs && AllocatedGPRs > NumGPRs &&
+        StackUsed && !IsByVal) {
       llvm::Type *PaddingTy = llvm::ArrayType::get(
           llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
       if (I.info.canHaveCoerceToType()) {
Index: test/CodeGen/arm-aapcs-vfp.c
===================================================================
--- test/CodeGen/arm-aapcs-vfp.c
+++ test/CodeGen/arm-aapcs-vfp.c
@@ -145,3 +145,8 @@
 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)
 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
+// is passed ByVal (due to being > 64 bytes), so the backend handles this instead.
+void test_vfp_stack_gpr_split_6(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_seventeen_ints k) {}
+// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_6(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, %struct.struct_seventeen_ints* byval align 4 %k)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to