diff options
Diffstat (limited to 'test/CodeGen/PowerPC/ppc64le-aggregates.ll')
-rw-r--r-- | test/CodeGen/PowerPC/ppc64le-aggregates.ll | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/test/CodeGen/PowerPC/ppc64le-aggregates.ll b/test/CodeGen/PowerPC/ppc64le-aggregates.ll new file mode 100644 index 0000000..9eed623 --- /dev/null +++ b/test/CodeGen/PowerPC/ppc64le-aggregates.ll @@ -0,0 +1,329 @@ +; RUN: llc < %s -march=ppc64le -mcpu=pwr8 -mattr=+altivec | FileCheck %s + +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-unknown-linux-gnu" + +; +; Verify use of registers for float/vector aggregate return. +; + +define [8 x float] @return_float([8 x float] %x) { +entry: + ret [8 x float] %x +} +; CHECK-LABEL: @return_float +; CHECK: %entry +; CHECK-NEXT: blr + +define [8 x double] @return_double([8 x double] %x) { +entry: + ret [8 x double] %x +} +; CHECK-LABEL: @return_double +; CHECK: %entry +; CHECK-NEXT: blr + +define [4 x ppc_fp128] @return_ppcf128([4 x ppc_fp128] %x) { +entry: + ret [4 x ppc_fp128] %x +} +; CHECK-LABEL: @return_ppcf128 +; CHECK: %entry +; CHECK-NEXT: blr + +define [8 x <4 x i32>] @return_v4i32([8 x <4 x i32>] %x) { +entry: + ret [8 x <4 x i32>] %x +} +; CHECK-LABEL: @return_v4i32 +; CHECK: %entry +; CHECK-NEXT: blr + + +; +; Verify amount of space taken up by aggregates in the parameter save area. +; + +define i64 @callee_float([7 x float] %a, [7 x float] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_float +; CHECK: ld 3, 96(1) +; CHECK: blr + +define void @caller_float(i64 %x, [7 x float] %y) { +entry: + tail call void @test_float([7 x float] %y, [7 x float] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_float +; CHECK: std 3, 96(1) +; CHECK: bl test_float + +declare void @test_float([7 x float], [7 x float], i64) + +define i64 @callee_double(i64 %a, [7 x double] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_double +; CHECK: ld 3, 96(1) +; CHECK: blr + +define void @caller_double(i64 %x, [7 x double] %y) { +entry: + tail call void @test_double(i64 %x, [7 x double] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_double +; CHECK: std 3, 96(1) +; CHECK: bl test_double + +declare void @test_double(i64, [7 x double], i64) + +define i64 @callee_ppcf128(i64 %a, [4 x ppc_fp128] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_ppcf128 +; CHECK: ld 3, 104(1) +; CHECK: blr + +define void @caller_ppcf128(i64 %x, [4 x ppc_fp128] %y) { +entry: + tail call void @test_ppcf128(i64 %x, [4 x ppc_fp128] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_ppcf128 +; CHECK: std 3, 104(1) +; CHECK: bl test_ppcf128 + +declare void @test_ppcf128(i64, [4 x ppc_fp128], i64) + +define i64 @callee_i64(i64 %a, [7 x i64] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_i64 +; CHECK: ld 3, 96(1) +; CHECK: blr + +define void @caller_i64(i64 %x, [7 x i64] %y) { +entry: + tail call void @test_i64(i64 %x, [7 x i64] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_i64 +; CHECK: std 3, 96(1) +; CHECK: bl test_i64 + +declare void @test_i64(i64, [7 x i64], i64) + +define i64 @callee_i128(i64 %a, [4 x i128] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_i128 +; CHECK: ld 3, 112(1) +; CHECK: blr + +define void @caller_i128(i64 %x, [4 x i128] %y) { +entry: + tail call void @test_i128(i64 %x, [4 x i128] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_i128 +; CHECK: std 3, 112(1) +; CHECK: bl test_i128 + +declare void @test_i128(i64, [4 x i128], i64) + +define i64 @callee_v4i32(i64 %a, [4 x <4 x i32>] %b, i64 %c) { +entry: + ret i64 %c +} +; CHECK-LABEL: @callee_v4i32 +; CHECK: ld 3, 112(1) +; CHECK: blr + +define void @caller_v4i32(i64 %x, [4 x <4 x i32>] %y) { +entry: + tail call void @test_v4i32(i64 %x, [4 x <4 x i32>] %y, i64 %x) + ret void +} +; CHECK-LABEL: @caller_v4i32 +; CHECK: std 3, 112(1) +; CHECK: bl test_v4i32 + +declare void @test_v4i32(i64, [4 x <4 x i32>], i64) + + +; +; Verify handling of floating point arguments in GPRs +; + +%struct.float8 = type { [8 x float] } +%struct.float5 = type { [5 x float] } +%struct.float2 = type { [2 x float] } + +@g8 = common global %struct.float8 zeroinitializer, align 4 +@g5 = common global %struct.float5 zeroinitializer, align 4 +@g2 = common global %struct.float2 zeroinitializer, align 4 + +define float @callee0([7 x float] %a, [7 x float] %b) { +entry: + %b.extract = extractvalue [7 x float] %b, 6 + ret float %b.extract +} +; CHECK-LABEL: @callee0 +; CHECK: stw 10, [[OFF:.*]](1) +; CHECK: lfs 1, [[OFF]](1) +; CHECK: blr + +define void @caller0([7 x float] %a) { +entry: + tail call void @test0([7 x float] %a, [7 x float] %a) + ret void +} +; CHECK-LABEL: @caller0 +; CHECK-DAG: fmr 8, 1 +; CHECK-DAG: fmr 9, 2 +; CHECK-DAG: fmr 10, 3 +; CHECK-DAG: fmr 11, 4 +; CHECK-DAG: fmr 12, 5 +; CHECK-DAG: fmr 13, 6 +; CHECK-DAG: stfs 7, [[OFF:[0-9]+]](1) +; CHECK-DAG: lwz 10, [[OFF]](1) +; CHECK: bl test0 + +declare void @test0([7 x float], [7 x float]) + +define float @callee1([8 x float] %a, [8 x float] %b) { +entry: + %b.extract = extractvalue [8 x float] %b, 7 + ret float %b.extract +} +; CHECK-LABEL: @callee1 +; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32 +; CHECK: stw [[REG]], [[OFF:.*]](1) +; CHECK: lfs 1, [[OFF]](1) +; CHECK: blr + +define void @caller1([8 x float] %a) { +entry: + tail call void @test1([8 x float] %a, [8 x float] %a) + ret void +} +; CHECK-LABEL: @caller1 +; CHECK-DAG: fmr 9, 1 +; CHECK-DAG: fmr 10, 2 +; CHECK-DAG: fmr 11, 3 +; CHECK-DAG: fmr 12, 4 +; CHECK-DAG: fmr 13, 5 +; CHECK-DAG: stfs 5, [[OFF0:[0-9]+]](1) +; CHECK-DAG: stfs 6, [[OFF1:[0-9]+]](1) +; CHECK-DAG: stfs 7, [[OFF2:[0-9]+]](1) +; CHECK-DAG: stfs 8, [[OFF3:[0-9]+]](1) +; CHECK-DAG: lwz [[REG0:[0-9]+]], [[OFF0]](1) +; CHECK-DAG: lwz [[REG1:[0-9]+]], [[OFF1]](1) +; CHECK-DAG: lwz [[REG2:[0-9]+]], [[OFF2]](1) +; CHECK-DAG: lwz [[REG3:[0-9]+]], [[OFF3]](1) +; CHECK-DAG: sldi [[REG1]], [[REG1]], 32 +; CHECK-DAG: sldi [[REG3]], [[REG3]], 32 +; CHECK-DAG: or 9, [[REG0]], [[REG1]] +; CHECK-DAG: or 10, [[REG2]], [[REG3]] +; CHECK: bl test1 + +declare void @test1([8 x float], [8 x float]) + +define float @callee2([8 x float] %a, [5 x float] %b, [2 x float] %c) { +entry: + %c.extract = extractvalue [2 x float] %c, 1 + ret float %c.extract +} +; CHECK-LABEL: @callee2 +; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32 +; CHECK: stw [[REG]], [[OFF:.*]](1) +; CHECK: lfs 1, [[OFF]](1) +; CHECK: blr + +define void @caller2() { +entry: + %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4 + %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4 + %2 = load [2 x float]* getelementptr inbounds (%struct.float2* @g2, i64 0, i32 0), align 4 + tail call void @test2([8 x float] %0, [5 x float] %1, [2 x float] %2) + ret void +} +; CHECK-LABEL: @caller2 +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK-DAG: lfs 1, 0([[REG]]) +; CHECK-DAG: lfs 2, 4([[REG]]) +; CHECK-DAG: lfs 3, 8([[REG]]) +; CHECK-DAG: lfs 4, 12([[REG]]) +; CHECK-DAG: lfs 5, 16([[REG]]) +; CHECK-DAG: lfs 6, 20([[REG]]) +; CHECK-DAG: lfs 7, 24([[REG]]) +; CHECK-DAG: lfs 8, 28([[REG]]) +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK-DAG: lfs 9, 0([[REG]]) +; CHECK-DAG: lfs 10, 4([[REG]]) +; CHECK-DAG: lfs 11, 8([[REG]]) +; CHECK-DAG: lfs 12, 12([[REG]]) +; CHECK-DAG: lfs 13, 16([[REG]]) +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK-DAG: lwz [[REG0:[0-9]+]], 0([[REG]]) +; CHECK-DAG: lwz [[REG1:[0-9]+]], 4([[REG]]) +; CHECK-DAG: sldi [[REG1]], [[REG1]], 32 +; CHECK-DAG: or 10, [[REG0]], [[REG1]] +; CHECK: bl test2 + +declare void @test2([8 x float], [5 x float], [2 x float]) + +define double @callee3([8 x float] %a, [5 x float] %b, double %c) { +entry: + ret double %c +} +; CHECK-LABEL: @callee3 +; CHECK: std 10, [[OFF:.*]](1) +; CHECK: lfd 1, [[OFF]](1) +; CHECK: blr + +define void @caller3(double %d) { +entry: + %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4 + %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4 + tail call void @test3([8 x float] %0, [5 x float] %1, double %d) + ret void +} +; CHECK-LABEL: @caller3 +; CHECK: stfd 1, [[OFF:.*]](1) +; CHECK: ld 10, [[OFF]](1) +; CHECK: bl test3 + +declare void @test3([8 x float], [5 x float], double) + +define float @callee4([8 x float] %a, [5 x float] %b, float %c) { +entry: + ret float %c +} +; CHECK-LABEL: @callee4 +; CHECK: stw 10, [[OFF:.*]](1) +; CHECK: lfs 1, [[OFF]](1) +; CHECK: blr + +define void @caller4(float %f) { +entry: + %0 = load [8 x float]* getelementptr inbounds (%struct.float8* @g8, i64 0, i32 0), align 4 + %1 = load [5 x float]* getelementptr inbounds (%struct.float5* @g5, i64 0, i32 0), align 4 + tail call void @test4([8 x float] %0, [5 x float] %1, float %f) + ret void +} +; CHECK-LABEL: @caller4 +; CHECK: stfs 1, [[OFF:.*]](1) +; CHECK: lwz 10, [[OFF]](1) +; CHECK: bl test4 + +declare void @test4([8 x float], [5 x float], float) + |