aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2014-07-18 09:09:31 +0000
committerOliver Stannard <oliver.stannard@arm.com>2014-07-18 09:09:31 +0000
commite022851f3b253f421eced5fb0f8f5654771a35a1 (patch)
treede0900534dafd45df27b6ec167df53b453609357 /clang
parent12817862f10b9f3e9da7cd3e3dfc5dad86cd8cb8 (diff)
downloadllvm-e022851f3b253f421eced5fb0f8f5654771a35a1.zip
llvm-e022851f3b253f421eced5fb0f8f5654771a35a1.tar.gz
llvm-e022851f3b253f421eced5fb0f8f5654771a35a1.tar.bz2
[ARM] Fix AAPCS regression caused by r211898
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. llvm-svn: 213359
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp6
-rw-r--r--clang/test/CodeGen/arm-aapcs-vfp.c5
2 files changed, 10 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 10050ac..4ccdedb 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -3996,8 +3996,12 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
// 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()) {
diff --git a/clang/test/CodeGen/arm-aapcs-vfp.c b/clang/test/CodeGen/arm-aapcs-vfp.c
index 7bc1b1e..eea6ab2 100644
--- a/clang/test/CodeGen/arm-aapcs-vfp.c
+++ b/clang/test/CodeGen/arm-aapcs-vfp.c
@@ -145,3 +145,8 @@ 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)
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)