1; RUN: llc -march=mipsel < %s | FileCheck %s 2 3 4; Check that function accesses vector return value from stack in cases when 5; vector can't be returned in registers. Also check that caller passes in 6; register $4 stack address where the vector should be placed. 7 8 9declare <8 x i32> @i8(...) 10declare <4 x float> @f4(...) 11declare <4 x double> @d4(...) 12 13define i32 @call_i8() { 14entry: 15 %call = call <8 x i32> (...)* @i8() 16 %v0 = extractelement <8 x i32> %call, i32 0 17 %v1 = extractelement <8 x i32> %call, i32 1 18 %v2 = extractelement <8 x i32> %call, i32 2 19 %v3 = extractelement <8 x i32> %call, i32 3 20 %v4 = extractelement <8 x i32> %call, i32 4 21 %v5 = extractelement <8 x i32> %call, i32 5 22 %v6 = extractelement <8 x i32> %call, i32 6 23 %v7 = extractelement <8 x i32> %call, i32 7 24 %add1 = add i32 %v0, %v1 25 %add2 = add i32 %v2, %v3 26 %add3 = add i32 %v4, %v5 27 %add4 = add i32 %v6, %v7 28 %add5 = add i32 %add1, %add2 29 %add6 = add i32 %add3, %add4 30 %add7 = add i32 %add5, %add6 31 ret i32 %add7 32 33; CHECK-LABEL: call_i8: 34; CHECK: call16(i8) 35; CHECK: addiu $4, $sp, 32 36; CHECK: lw $[[R0:[a-z0-9]+]], 60($sp) 37; CHECK: lw $[[R1:[a-z0-9]+]], 56($sp) 38; CHECK: lw $[[R2:[a-z0-9]+]], 52($sp) 39; CHECK: lw $[[R3:[a-z0-9]+]], 48($sp) 40; CHECK: lw $[[R4:[a-z0-9]+]], 44($sp) 41; CHECK: lw $[[R5:[a-z0-9]+]], 40($sp) 42; CHECK: lw $[[R6:[a-z0-9]+]], 36($sp) 43; CHECK: lw $[[R7:[a-z0-9]+]], 32($sp) 44} 45 46 47define float @call_f4() { 48entry: 49 %call = call <4 x float> (...)* @f4() 50 %v0 = extractelement <4 x float> %call, i32 0 51 %v1 = extractelement <4 x float> %call, i32 1 52 %v2 = extractelement <4 x float> %call, i32 2 53 %v3 = extractelement <4 x float> %call, i32 3 54 %add1 = fadd float %v0, %v1 55 %add2 = fadd float %v2, %v3 56 %add3 = fadd float %add1, %add2 57 ret float %add3 58 59; CHECK-LABEL: call_f4: 60; CHECK: call16(f4) 61; CHECK: addiu $4, $sp, 16 62; CHECK: lwc1 $[[R0:[a-z0-9]+]], 28($sp) 63; CHECK: lwc1 $[[R1:[a-z0-9]+]], 24($sp) 64; CHECK: lwc1 $[[R3:[a-z0-9]+]], 20($sp) 65; CHECK: lwc1 $[[R4:[a-z0-9]+]], 16($sp) 66} 67 68 69define double @call_d4() { 70entry: 71 %call = call <4 x double> (...)* @d4() 72 %v0 = extractelement <4 x double> %call, i32 0 73 %v1 = extractelement <4 x double> %call, i32 1 74 %v2 = extractelement <4 x double> %call, i32 2 75 %v3 = extractelement <4 x double> %call, i32 3 76 %add1 = fadd double %v0, %v1 77 %add2 = fadd double %v2, %v3 78 %add3 = fadd double %add1, %add2 79 ret double %add3 80 81; CHECK-LABEL: call_d4: 82; CHECK: call16(d4) 83; CHECK: addiu $4, $sp, 32 84; CHECK: ldc1 $[[R0:[a-z0-9]+]], 56($sp) 85; CHECK: ldc1 $[[R1:[a-z0-9]+]], 48($sp) 86; CHECK: ldc1 $[[R3:[a-z0-9]+]], 40($sp) 87; CHECK: ldc1 $[[R4:[a-z0-9]+]], 32($sp) 88} 89 90 91 92; Check that function accesses vector return value from registers in cases when 93; vector can be returned in registers 94 95 96declare <4 x i32> @i4(...) 97declare <2 x float> @f2(...) 98declare <2 x double> @d2(...) 99 100define i32 @call_i4() { 101entry: 102 %call = call <4 x i32> (...)* @i4() 103 %v0 = extractelement <4 x i32> %call, i32 0 104 %v1 = extractelement <4 x i32> %call, i32 1 105 %v2 = extractelement <4 x i32> %call, i32 2 106 %v3 = extractelement <4 x i32> %call, i32 3 107 %add1 = add i32 %v0, %v1 108 %add2 = add i32 %v2, %v3 109 %add3 = add i32 %add1, %add2 110 ret i32 %add3 111 112; CHECK-LABEL: call_i4: 113; CHECK: call16(i4) 114; CHECK-NOT: lw 115; CHECK: addu $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]] 116; CHECK: addu $[[R5:[a-z0-9]+]], $[[R3:[a-z0-9]+]], $[[R4:[a-z0-9]+]] 117; CHECK: addu $[[R6:[a-z0-9]+]], $[[R5]], $[[R2]] 118} 119 120 121define float @call_f2() { 122entry: 123 %call = call <2 x float> (...)* @f2() 124 %v0 = extractelement <2 x float> %call, i32 0 125 %v1 = extractelement <2 x float> %call, i32 1 126 %add1 = fadd float %v0, %v1 127 ret float %add1 128 129; CHECK-LABEL: call_f2: 130; CHECK: call16(f2) 131; CHECK-NOT: lwc1 132; CHECK: add.s $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]] 133} 134 135 136define double @call_d2() { 137entry: 138 %call = call <2 x double> (...)* @d2() 139 %v0 = extractelement <2 x double> %call, i32 0 140 %v1 = extractelement <2 x double> %call, i32 1 141 %add1 = fadd double %v0, %v1 142 ret double %add1 143 144; CHECK-LABEL: call_d2: 145; CHECK: call16(d2) 146; CHECK-NOT: ldc1 147; CHECK: add.d $[[R2:[a-z0-9]+]], $[[R0:[a-z0-9]+]], $[[R1:[a-z0-9]+]] 148} 149 150 151 152; Check that function returns vector on stack in cases when vector can't be 153; returned in registers. Also check that vector is placed on stack starting 154; from the address in register $4. 155 156 157define <8 x i32> @return_i8() { 158entry: 159 ret <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 160 161; CHECK-LABEL: return_i8: 162; CHECK: sw $[[R0:[a-z0-9]+]], 28($4) 163; CHECK: sw $[[R1:[a-z0-9]+]], 24($4) 164; CHECK: sw $[[R2:[a-z0-9]+]], 20($4) 165; CHECK: sw $[[R3:[a-z0-9]+]], 16($4) 166; CHECK: sw $[[R4:[a-z0-9]+]], 12($4) 167; CHECK: sw $[[R5:[a-z0-9]+]], 8($4) 168; CHECK: sw $[[R6:[a-z0-9]+]], 4($4) 169; CHECK: sw $[[R7:[a-z0-9]+]], 0($4) 170} 171 172 173define <4 x float> @return_f4(float %a, float %b, float %c, float %d) { 174entry: 175 %vecins1 = insertelement <4 x float> undef, float %a, i32 0 176 %vecins2 = insertelement <4 x float> %vecins1, float %b, i32 1 177 %vecins3 = insertelement <4 x float> %vecins2, float %c, i32 2 178 %vecins4 = insertelement <4 x float> %vecins3, float %d, i32 3 179 ret <4 x float> %vecins4 180 181; CHECK-LABEL: return_f4: 182; CHECK-DAG: lwc1 $[[R0:[a-z0-9]+]], 16($sp) 183; CHECK-DAG: swc1 $[[R0]], 12($4) 184; CHECK-DAG: sw $7, 8($4) 185; CHECK-DAG: sw $6, 4($4) 186; CHECK-DAG: sw $5, 0($4) 187} 188 189 190define <4 x double> @return_d4(double %a, double %b, double %c, double %d) { 191entry: 192 %vecins1 = insertelement <4 x double> undef, double %a, i32 0 193 %vecins2 = insertelement <4 x double> %vecins1, double %b, i32 1 194 %vecins3 = insertelement <4 x double> %vecins2, double %c, i32 2 195 %vecins4 = insertelement <4 x double> %vecins3, double %d, i32 3 196 ret <4 x double> %vecins4 197 198; CHECK-LABEL: return_d4: 199; CHECK-DAG: sdc1 $[[R0:[a-z0-9]+]], 24($4) 200; CHECK-DAG: sdc1 $[[R1:[a-z0-9]+]], 16($4) 201; CHECK-DAG: sdc1 $[[R2:[a-z0-9]+]], 8($4) 202; CHECK-DAG: sdc1 $[[R3:[a-z0-9]+]], 0($4) 203} 204 205 206 207; Check that function returns vector in registers in cases when vector can be 208; returned in registers. 209 210 211define <4 x i32> @return_i4() { 212entry: 213 ret <4 x i32> <i32 0, i32 1, i32 2, i32 3> 214 215; CHECK-LABEL: return_i4: 216; CHECK: addiu $2, $zero, 0 217; CHECK: addiu $3, $zero, 1 218; CHECK: addiu $4, $zero, 2 219; CHECK: addiu $5, $zero, 3 220} 221 222 223define <2 x float> @return_f2(float %a, float %b) { 224entry: 225 %vecins1 = insertelement <2 x float> undef, float %a, i32 0 226 %vecins2 = insertelement <2 x float> %vecins1, float %b, i32 1 227 ret <2 x float> %vecins2 228 229; CHECK-LABEL: return_f2: 230; CHECK: mov.s $f0, $f12 231; CHECK: mov.s $f2, $f14 232} 233 234 235define <2 x double> @return_d2(double %a, double %b) { 236entry: 237 %vecins1 = insertelement <2 x double> undef, double %a, i32 0 238 %vecins2 = insertelement <2 x double> %vecins1, double %b, i32 1 239 ret <2 x double> %vecins2 240 241; CHECK-LABEL: return_d2: 242; CHECK: mov.d $f0, $f12 243; CHECK: mov.d $f2, $f14 244} 245