diff options
Diffstat (limited to 'test/CodeGen/ARM/byval-align.ll')
-rw-r--r-- | test/CodeGen/ARM/byval-align.ll | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/test/CodeGen/ARM/byval-align.ll b/test/CodeGen/ARM/byval-align.ll new file mode 100644 index 0000000..a26b5a7 --- /dev/null +++ b/test/CodeGen/ARM/byval-align.ll @@ -0,0 +1,76 @@ +; RUN: llc -mtriple=thumbv7-apple-ios8.0 %s -o - | FileCheck %s + +; This checks that alignments greater than 4 are respected by APCS +; targets. Mostly here to make sure *some* correct code is created after some +; simplifying refactoring; at the time of writing there were no actual APCS +; users of byval alignments > 4, so no real calls for ABI stability. + +; "byval align 16" can't fit in any regs with an i8* taking up r0. +define i32 @test_align16(i8*, [4 x i32]* byval align 16 %b) { +; CHECK-LABEL: test_align16: +; CHECK-NOT: sub sp +; CHECK: push {r4, r7, lr} +; CHECK: add r7, sp, #4 + +; CHECK: ldr r0, [r7, #8] + + call void @bar() + %valptr = getelementptr [4 x i32], [4 x i32]* %b, i32 0, i32 0 + %val = load i32, i32* %valptr + ret i32 %val +} + +; byval align 8 can, but we used to incorrectly set r7 here (miscalculating the +; space taken up by arg regs). +define i32 @test_align8(i8*, [4 x i32]* byval align 8 %b) { +; CHECK-LABEL: test_align8: +; CHECK: sub sp, #8 +; CHECK: push {r4, r7, lr} +; CHECK: add r7, sp, #4 + +; CHECK-DAG: str r2, [r7, #8] +; CHECK-DAG: str r3, [r7, #12] + +; CHECK: ldr r0, [r7, #8] + + call void @bar() + %valptr = getelementptr [4 x i32], [4 x i32]* %b, i32 0, i32 0 + %val = load i32, i32* %valptr + ret i32 %val +} + +; "byval align 32" can't fit in regs no matter what: it would be misaligned +; unless the incoming stack was deliberately misaligned. +define i32 @test_align32(i8*, [4 x i32]* byval align 32 %b) { +; CHECK-LABEL: test_align32: +; CHECK-NOT: sub sp +; CHECK: push {r4, r7, lr} +; CHECK: add r7, sp, #4 + +; CHECK: ldr r0, [r7, #8] + + call void @bar() + %valptr = getelementptr [4 x i32], [4 x i32]* %b, i32 0, i32 0 + %val = load i32, i32* %valptr + ret i32 %val +} + +; When passing an object "byval align N", the stack must be at least N-aligned. +define void @test_call_align16() { +; CHECK-LABEL: test_call_align16: +; CHECK: push {r4, r7, lr} +; CHECK: add r7, sp, #4 + +; CHECK: mov [[TMP:r[0-9]+]], sp +; CHECK: bfc [[TMP]], #0, #4 +; CHECK: mov sp, [[TMP]] + +; While we're here, make sure the caller also puts it at sp + ; CHECK: mov r[[BASE:[0-9]+]], sp + ; CHECK: vst1.32 {d{{[0-9]+}}, d{{[0-9]+}}}, [r[[BASE]]] + call i32 @test_align16(i8* null, [4 x i32]* byval align 16 @var) + ret void +} + +@var = global [4 x i32] zeroinitializer +declare void @bar() |