|  | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
|  | ; RUN: llc < %s -mtriple=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC %s | 
|  | ; RUN: llc < %s -mtriple=sparc64 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC64 %s | 
|  |  | 
|  | ;; Structs up to six registers in size can be returned in registers. | 
|  | ;; Note that the maximum return size and member placement is NOT | 
|  | ;; compatible with the C ABI - see SparcCallingConv.td. | 
|  | define { i32, i32 } @ret_i32_pair(i32 %a0, i32 %a1, i32* %p, i32* %q) { | 
|  | ; SPARC-LABEL: ret_i32_pair: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -96, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    ld [%i2], %i0 | 
|  | ; SPARC-NEXT:    st %g0, [%i2] | 
|  | ; SPARC-NEXT:    ld [%i3], %i1 | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: ret_i32_pair: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -128, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    ld [%i2], %i0 | 
|  | ; SPARC64-NEXT:    st %g0, [%i2] | 
|  | ; SPARC64-NEXT:    ld [%i3], %i1 | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %r1 = load i32, i32* %p | 
|  | %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 0 | 
|  | store i32 0, i32* %p | 
|  | %r2 = load i32, i32* %q | 
|  | %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 1 | 
|  | ret { i32, i32 } %rv2 | 
|  | } | 
|  |  | 
|  | define void @call_ret_i32_pair(i32* %i0) { | 
|  | ; SPARC-LABEL: call_ret_i32_pair: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -96, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    call ret_i32_pair | 
|  | ; SPARC-NEXT:    nop | 
|  | ; SPARC-NEXT:    st %o0, [%i0] | 
|  | ; SPARC-NEXT:    st %o1, [%i0] | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: call_ret_i32_pair: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -176, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    call ret_i32_pair | 
|  | ; SPARC64-NEXT:    nop | 
|  | ; SPARC64-NEXT:    st %o0, [%i0] | 
|  | ; SPARC64-NEXT:    st %o1, [%i0] | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %rv = call { i32, i32 } @ret_i32_pair(i32 undef, i32 undef, | 
|  | i32* undef, i32* undef) | 
|  | %e0 = extractvalue { i32, i32 } %rv, 0 | 
|  | store volatile i32 %e0, i32* %i0 | 
|  | %e1 = extractvalue { i32, i32 } %rv, 1 | 
|  | store i32 %e1, i32* %i0 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ;; Functions returning structs more than six registers' worth of space | 
|  | ;; should be automatically treated as an sret function. | 
|  | declare { [16 x i32] } @ret_i32_arr(i32 %input) | 
|  |  | 
|  | define i32 @call_ret_i32_arr(i32 %0) { | 
|  | ; SPARC-LABEL: call_ret_i32_arr: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -160, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    add %fp, -64, %i1 | 
|  | ; SPARC-NEXT:    st %i1, [%sp+64] | 
|  | ; SPARC-NEXT:    mov %i0, %o0 | 
|  | ; SPARC-NEXT:    call ret_i32_arr | 
|  | ; SPARC-NEXT:    nop | 
|  | ; SPARC-NEXT:    unimp 64 | 
|  | ; SPARC-NEXT:    ld [%fp+-4], %i0 | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: call_ret_i32_arr: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -240, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    add %fp, 1983, %o0 | 
|  | ; SPARC64-NEXT:    mov %i0, %o1 | 
|  | ; SPARC64-NEXT:    call ret_i32_arr | 
|  | ; SPARC64-NEXT:    nop | 
|  | ; SPARC64-NEXT:    ld [%fp+2043], %i0 | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %2 = call { [16 x i32] } @ret_i32_arr(i32 %0) | 
|  | %3 = extractvalue { [16 x i32] } %2, 0 | 
|  | %4 = extractvalue [16 x i32] %3, 15 | 
|  | ret i32 %4 | 
|  | } | 
|  |  | 
|  | ;; Structs up to six registers in size can be returned in registers. | 
|  | ;; Note that the maximum return size and member placement is NOT | 
|  | ;; compatible with the C ABI - see SparcCallingConv.td. | 
|  | define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, i64* %p, i64* %q) { | 
|  | ; SPARC-LABEL: ret_i64_pair: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -96, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    mov %g0, %i4 | 
|  | ; SPARC-NEXT:    ldd [%i2], %i0 | 
|  | ; SPARC-NEXT:    mov %g0, %i5 | 
|  | ; SPARC-NEXT:    std %i4, [%i2] | 
|  | ; SPARC-NEXT:    ldd [%i3], %i2 | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: ret_i64_pair: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -128, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    ldx [%i2], %i0 | 
|  | ; SPARC64-NEXT:    stx %g0, [%i2] | 
|  | ; SPARC64-NEXT:    ldx [%i3], %i1 | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %r1 = load i64, i64* %p | 
|  | %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0 | 
|  | store i64 0, i64* %p | 
|  | %r2 = load i64, i64* %q | 
|  | %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1 | 
|  | ret { i64, i64 } %rv2 | 
|  | } | 
|  |  | 
|  | define void @call_ret_i64_pair(i64* %i0) { | 
|  | ; SPARC-LABEL: call_ret_i64_pair: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -96, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    call ret_i64_pair | 
|  | ; SPARC-NEXT:    nop | 
|  | ; SPARC-NEXT:    ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1 | 
|  | ; SPARC-NEXT:    ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3 | 
|  | ; SPARC-NEXT:    ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1 | 
|  | ; SPARC-NEXT:    std %o0, [%i0] | 
|  | ; SPARC-NEXT:    ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3 | 
|  | ; SPARC-NEXT:    std %o2, [%i0] | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: call_ret_i64_pair: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -176, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    call ret_i64_pair | 
|  | ; SPARC64-NEXT:    nop | 
|  | ; SPARC64-NEXT:    stx %o0, [%i0] | 
|  | ; SPARC64-NEXT:    stx %o1, [%i0] | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef, | 
|  | i64* undef, i64* undef) | 
|  | %e0 = extractvalue { i64, i64 } %rv, 0 | 
|  | store volatile i64 %e0, i64* %i0 | 
|  | %e1 = extractvalue { i64, i64 } %rv, 1 | 
|  | store i64 %e1, i64* %i0 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ;; Functions returning structs more than six registers' worth of space | 
|  | ;; should be automatically treated as an sret function. | 
|  | declare { [16 x i64] } @ret_i64_arr(i64 %input) | 
|  |  | 
|  | define i64 @call_ret_i64_arr(i64 %0) { | 
|  | ; SPARC-LABEL: call_ret_i64_arr: | 
|  | ; SPARC:         .cfi_startproc | 
|  | ; SPARC-NEXT:  ! %bb.0: | 
|  | ; SPARC-NEXT:    save %sp, -224, %sp | 
|  | ; SPARC-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC-NEXT:    .cfi_window_save | 
|  | ; SPARC-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC-NEXT:    add %fp, -128, %i2 | 
|  | ; SPARC-NEXT:    st %i2, [%sp+64] | 
|  | ; SPARC-NEXT:    mov %i0, %o0 | 
|  | ; SPARC-NEXT:    mov %i1, %o1 | 
|  | ; SPARC-NEXT:    call ret_i64_arr | 
|  | ; SPARC-NEXT:    nop | 
|  | ; SPARC-NEXT:    unimp 128 | 
|  | ; SPARC-NEXT:    ldd [%fp+-8], %i0 | 
|  | ; SPARC-NEXT:    restore | 
|  | ; SPARC-NEXT:    retl | 
|  | ; SPARC-NEXT:    nop | 
|  | ; | 
|  | ; SPARC64-LABEL: call_ret_i64_arr: | 
|  | ; SPARC64:         .cfi_startproc | 
|  | ; SPARC64-NEXT:  ! %bb.0: | 
|  | ; SPARC64-NEXT:    save %sp, -304, %sp | 
|  | ; SPARC64-NEXT:    .cfi_def_cfa_register %fp | 
|  | ; SPARC64-NEXT:    .cfi_window_save | 
|  | ; SPARC64-NEXT:    .cfi_register %o7, %i7 | 
|  | ; SPARC64-NEXT:    add %fp, 1919, %o0 | 
|  | ; SPARC64-NEXT:    mov %i0, %o1 | 
|  | ; SPARC64-NEXT:    call ret_i64_arr | 
|  | ; SPARC64-NEXT:    nop | 
|  | ; SPARC64-NEXT:    ldx [%fp+2039], %i0 | 
|  | ; SPARC64-NEXT:    restore | 
|  | ; SPARC64-NEXT:    retl | 
|  | ; SPARC64-NEXT:    nop | 
|  | %2 = call { [16 x i64] } @ret_i64_arr(i64 %0) | 
|  | %3 = extractvalue { [16 x i64] } %2, 0 | 
|  | %4 = extractvalue [16 x i64] %3, 15 | 
|  | ret i64 %4 | 
|  | } |