summaryrefslogtreecommitdiff
path: root/test/CodeGen/ARM/hfa-in-contiguous-registers.ll
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2014-05-09 14:01:47 +0000
committerOliver Stannard <oliver.stannard@arm.com>2014-05-09 14:01:47 +0000
commite2948385b92b5aec6ac5187ca4fee367db2f0dd1 (patch)
tree8a8ce832cbbde87255db369fe716cf4c6938acdd /test/CodeGen/ARM/hfa-in-contiguous-registers.ll
parentba148a1b8f04f20fc8e70a50585ffffadac3368d (diff)
ARM: HFAs must be passed in consecutive registers
When using the ARM AAPCS, HFAs (Homogeneous Floating-point Aggregates) must be passed in a block of consecutive floating-point registers, or on the stack. This means that unused floating-point registers cannot be back-filled with part of an HFA, however this can currently happen. This patch, along with the corresponding clang patch (http://reviews.llvm.org/D3083) prevents this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208413 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen/ARM/hfa-in-contiguous-registers.ll')
-rw-r--r--test/CodeGen/ARM/hfa-in-contiguous-registers.ll94
1 files changed, 94 insertions, 0 deletions
diff --git a/test/CodeGen/ARM/hfa-in-contiguous-registers.ll b/test/CodeGen/ARM/hfa-in-contiguous-registers.ll
new file mode 100644
index 00000000000..f9ec6e0c645
--- /dev/null
+++ b/test/CodeGen/ARM/hfa-in-contiguous-registers.ll
@@ -0,0 +1,94 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+target triple = "armv7-none--gnueabihf"
+
+%struct.s = type { float, float }
+%union.t = type { [4 x float] }
+
+; Equivalent C code:
+; struct s { float a; float b; };
+; float foo(float a, double b, struct s c) { return c.a; }
+; Argument allocation:
+; a -> s0
+; b -> d1
+; c -> s4, s5
+; s1 is unused
+; return in s0
+define float @test1(float %a, double %b, %struct.s %c) {
+entry:
+; CHECK-LABEL: test1
+; CHECK: vmov.f32 s0, s4
+; CHECK-NOT: vmov.f32 s0, s1
+
+ %result = extractvalue %struct.s %c, 0
+ ret float %result
+}
+
+; Equivalent C code:
+; union t { float a[4] };
+; float foo(float a, double b, union s c) { return c.a[0]; }
+; Argument allocation:
+; a -> s0
+; b -> d1
+; c -> s4..s7
+define float @test2(float %a, double %b, %union.t %c) #0 {
+entry:
+; CHECK-LABEL: test2
+; CHECK: vmov.f32 s0, s4
+; CHECK-NOT: vmov.f32 s0, s1
+
+ %result = extractvalue %union.t %c, 0, 0
+ ret float %result
+}
+
+; Equivalent C code:
+; struct s { float a; float b; };
+; float foo(float a, double b, struct s c, float d) { return d; }
+; Argument allocation:
+; a -> s0
+; b -> d1
+; c -> s4, s5
+; d -> s1
+; return in s0
+define float @test3(float %a, double %b, %struct.s %c, float %d) {
+entry:
+; CHECK-LABEL: test3
+; CHECK: vmov.f32 s0, s1
+; CHECK-NOT: vmov.f32 s0, s5
+
+ ret float %d
+}
+
+; Equivalent C code:
+; struct s { float a; float b; };
+; float foo(struct s a, struct s b) { return b.b; }
+; Argument allocation:
+; a -> s0, s1
+; b -> s2, s3
+; return in s0
+define float @test4(%struct.s %a, %struct.s %b) {
+entry:
+; CHECK-LABEL: test4
+; CHECK: vmov.f32 s0, s3
+
+ %result = extractvalue %struct.s %b, 1
+ ret float %result
+}
+
+; Equivalent C code:
+; struct s { float a; float b; };
+; float foo(struct s a, float b, struct s c) { return c.a; }
+; Argument allocation:
+; a -> s0, s1
+; b -> s2
+; c -> s3, s4
+; return in s0
+define float @test5(%struct.s %a, float %b, %struct.s %c) {
+entry:
+; CHECK-LABEL: test5
+; CHECK: vmov.f32 s0, s3
+
+ %result = extractvalue %struct.s %c, 0
+ ret float %result
+}