diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-04-07 19:10:57 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-04-07 19:10:57 +0000 |
commit | 18fdb398ea94c7ddee40bec49f63491922c5b110 (patch) | |
tree | 62f098f44d1924adc2ee508cb2f7658cb8ee8493 /test/CodeGen/SPARC | |
parent | 0f08eb135997a94ba37f79aaeb306993c21bbae2 (diff) | |
download | llvm-18fdb398ea94c7ddee40bec49f63491922c5b110.tar.gz llvm-18fdb398ea94c7ddee40bec49f63491922c5b110.tar.bz2 llvm-18fdb398ea94c7ddee40bec49f63491922c5b110.tar.xz |
Implement LowerCall_64 for the SPARC v9 64-bit ABI.
There is still no support for byval arguments (which I don't think are
needed) and varargs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178993 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen/SPARC')
-rw-r--r-- | test/CodeGen/SPARC/64abi.ll | 150 |
1 files changed, 147 insertions, 3 deletions
diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll index d447ec76d8..10d8ff7c9a 100644 --- a/test/CodeGen/SPARC/64abi.ll +++ b/test/CodeGen/SPARC/64abi.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=sparcv9 | FileCheck %s +; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler | FileCheck %s ; CHECK: intarg ; CHECK: stb %i0, [%i4] @@ -17,7 +17,7 @@ define void @intarg(i8 %a0, ; %i0 i32 %a3, ; %i3 i8* %a4, ; %i4 i32 %a5, ; %i5 - i32 %a6, ; [%fp+BIAS+176] + i32 signext %a6, ; [%fp+BIAS+176] i8* %a7) { ; [%fp+BIAS+184] store i8 %a0, i8* %a4 store i8 %a1, i8* %a4 @@ -33,6 +33,18 @@ define void @intarg(i8 %a0, ; %i0 ret void } +; CHECK: call_intarg +; Sign-extend and store the full 64 bits. +; CHECK: sra %i0, 0, [[R:%[gilo][0-7]]] +; CHECK: stx [[R]], [%sp+2223] +; Use %o0-%o5 for outgoing arguments +; CHECK: or %g0, 5, %o5 +; CHECK: call intarg +define void @call_intarg(i32 %i0, i8* %i1) { + call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1) + ret void +} + ; CHECK: floatarg ; CHECK: fstod %f1, ; CHECK: faddd %f2, @@ -57,7 +69,7 @@ define double @floatarg(float %a0, ; %f1 float %a14, ; %f29 float %a15, ; %f31 float %a16, ; [%fp+BIAS+256] (using 8 bytes) - float %a17) { ; [%fp+BIAS+264] (using 8 bytes) + double %a17) { ; [%fp+BIAS+264] (using 8 bytes) %d0 = fpext float %a0 to double %s1 = fadd double %a1, %d0 %s2 = fadd double %a2, %s1 @@ -68,6 +80,23 @@ define double @floatarg(float %a0, ; %f1 ret double %s17 } +; CHECK: call_floatarg +; Store 4 bytes, right-aligned in slot. +; CHECK: st %f1, [%sp+2307] +; Store 8 bytes in full slot. +; CHECK: std %f2, [%sp+2311] +; CHECK: fmovd %f2, %f4 +; CHECK: call floatarg +define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) { + %r = call double @floatarg(float %f5, double %d2, double %d2, double %d2, + float %f5, float %f5, float %f5, float %f5, + float %f5, float %f5, float %f5, float %f5, + float %f5, float %f5, float %f5, float %f5, + float %f1, double %d2) + store double %r, double* %p + ret void +} + ; CHECK: mixedarg ; CHECK: fstod %f3 ; CHECK: faddd %f6 @@ -92,6 +121,26 @@ define void @mixedarg(i8 %a0, ; %i0 ret void } +; CHECK: call_mixedarg +; CHECK: stx %i2, [%sp+2247] +; CHECK: stx %i0, [%sp+2223] +; CHECK: fmovd %f2, %f6 +; CHECK: fmovd %f2, %f16 +; CHECK: call mixedarg +define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) { + call void @mixedarg(i8 undef, + float undef, + i16 undef, + double %f2, + i13 undef, + float undef, + i64 %i0, + double* undef, + double %f2, + i16* %i2) + ret void +} + ; The inreg attribute is used to indicate 32-bit sized struct elements that ; share an 8-byte slot. ; CHECK: inreg_fi @@ -105,6 +154,15 @@ define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0 ret i32 %rv } +; CHECK: call_inreg_fi +; CHECK: sllx %i1, 32, %o0 +; CHECK: fmovs %f5, %f1 +; CHECK: call inreg_fi +define void @call_inreg_fi(i32* %p, i32 %i1, float %f5) { + %x = call i32 @inreg_fi(i32 %i1, float %f5) + ret void +} + ; CHECK: inreg_ff ; CHECK: fsubs %f0, %f1, %f1 define float @inreg_ff(float inreg %a0, ; %f0 @@ -113,6 +171,15 @@ define float @inreg_ff(float inreg %a0, ; %f0 ret float %rv } +; CHECK: call_inreg_ff +; CHECK: fmovs %f3, %f0 +; CHECK: fmovs %f5, %f1 +; CHECK: call inreg_ff +define void @call_inreg_ff(i32* %p, float %f3, float %f5) { + %x = call float @inreg_ff(float %f3, float %f5) + ret void +} + ; CHECK: inreg_if ; CHECK: fstoi %f0 ; CHECK: sub %i0 @@ -123,6 +190,15 @@ define i32 @inreg_if(float inreg %a0, ; %f0 ret i32 %rv } +; CHECK: call_inreg_if +; CHECK: fmovs %f3, %f0 +; CHECK: or %g0, %i2, %o0 +; CHECK: call inreg_if +define void @call_inreg_if(i32* %p, float %f3, i32 %i2) { + %x = call i32 @inreg_if(float %f3, i32 %i2) + ret void +} + ; The frontend shouldn't do this. Just pass i64 instead. ; CHECK: inreg_ii ; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]] @@ -133,6 +209,16 @@ define i32 @inreg_ii(i32 inreg %a0, ; high bits of %i0 ret i32 %rv } +; CHECK: call_inreg_ii +; CHECK: srl %i2, 0, [[R2:%[gilo][0-7]]] +; CHECK: sllx %i1, 32, [[R1:%[gilo][0-7]]] +; CHECK: or [[R1]], [[R2]], %o0 +; CHECK: call inreg_ii +define void @call_inreg_ii(i32* %p, i32 %i1, i32 %i2) { + %x = call i32 @inreg_ii(i32 %i1, i32 %i2) + ret void +} + ; Structs up to 32 bytes in size can be returned in registers. ; CHECK: ret_i64_pair ; CHECK: ldx [%i2], %i0 @@ -146,6 +232,20 @@ define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) { ret { i64, i64 } %rv2 } +; CHECK: call_ret_i64_pair +; CHECK: call ret_i64_pair +; CHECK: stx %o0, [%i0] +; CHECK: stx %o1, [%i0] +define void @call_ret_i64_pair(i64* %i0) { + %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef, + i64* undef, i64* undef) + %e0 = extractvalue { i64, i64 } %rv, 0 + store i64 %e0, i64* %i0 + %e1 = extractvalue { i64, i64 } %rv, 1 + store i64 %e1, i64* %i0 + ret void +} + ; This is not a C struct, each member uses 8 bytes. ; CHECK: ret_i32_float_pair ; CHECK: ld [%i2], %i0 @@ -160,6 +260,20 @@ define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1, ret { i32, float } %rv2 } +; CHECK: call_ret_i32_float_pair +; CHECK: call ret_i32_float_pair +; CHECK: st %o0, [%i0] +; CHECK: st %f3, [%i1] +define void @call_ret_i32_float_pair(i32* %i0, float* %i1) { + %rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef, + i32* undef, float* undef) + %e0 = extractvalue { i32, float } %rv, 0 + store i32 %e0, i32* %i0 + %e1 = extractvalue { i32, float } %rv, 1 + store float %e1, float* %i1 + ret void +} + ; This is a C struct, each member uses 4 bytes. ; CHECK: ret_i32_float_packed ; CHECK: ld [%i2], [[R:%[gilo][0-7]]] @@ -175,6 +289,21 @@ define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1, ret { i32, float } %rv2 } +; CHECK: call_ret_i32_float_packed +; CHECK: call ret_i32_float_packed +; CHECK: srlx %o0, 32, [[R:%[gilo][0-7]]] +; CHECK: st [[R]], [%i0] +; CHECK: st %f1, [%i1] +define void @call_ret_i32_float_packed(i32* %i0, float* %i1) { + %rv = call { i32, float } @ret_i32_float_packed(i32 undef, i32 undef, + i32* undef, float* undef) + %e0 = extractvalue { i32, float } %rv, 0 + store i32 %e0, i32* %i0 + %e1 = extractvalue { i32, float } %rv, 1 + store float %e1, float* %i1 + ret void +} + ; The C frontend should use i64 to return { i32, i32 } structs, but verify that ; we don't miscompile thi case where both struct elements are placed in %i0. ; CHECK: ret_i32_packed @@ -192,6 +321,21 @@ define inreg { i32, i32 } @ret_i32_packed(i32 %a0, i32 %a1, ret { i32, i32 } %rv2 } +; CHECK: call_ret_i32_packed +; CHECK: call ret_i32_packed +; CHECK: srlx %o0, 32, [[R:%[gilo][0-7]]] +; CHECK: st [[R]], [%i0] +; CHECK: st %o0, [%i1] +define void @call_ret_i32_packed(i32* %i0, i32* %i1) { + %rv = call { i32, i32 } @ret_i32_packed(i32 undef, i32 undef, + i32* undef, i32* undef) + %e0 = extractvalue { i32, i32 } %rv, 0 + store i32 %e0, i32* %i0 + %e1 = extractvalue { i32, i32 } %rv, 1 + store i32 %e1, i32* %i1 + ret void +} + ; The return value must be sign-extended to 64 bits. ; CHECK: ret_sext ; CHECK: sra %i0, 0, %i0 |