1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC %s 3; RUN: llc < %s -mtriple=sparc64 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC64 %s 4 5;; Structs up to six registers in size can be returned in registers. 6;; Note that the maximum return size and member placement is NOT 7;; compatible with the C ABI - see SparcCallingConv.td. 8define { i32, i32 } @ret_i32_pair(i32 %a0, i32 %a1, ptr %p, ptr %q) { 9; SPARC-LABEL: ret_i32_pair: 10; SPARC: .cfi_startproc 11; SPARC-NEXT: ! %bb.0: 12; SPARC-NEXT: save %sp, -96, %sp 13; SPARC-NEXT: .cfi_def_cfa_register %fp 14; SPARC-NEXT: .cfi_window_save 15; SPARC-NEXT: .cfi_register %o7, %i7 16; SPARC-NEXT: ld [%i2], %i0 17; SPARC-NEXT: st %g0, [%i2] 18; SPARC-NEXT: ld [%i3], %i1 19; SPARC-NEXT: restore 20; SPARC-NEXT: retl 21; SPARC-NEXT: nop 22; 23; SPARC64-LABEL: ret_i32_pair: 24; SPARC64: .cfi_startproc 25; SPARC64-NEXT: ! %bb.0: 26; SPARC64-NEXT: save %sp, -128, %sp 27; SPARC64-NEXT: .cfi_def_cfa_register %fp 28; SPARC64-NEXT: .cfi_window_save 29; SPARC64-NEXT: .cfi_register %o7, %i7 30; SPARC64-NEXT: ld [%i2], %i0 31; SPARC64-NEXT: st %g0, [%i2] 32; SPARC64-NEXT: ld [%i3], %i1 33; SPARC64-NEXT: restore 34; SPARC64-NEXT: retl 35; SPARC64-NEXT: nop 36 %r1 = load i32, ptr %p 37 %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 0 38 store i32 0, ptr %p 39 %r2 = load i32, ptr %q 40 %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 1 41 ret { i32, i32 } %rv2 42} 43 44define void @call_ret_i32_pair(ptr %i0) { 45; SPARC-LABEL: call_ret_i32_pair: 46; SPARC: .cfi_startproc 47; SPARC-NEXT: ! %bb.0: 48; SPARC-NEXT: save %sp, -96, %sp 49; SPARC-NEXT: .cfi_def_cfa_register %fp 50; SPARC-NEXT: .cfi_window_save 51; SPARC-NEXT: .cfi_register %o7, %i7 52; SPARC-NEXT: call ret_i32_pair 53; SPARC-NEXT: nop 54; SPARC-NEXT: st %o0, [%i0] 55; SPARC-NEXT: st %o1, [%i0] 56; SPARC-NEXT: restore 57; SPARC-NEXT: retl 58; SPARC-NEXT: nop 59; 60; SPARC64-LABEL: call_ret_i32_pair: 61; SPARC64: .cfi_startproc 62; SPARC64-NEXT: ! %bb.0: 63; SPARC64-NEXT: save %sp, -176, %sp 64; SPARC64-NEXT: .cfi_def_cfa_register %fp 65; SPARC64-NEXT: .cfi_window_save 66; SPARC64-NEXT: .cfi_register %o7, %i7 67; SPARC64-NEXT: call ret_i32_pair 68; SPARC64-NEXT: nop 69; SPARC64-NEXT: st %o0, [%i0] 70; SPARC64-NEXT: st %o1, [%i0] 71; SPARC64-NEXT: restore 72; SPARC64-NEXT: retl 73; SPARC64-NEXT: nop 74 %rv = call { i32, i32 } @ret_i32_pair(i32 undef, i32 undef, 75 ptr undef, ptr undef) 76 %e0 = extractvalue { i32, i32 } %rv, 0 77 store volatile i32 %e0, ptr %i0 78 %e1 = extractvalue { i32, i32 } %rv, 1 79 store i32 %e1, ptr %i0 80 ret void 81} 82 83;; Functions returning structs more than six registers' worth of space 84;; should be automatically treated as an sret function. 85declare { [16 x i32] } @ret_i32_arr(i32 %input) 86 87define i32 @call_ret_i32_arr(i32 %0) { 88; SPARC-LABEL: call_ret_i32_arr: 89; SPARC: .cfi_startproc 90; SPARC-NEXT: ! %bb.0: 91; SPARC-NEXT: save %sp, -160, %sp 92; SPARC-NEXT: .cfi_def_cfa_register %fp 93; SPARC-NEXT: .cfi_window_save 94; SPARC-NEXT: .cfi_register %o7, %i7 95; SPARC-NEXT: add %fp, -64, %i1 96; SPARC-NEXT: st %i1, [%sp+64] 97; SPARC-NEXT: mov %i0, %o0 98; SPARC-NEXT: call ret_i32_arr 99; SPARC-NEXT: nop 100; SPARC-NEXT: unimp 64 101; SPARC-NEXT: ld [%fp+-4], %i0 102; SPARC-NEXT: restore 103; SPARC-NEXT: retl 104; SPARC-NEXT: nop 105; 106; SPARC64-LABEL: call_ret_i32_arr: 107; SPARC64: .cfi_startproc 108; SPARC64-NEXT: ! %bb.0: 109; SPARC64-NEXT: save %sp, -240, %sp 110; SPARC64-NEXT: .cfi_def_cfa_register %fp 111; SPARC64-NEXT: .cfi_window_save 112; SPARC64-NEXT: .cfi_register %o7, %i7 113; SPARC64-NEXT: add %fp, 1983, %o0 114; SPARC64-NEXT: mov %i0, %o1 115; SPARC64-NEXT: call ret_i32_arr 116; SPARC64-NEXT: nop 117; SPARC64-NEXT: ld [%fp+2043], %i0 118; SPARC64-NEXT: restore 119; SPARC64-NEXT: retl 120; SPARC64-NEXT: nop 121 %2 = call { [16 x i32] } @ret_i32_arr(i32 %0) 122 %3 = extractvalue { [16 x i32] } %2, 0 123 %4 = extractvalue [16 x i32] %3, 15 124 ret i32 %4 125} 126 127;; Structs up to six registers in size can be returned in registers. 128;; Note that the maximum return size and member placement is NOT 129;; compatible with the C ABI - see SparcCallingConv.td. 130define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, ptr %p, ptr %q) { 131; SPARC-LABEL: ret_i64_pair: 132; SPARC: .cfi_startproc 133; SPARC-NEXT: ! %bb.0: 134; SPARC-NEXT: save %sp, -96, %sp 135; SPARC-NEXT: .cfi_def_cfa_register %fp 136; SPARC-NEXT: .cfi_window_save 137; SPARC-NEXT: .cfi_register %o7, %i7 138; SPARC-NEXT: mov %g0, %i4 139; SPARC-NEXT: ldd [%i2], %i0 140; SPARC-NEXT: mov %g0, %i5 141; SPARC-NEXT: std %i4, [%i2] 142; SPARC-NEXT: ldd [%i3], %i2 143; SPARC-NEXT: restore 144; SPARC-NEXT: retl 145; SPARC-NEXT: nop 146; 147; SPARC64-LABEL: ret_i64_pair: 148; SPARC64: .cfi_startproc 149; SPARC64-NEXT: ! %bb.0: 150; SPARC64-NEXT: save %sp, -128, %sp 151; SPARC64-NEXT: .cfi_def_cfa_register %fp 152; SPARC64-NEXT: .cfi_window_save 153; SPARC64-NEXT: .cfi_register %o7, %i7 154; SPARC64-NEXT: ldx [%i2], %i0 155; SPARC64-NEXT: stx %g0, [%i2] 156; SPARC64-NEXT: ldx [%i3], %i1 157; SPARC64-NEXT: restore 158; SPARC64-NEXT: retl 159; SPARC64-NEXT: nop 160 %r1 = load i64, ptr %p 161 %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0 162 store i64 0, ptr %p 163 %r2 = load i64, ptr %q 164 %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1 165 ret { i64, i64 } %rv2 166} 167 168define void @call_ret_i64_pair(ptr %i0) { 169; SPARC-LABEL: call_ret_i64_pair: 170; SPARC: .cfi_startproc 171; SPARC-NEXT: ! %bb.0: 172; SPARC-NEXT: save %sp, -96, %sp 173; SPARC-NEXT: .cfi_def_cfa_register %fp 174; SPARC-NEXT: .cfi_window_save 175; SPARC-NEXT: .cfi_register %o7, %i7 176; SPARC-NEXT: call ret_i64_pair 177; SPARC-NEXT: nop 178; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1 179; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3 180; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1 181; SPARC-NEXT: std %o0, [%i0] 182; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3 183; SPARC-NEXT: std %o2, [%i0] 184; SPARC-NEXT: restore 185; SPARC-NEXT: retl 186; SPARC-NEXT: nop 187; 188; SPARC64-LABEL: call_ret_i64_pair: 189; SPARC64: .cfi_startproc 190; SPARC64-NEXT: ! %bb.0: 191; SPARC64-NEXT: save %sp, -176, %sp 192; SPARC64-NEXT: .cfi_def_cfa_register %fp 193; SPARC64-NEXT: .cfi_window_save 194; SPARC64-NEXT: .cfi_register %o7, %i7 195; SPARC64-NEXT: call ret_i64_pair 196; SPARC64-NEXT: nop 197; SPARC64-NEXT: stx %o0, [%i0] 198; SPARC64-NEXT: stx %o1, [%i0] 199; SPARC64-NEXT: restore 200; SPARC64-NEXT: retl 201; SPARC64-NEXT: nop 202 %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef, 203 ptr undef, ptr undef) 204 %e0 = extractvalue { i64, i64 } %rv, 0 205 store volatile i64 %e0, ptr %i0 206 %e1 = extractvalue { i64, i64 } %rv, 1 207 store i64 %e1, ptr %i0 208 ret void 209} 210 211;; Functions returning structs more than six registers' worth of space 212;; should be automatically treated as an sret function. 213declare { [16 x i64] } @ret_i64_arr(i64 %input) 214 215define i64 @call_ret_i64_arr(i64 %0) { 216; SPARC-LABEL: call_ret_i64_arr: 217; SPARC: .cfi_startproc 218; SPARC-NEXT: ! %bb.0: 219; SPARC-NEXT: save %sp, -224, %sp 220; SPARC-NEXT: .cfi_def_cfa_register %fp 221; SPARC-NEXT: .cfi_window_save 222; SPARC-NEXT: .cfi_register %o7, %i7 223; SPARC-NEXT: add %fp, -128, %i2 224; SPARC-NEXT: st %i2, [%sp+64] 225; SPARC-NEXT: mov %i0, %o0 226; SPARC-NEXT: mov %i1, %o1 227; SPARC-NEXT: call ret_i64_arr 228; SPARC-NEXT: nop 229; SPARC-NEXT: unimp 128 230; SPARC-NEXT: ldd [%fp+-8], %i0 231; SPARC-NEXT: restore 232; SPARC-NEXT: retl 233; SPARC-NEXT: nop 234; 235; SPARC64-LABEL: call_ret_i64_arr: 236; SPARC64: .cfi_startproc 237; SPARC64-NEXT: ! %bb.0: 238; SPARC64-NEXT: save %sp, -304, %sp 239; SPARC64-NEXT: .cfi_def_cfa_register %fp 240; SPARC64-NEXT: .cfi_window_save 241; SPARC64-NEXT: .cfi_register %o7, %i7 242; SPARC64-NEXT: add %fp, 1919, %o0 243; SPARC64-NEXT: mov %i0, %o1 244; SPARC64-NEXT: call ret_i64_arr 245; SPARC64-NEXT: nop 246; SPARC64-NEXT: ldx [%fp+2039], %i0 247; SPARC64-NEXT: restore 248; SPARC64-NEXT: retl 249; SPARC64-NEXT: nop 250 %2 = call { [16 x i64] } @ret_i64_arr(i64 %0) 251 %3 = extractvalue { [16 x i64] } %2, 0 252 %4 = extractvalue [16 x i64] %3, 15 253 ret i64 %4 254} 255