diff options
Diffstat (limited to 'test/CodeGen/SPARC')
-rw-r--r-- | test/CodeGen/SPARC/64abi.ll | 378 | ||||
-rw-r--r-- | test/CodeGen/SPARC/64bit.ll | 37 | ||||
-rw-r--r-- | test/CodeGen/SPARC/constpool.ll | 48 | ||||
-rw-r--r-- | test/CodeGen/SPARC/globals.ll | 50 | ||||
-rw-r--r-- | test/CodeGen/SPARC/varargs.ll | 75 |
5 files changed, 588 insertions, 0 deletions
diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll new file mode 100644 index 0000000..ec97135 --- /dev/null +++ b/test/CodeGen/SPARC/64abi.ll @@ -0,0 +1,378 @@ +; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler | FileCheck %s + +; CHECK: intarg +; The save/restore frame is not strictly necessary here, but we would need to +; refer to %o registers instead. +; CHECK: save %sp, -128, %sp +; CHECK: stb %i0, [%i4] +; CHECK: stb %i1, [%i4] +; CHECK: sth %i2, [%i4] +; CHECK: st %i3, [%i4] +; CHECK: stx %i4, [%i4] +; CHECK: st %i5, [%i4] +; CHECK: ld [%fp+2227], [[R:%[gilo][0-7]]] +; CHECK: st [[R]], [%i4] +; CHECK: ldx [%fp+2231], [[R:%[gilo][0-7]]] +; CHECK: stx [[R]], [%i4] +; CHECK: restore +define void @intarg(i8 %a0, ; %i0 + i8 %a1, ; %i1 + i16 %a2, ; %i2 + i32 %a3, ; %i3 + i8* %a4, ; %i4 + i32 %a5, ; %i5 + i32 signext %a6, ; [%fp+BIAS+176] + i8* %a7) { ; [%fp+BIAS+184] + store i8 %a0, i8* %a4 + store i8 %a1, i8* %a4 + %p16 = bitcast i8* %a4 to i16* + store i16 %a2, i16* %p16 + %p32 = bitcast i8* %a4 to i32* + store i32 %a3, i32* %p32 + %pp = bitcast i8* %a4 to i8** + store i8* %a4, i8** %pp + store i32 %a5, i32* %p32 + store i32 %a6, i32* %p32 + store i8* %a7, i8** %pp + ret void +} + +; CHECK: call_intarg +; 16 saved + 8 args. +; CHECK: save %sp, -192, %sp +; 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 +; CHECK-NOT: add %sp +; CHECK: restore +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: save %sp, -128, %sp +; CHECK: fstod %f1, +; CHECK: faddd %f2, +; CHECK: faddd %f4, +; CHECK: faddd %f6, +; CHECK: ld [%fp+2307], [[F:%f[0-9]+]] +; CHECK: fadds %f31, [[F]] +define double @floatarg(float %a0, ; %f1 + double %a1, ; %d2 + double %a2, ; %d4 + double %a3, ; %d6 + float %a4, ; %f9 + float %a5, ; %f11 + float %a6, ; %f13 + float %a7, ; %f15 + float %a8, ; %f17 + float %a9, ; %f19 + float %a10, ; %f21 + float %a11, ; %f23 + float %a12, ; %f25 + float %a13, ; %f27 + float %a14, ; %f29 + float %a15, ; %f31 + float %a16, ; [%fp+BIAS+256] (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 + %s3 = fadd double %a3, %s2 + %s16 = fadd float %a15, %a16 + %d16 = fpext float %s16 to double + %s17 = fadd double %d16, %s3 + ret double %s17 +} + +; CHECK: call_floatarg +; CHECK: save %sp, -272, %sp +; 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 +; CHECK-NOT: add %sp +; CHECK: restore +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 +; CHECK: faddd %f16 +; CHECK: ldx [%fp+2231] +; CHECK: ldx [%fp+2247] +define void @mixedarg(i8 %a0, ; %i0 + float %a1, ; %f3 + i16 %a2, ; %i2 + double %a3, ; %d6 + i13 %a4, ; %i4 + float %a5, ; %f11 + i64 %a6, ; [%fp+BIAS+176] + double *%a7, ; [%fp+BIAS+184] + double %a8, ; %d16 + i16* %a9) { ; [%fp+BIAS+200] + %d1 = fpext float %a1 to double + %s3 = fadd double %a3, %d1 + %s8 = fadd double %a8, %s3 + store double %s8, double* %a7 + store i16 %a2, i16* %a9 + 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 +; CHECK-NOT: add %sp +; CHECK: restore +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 +; CHECK: fstoi %f1 +; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]] +; CHECK: sub [[R]], +define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0 + float inreg %a1) { ; %f1 + %b1 = fptosi float %a1 to i32 + %rv = sub i32 %a0, %b1 + ret i32 %rv +} + +; CHECK: call_inreg_fi +; Allocate space for 6 arguments, even when only 2 are used. +; CHECK: save %sp, -176, %sp +; 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 + float inreg %a1) { ; %f1 + %rv = fsub float %a0, %a1 + 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 +define i32 @inreg_if(float inreg %a0, ; %f0 + i32 inreg %a1) { ; low bits of %i0 + %b0 = fptosi float %a0 to i32 + %rv = sub i32 %a1, %b0 + 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]]] +; CHECK: sub %i0, [[R]], %i0 +define i32 @inreg_ii(i32 inreg %a0, ; high bits of %i0 + i32 inreg %a1) { ; low bits of %i0 + %rv = sub i32 %a1, %a0 + 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 +; CHECK: ldx [%i3], %i1 +define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) { + %r1 = load i64* %p + %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0 + store i64 0, i64* %p + %r2 = load i64* %q + %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1 + 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 +; CHECK: ld [%i3], %f3 +define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1, + i32* %p, float* %q) { + %r1 = load i32* %p + %rv1 = insertvalue { i32, float } undef, i32 %r1, 0 + store i32 0, i32* %p + %r2 = load float* %q + %rv2 = insertvalue { i32, float } %rv1, float %r2, 1 + 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]]] +; CHECK: sllx [[R]], 32, %i0 +; CHECK: ld [%i3], %f1 +define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1, + i32* %p, float* %q) { + %r1 = load i32* %p + %rv1 = insertvalue { i32, float } undef, i32 %r1, 0 + store i32 0, i32* %p + %r2 = load float* %q + %rv2 = insertvalue { i32, float } %rv1, float %r2, 1 + 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 +; CHECK: ld [%i2], [[R1:%[gilo][0-7]]] +; CHECK: ld [%i3], [[R2:%[gilo][0-7]]] +; CHECK: sllx [[R2]], 32, [[R3:%[gilo][0-7]]] +; CHECK: or [[R3]], [[R1]], %i0 +define inreg { i32, i32 } @ret_i32_packed(i32 %a0, i32 %a1, + i32* %p, i32* %q) { + %r1 = load i32* %p + %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 1 + store i32 0, i32* %p + %r2 = load i32* %q + %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 0 + 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 +define signext i32 @ret_sext(i32 %a0) { + ret i32 %a0 +} + +; CHECK: ret_zext +; CHECK: srl %i0, 0, %i0 +define zeroext i32 @ret_zext(i32 %a0) { + ret i32 %a0 +} + +; CHECK: ret_nosext +; CHECK-NOT: sra +define signext i32 @ret_nosext(i32 signext %a0) { + ret i32 %a0 +} + +; CHECK: ret_nozext +; CHECK-NOT: srl +define signext i32 @ret_nozext(i32 signext %a0) { + ret i32 %a0 +} diff --git a/test/CodeGen/SPARC/64bit.ll b/test/CodeGen/SPARC/64bit.ll index 0d4e191..2bbf7de 100644 --- a/test/CodeGen/SPARC/64bit.ll +++ b/test/CodeGen/SPARC/64bit.ll @@ -66,6 +66,12 @@ define i64 @ret_bigimm() { ret i64 6800754272627607872 } +; CHECK: ret_bigimm2 +; CHECK: sethi 1048576 +define i64 @ret_bigimm2() { + ret i64 4611686018427387904 ; 0x4000000000000000 +} + ; CHECK: reg_reg_alu ; CHECK: add %i0, %i1, [[R0:%[goli][0-7]]] ; CHECK: sub [[R0]], %i2, [[R1:%[goli][0-7]]] @@ -144,3 +150,34 @@ define void @stores(i64* %p, i32* %q, i16* %r, i8* %s) { ret void } + +; CHECK: promote_shifts +; CHECK: ldub [%i0], [[R:%[goli][0-7]]] +; CHECK: sll [[R]], [[R]], %i0 +define i8 @promote_shifts(i8* %p) { + %L24 = load i8* %p + %L32 = load i8* %p + %B36 = shl i8 %L24, %L32 + ret i8 %B36 +} + +; CHECK: multiply +; CHECK: mulx %i0, %i1, %i0 +define i64 @multiply(i64 %a, i64 %b) { + %r = mul i64 %a, %b + ret i64 %r +} + +; CHECK: signed_divide +; CHECK: sdivx %i0, %i1, %i0 +define i64 @signed_divide(i64 %a, i64 %b) { + %r = sdiv i64 %a, %b + ret i64 %r +} + +; CHECK: unsigned_divide +; CHECK: udivx %i0, %i1, %i0 +define i64 @unsigned_divide(i64 %a, i64 %b) { + %r = udiv i64 %a, %b + ret i64 %r +} diff --git a/test/CodeGen/SPARC/constpool.ll b/test/CodeGen/SPARC/constpool.ll new file mode 100644 index 0000000..d93a53b --- /dev/null +++ b/test/CodeGen/SPARC/constpool.ll @@ -0,0 +1,48 @@ +; RUN: llc < %s -march=sparc -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=medium | FileCheck --check-prefix=abs44 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=large | FileCheck --check-prefix=abs64 %s +; RUN: llc < %s -march=sparc -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v8pic32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v9pic32 %s + +define float @floatCP() { +entry: + ret float 1.000000e+00 +} + +; abs32: floatCP +; abs32: sethi %hi(.LCPI0_0), %[[R:[gilo][0-7]]] +; abs32: ld [%[[R]]+%lo(.LCPI0_0)], %f +; abs32: jmp %i7+8 + +; abs44: floatCP +; abs44: sethi %h44(.LCPI0_0), %[[R1:[gilo][0-7]]] +; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]] +; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] +; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1 +; abs44: jmp %i7+8 + +; abs64: floatCP +; abs64: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]] +; abs64: add %[[R1]], %lo(.LCPI0_0), %[[R2:[gilo][0-7]]] +; abs64: sethi %hh(.LCPI0_0), %[[R3:[gilo][0-7]]] +; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]] +; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] +; abs64: ld [%[[R5]]+%[[R2]]], %f1 +; abs64: jmp %i7+8 + +; v8pic32: floatCP +; v8pic32: _GLOBAL_OFFSET_TABLE_ +; v8pic32: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]] +; v8pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] +; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +; v8pic32: ld [%[[Gaddr]]], %f0 +; v8pic32: jmp %i7+8 + +; v9pic32: floatCP +; v9pic32: _GLOBAL_OFFSET_TABLE_ +; v9pic32: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]] +; v9pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] +; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +; v9pic32: ld [%[[Gaddr]]], %f1 +; v9pic32: jmp %i7+8 diff --git a/test/CodeGen/SPARC/globals.ll b/test/CodeGen/SPARC/globals.ll new file mode 100644 index 0000000..8d8de58 --- /dev/null +++ b/test/CodeGen/SPARC/globals.ll @@ -0,0 +1,50 @@ +; RUN: llc < %s -march=sparc -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=medium | FileCheck --check-prefix=abs44 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=large | FileCheck --check-prefix=abs64 %s +; RUN: llc < %s -march=sparc -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v8pic32 %s +; RUN: llc < %s -march=sparcv9 -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v9pic32 %s + +@G = external global i8 + +define zeroext i8 @loadG() { + %tmp = load i8* @G + ret i8 %tmp +} + +; abs32: loadG +; abs32: sethi %hi(G), %[[R:[gilo][0-7]]] +; abs32: ldub [%[[R]]+%lo(G)], %i0 +; abs32: jmp %i7+8 + +; abs44: loadG +; abs44: sethi %h44(G), %[[R1:[gilo][0-7]]] +; abs44: add %[[R1]], %m44(G), %[[R2:[gilo][0-7]]] +; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] +; abs44: ldub [%[[R3]]+%l44(G)], %i0 +; abs44: jmp %i7+8 + +; abs64: loadG +; abs64: sethi %hi(G), %[[R1:[gilo][0-7]]] +; abs64: add %[[R1]], %lo(G), %[[R2:[gilo][0-7]]] +; abs64: sethi %hh(G), %[[R3:[gilo][0-7]]] +; abs64: add %[[R3]], %hm(G), %[[R4:[gilo][0-7]]] +; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] +; abs64: ldub [%[[R5]]+%[[R2]]], %i0 +; abs64: jmp %i7+8 + +; v8pic32: loadG +; v8pic32: _GLOBAL_OFFSET_TABLE_ +; v8pic32: sethi %hi(G), %[[R1:[gilo][0-7]]] +; v8pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]] +; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +; v8pic32: ldub [%[[Gaddr]]], %i0 +; v8pic32: jmp %i7+8 + +; v9pic32: loadG +; v9pic32: _GLOBAL_OFFSET_TABLE_ +; v9pic32: sethi %hi(G), %[[R1:[gilo][0-7]]] +; v9pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]] +; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +; v9pic32: ldub [%[[Gaddr]]], %i0 +; v9pic32: jmp %i7+8 diff --git a/test/CodeGen/SPARC/varargs.ll b/test/CodeGen/SPARC/varargs.ll new file mode 100644 index 0000000..b13f90e --- /dev/null +++ b/test/CodeGen/SPARC/varargs.ll @@ -0,0 +1,75 @@ +; RUN: llc < %s -disable-block-placement | FileCheck %s +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32:64-S128" +target triple = "sparcv9-sun-solaris" + +; CHECK: varargsfunc +; 128 byte save ares + 1 alloca rounded up to 16 bytes alignment. +; CHECK: save %sp, -144, %sp +; Store the ... arguments to the argument array. The order is not important. +; CHECK: stx %i5, [%fp+2215] +; CHECK: stx %i4, [%fp+2207] +; CHECK: stx %i3, [%fp+2199] +; CHECK: stx %i2, [%fp+2191] +; Store the address of the ... args to %ap at %fp+BIAS+128-8 +; add %fp, 2191, [[R:[gilo][0-7]]] +; stx [[R]], [%fp+2039] +define double @varargsfunc(i8* nocapture %fmt, double %sum, ...) { +entry: + %ap = alloca i8*, align 4 + %ap1 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap1) + br label %for.cond + +for.cond: + %fmt.addr.0 = phi i8* [ %fmt, %entry ], [ %incdec.ptr, %for.cond.backedge ] + %sum.addr.0 = phi double [ %sum, %entry ], [ %sum.addr.0.be, %for.cond.backedge ] + %incdec.ptr = getelementptr inbounds i8* %fmt.addr.0, i64 1 + %0 = load i8* %fmt.addr.0, align 1 + %conv = sext i8 %0 to i32 + switch i32 %conv, label %sw.default [ + i32 105, label %sw.bb + i32 102, label %sw.bb3 + ] + +; CHECK: sw.bb +; ldx [%fp+2039], %[[AP:[gilo][0-7]]] +; add %[[AP]], 4, %[[AP2:[gilo][0-7]]] +; stx %[[AP2]], [%fp+2039] +; ld [%[[AP]]] +sw.bb: + %1 = va_arg i8** %ap, i32 + %conv2 = sitofp i32 %1 to double + br label %for.cond.backedge + +; CHECK: sw.bb3 +; ldx [%fp+2039], %[[AP:[gilo][0-7]]] +; add %[[AP]], 8, %[[AP2:[gilo][0-7]]] +; stx %[[AP2]], [%fp+2039] +; ldd [%[[AP]]] +sw.bb3: + %2 = va_arg i8** %ap, double + br label %for.cond.backedge + +for.cond.backedge: + %.pn = phi double [ %2, %sw.bb3 ], [ %conv2, %sw.bb ] + %sum.addr.0.be = fadd double %.pn, %sum.addr.0 + br label %for.cond + +sw.default: + ret double %sum.addr.0 +} + +declare void @llvm.va_start(i8*) + +@.str = private unnamed_addr constant [4 x i8] c"abc\00", align 1 + +; CHECK: call_1d +; The fixed-arg double goes in %d2, the second goes in %o2. +; CHECK: sethi 1048576 +; CHECK: , %o2 +; CHECK: , %f2 +define i32 @call_1d() #0 { +entry: + %call = call double (i8*, double, ...)* @varargsfunc(i8* undef, double 1.000000e+00, double 2.000000e+00) + ret i32 1 +} |