1; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s | FileCheck %s 2; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s 3 4; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s | FileCheck %s 5; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s 6 7; Test how llvm handles return type of {i16, i8}. The return value will be 8; passed in %r0 and %r1. 9; CHECK-LABEL: test: 10; CHECK: bl {{.*}}gen 11; CHECK: sxth {{.*}}, r0 12; CHECK: sxtab r0, {{.*}}, r1 13; CHECK-O0-LABEL: test: 14; CHECK-O0: bl {{.*}}gen 15; CHECK-O0: sxth r0, r0 16; CHECK-O0: sxtb r1, r1 17; CHECK-O0: add r0, r0, r1 18define i16 @test(i32 %key) { 19entry: 20 %key.addr = alloca i32, align 4 21 store i32 %key, i32* %key.addr, align 4 22 %0 = load i32, i32* %key.addr, align 4 23 %call = call swiftcc { i16, i8 } @gen(i32 %0) 24 %v3 = extractvalue { i16, i8 } %call, 0 25 %v1 = sext i16 %v3 to i32 26 %v5 = extractvalue { i16, i8 } %call, 1 27 %v2 = sext i8 %v5 to i32 28 %add = add nsw i32 %v1, %v2 29 %conv = trunc i32 %add to i16 30 ret i16 %conv 31} 32 33declare swiftcc { i16, i8 } @gen(i32) 34 35; We can't pass every return value in register, instead, pass everything in 36; memroy. 37; The caller provides space for the return value and passes the address in %r0. 38; The first input argument will be in %r1. 39; CHECK-LABEL: test2: 40; CHECK: mov r1, r0 41; CHECK: mov r0, sp 42; CHECK: bl {{.*}}gen2 43; CHECK-DAG: add 44; CHECK-DAG: ldr {{.*}}, [sp, #16] 45; CHECK-DAG: add 46; CHECK-DAG: add 47; CHECK-DAG: add 48; CHECK-O0-LABEL: test2: 49; CHECK-O0: str r0 50; CHECK-O0: mov r0, sp 51; CHECK-O0: bl {{.*}}gen2 52; CHECK-O0-DAG: ldr {{.*}}, [sp] 53; CHECK-O0-DAG: ldr {{.*}}, [sp, #4] 54; CHECK-O0-DAG: ldr {{.*}}, [sp, #8] 55; CHECK-O0-DAG: ldr {{.*}}, [sp, #12] 56; CHECK-O0-DAG: ldr {{.*}}, [sp, #16] 57; CHECK-O0-DAG: add 58; CHECK-O0-DAG: add 59; CHECK-O0-DAG: add 60; CHECK-O0-DAG: add 61define i32 @test2(i32 %key) #0 { 62entry: 63 %key.addr = alloca i32, align 4 64 store i32 %key, i32* %key.addr, align 4 65 %0 = load i32, i32* %key.addr, align 4 66 %call = call swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %0) 67 68 %v3 = extractvalue { i32, i32, i32, i32, i32 } %call, 0 69 %v5 = extractvalue { i32, i32, i32, i32, i32 } %call, 1 70 %v6 = extractvalue { i32, i32, i32, i32, i32 } %call, 2 71 %v7 = extractvalue { i32, i32, i32, i32, i32 } %call, 3 72 %v8 = extractvalue { i32, i32, i32, i32, i32 } %call, 4 73 74 %add = add nsw i32 %v3, %v5 75 %add1 = add nsw i32 %add, %v6 76 %add2 = add nsw i32 %add1, %v7 77 %add3 = add nsw i32 %add2, %v8 78 ret i32 %add3 79} 80 81; The address of the return value is passed in %r0. 82; CHECK-LABEL: gen2: 83; CHECK-DAG: str r1, [r0] 84; CHECK-DAG: str r1, [r0, #4] 85; CHECK-DAG: str r1, [r0, #8] 86; CHECK-DAG: str r1, [r0, #12] 87; CHECK-DAG: str r1, [r0, #16] 88; CHECK-O0-LABEL: gen2: 89; CHECK-O0-DAG: str r1, [r0] 90; CHECK-O0-DAG: str r1, [r0, #4] 91; CHECK-O0-DAG: str r1, [r0, #8] 92; CHECK-O0-DAG: str r1, [r0, #12] 93; CHECK-O0-DAG: str r1, [r0, #16] 94define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) { 95 %Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0 96 %Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1 97 %Z2 = insertvalue { i32, i32, i32, i32, i32 } %Z, i32 %key, 2 98 %Z3 = insertvalue { i32, i32, i32, i32, i32 } %Z2, i32 %key, 3 99 %Z4 = insertvalue { i32, i32, i32, i32, i32 } %Z3, i32 %key, 4 100 ret { i32, i32, i32, i32, i32 } %Z4 101} 102 103; The return value {i32, i32, i32, i32} will be returned via registers %r0, %r1, 104; %r2, %r3. 105; CHECK-LABEL: test3: 106; CHECK: bl {{.*}}gen3 107; CHECK: add r0, r0, r1 108; CHECK: add r0, r0, r2 109; CHECK: add r0, r0, r3 110; CHECK-O0-LABEL: test3: 111; CHECK-O0: bl {{.*}}gen3 112; CHECK-O0: add r0, r0, r1 113; CHECK-O0: add r0, r0, r2 114; CHECK-O0: add r0, r0, r3 115define i32 @test3(i32 %key) #0 { 116entry: 117 %key.addr = alloca i32, align 4 118 store i32 %key, i32* %key.addr, align 4 119 %0 = load i32, i32* %key.addr, align 4 120 %call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0) 121 122 %v3 = extractvalue { i32, i32, i32, i32 } %call, 0 123 %v5 = extractvalue { i32, i32, i32, i32 } %call, 1 124 %v6 = extractvalue { i32, i32, i32, i32 } %call, 2 125 %v7 = extractvalue { i32, i32, i32, i32 } %call, 3 126 127 %add = add nsw i32 %v3, %v5 128 %add1 = add nsw i32 %add, %v6 129 %add2 = add nsw i32 %add1, %v7 130 ret i32 %add2 131} 132 133declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key) 134 135; The return value {float, float, float, float} will be returned via registers 136; s0-s3. 137; CHECK-LABEL: test4: 138; CHECK: bl _gen4 139; CHECK: vadd.f32 s0, s0, s1 140; CHECK: vadd.f32 s0, s0, s2 141; CHECK: vadd.f32 s0, s0, s3 142; CHECK-O0-LABEL: test4: 143; CHECK-O0: bl _gen4 144; CHECK-O0: vadd.f32 s0, s0, s1 145; CHECK-O0: vadd.f32 s0, s0, s2 146; CHECK-O0: vadd.f32 s0, s0, s3 147define float @test4(float %key) #0 { 148entry: 149 %key.addr = alloca float, align 4 150 store float %key, float* %key.addr, align 4 151 %0 = load float, float* %key.addr, align 4 152 %call = call swiftcc { float, float, float, float } @gen4(float %0) 153 154 %v3 = extractvalue { float, float, float, float } %call, 0 155 %v5 = extractvalue { float, float, float, float } %call, 1 156 %v6 = extractvalue { float, float, float, float } %call, 2 157 %v7 = extractvalue { float, float, float, float } %call, 3 158 159 %add = fadd float %v3, %v5 160 %add1 = fadd float %add, %v6 161 %add2 = fadd float %add1, %v7 162 ret float %add2 163} 164 165declare swiftcc { float, float, float, float } @gen4(float %key) 166 167; CHECK-LABEL: test5 168; CHECK: bl _gen5 169; CHECK: vadd.f64 [[TMP:d.*]], d0, d1 170; CHECK: vadd.f64 [[TMP]], [[TMP]], d2 171; CHECK: vadd.f64 d0, [[TMP]], d3 172define swiftcc double @test5() #0 { 173entry: 174 %call = call swiftcc { double, double, double, double } @gen5() 175 176 %v3 = extractvalue { double, double, double, double } %call, 0 177 %v5 = extractvalue { double, double, double, double } %call, 1 178 %v6 = extractvalue { double, double, double, double } %call, 2 179 %v7 = extractvalue { double, double, double, double } %call, 3 180 181 %add = fadd double %v3, %v5 182 %add1 = fadd double %add, %v6 183 %add2 = fadd double %add1, %v7 184 ret double %add2 185} 186 187declare swiftcc { double, double, double, double } @gen5() 188 189 190; CHECK-LABEL: test6 191; CHECK: bl _gen6 192; CHECK-DAG: vadd.f64 [[TMP:d.*]], d0, d1 193; CHECK-DAG: add r0, r0, r1 194; CHECK-DAG: add r0, r0, r2 195; CHECK-DAG: add r0, r0, r3 196; CHECK-DAG: vadd.f64 [[TMP]], [[TMP]], d2 197; CHECK-DAG: vadd.f64 d0, [[TMP]], d3 198define swiftcc { double, i32 } @test6() #0 { 199entry: 200 %call = call swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen6() 201 202 %v3 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 0 203 %v5 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 1 204 %v6 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 2 205 %v7 = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 3 206 %v3.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 4 207 %v5.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 5 208 %v6.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 6 209 %v7.i = extractvalue { double, double, double, double, i32, i32, i32, i32 } %call, 7 210 211 %add = fadd double %v3, %v5 212 %add1 = fadd double %add, %v6 213 %add2 = fadd double %add1, %v7 214 215 %add.i = add nsw i32 %v3.i, %v5.i 216 %add1.i = add nsw i32 %add.i, %v6.i 217 %add2.i = add nsw i32 %add1.i, %v7.i 218 219 %Y = insertvalue { double, i32 } undef, double %add2, 0 220 %Z = insertvalue { double, i32 } %Y, i32 %add2.i, 1 221 ret { double, i32} %Z 222} 223 224declare swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen6() 225 226; CHECK-LABEL: gen7 227; CHECK: mov r1, r0 228; CHECK: mov r2, r0 229; CHECK: mov r3, r0 230; CHECK: bx lr 231define swiftcc { i32, i32, i32, i32 } @gen7(i32 %key) { 232 %v0 = insertvalue { i32, i32, i32, i32 } undef, i32 %key, 0 233 %v1 = insertvalue { i32, i32, i32, i32 } %v0, i32 %key, 1 234 %v2 = insertvalue { i32, i32, i32, i32 } %v1, i32 %key, 2 235 %v3 = insertvalue { i32, i32, i32, i32 } %v2, i32 %key, 3 236 ret { i32, i32, i32, i32 } %v3 237} 238 239; CHECK-LABEL: gen9 240; CHECK: mov r1, r0 241; CHECK: mov r2, r0 242; CHECK: mov r3, r0 243; CHECK: bx lr 244define swiftcc { i8, i8, i8, i8 } @gen9(i8 %key) { 245 %v0 = insertvalue { i8, i8, i8, i8 } undef, i8 %key, 0 246 %v1 = insertvalue { i8, i8, i8, i8 } %v0, i8 %key, 1 247 %v2 = insertvalue { i8, i8, i8, i8 } %v1, i8 %key, 2 248 %v3 = insertvalue { i8, i8, i8, i8 } %v2, i8 %key, 3 249 ret { i8, i8, i8, i8 } %v3 250} 251; CHECK-LABEL: gen10 252; CHECK-DAG: vmov.f64 d1, d0 253; CHECK-DAG: mov r1, r0 254; CHECK-DAG: mov r2, r0 255; CHECK-DAG: mov r3, r0 256; CHECK-DAG: vmov.f64 d2, d0 257; CHECK-DAG: vmov.f64 d3, d0 258; CHECK-DAG: bx lr 259define swiftcc { double, double, double, double, i32, i32, i32, i32 } @gen10(double %keyd, i32 %keyi) { 260 %v0 = insertvalue { double, double, double, double, i32, i32, i32, i32 } undef, double %keyd, 0 261 %v1 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v0, double %keyd, 1 262 %v2 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v1, double %keyd, 2 263 %v3 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v2, double %keyd, 3 264 %v4 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v3, i32 %keyi, 4 265 %v5 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v4, i32 %keyi, 5 266 %v6 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v5, i32 %keyi, 6 267 %v7 = insertvalue { double, double, double, double, i32, i32, i32, i32 } %v6, i32 %keyi, 7 268 ret { double, double, double, double, i32, i32, i32, i32 } %v7 269} 270 271 272; CHECK-LABEL: test11 273; CHECK: bl _gen11 274; CHECK: vadd.f32 [[TMP:q.*]], q0, q1 275; CHECK: vadd.f32 [[TMP]], [[TMP]], q2 276; CHECK: vadd.f32 q0, [[TMP]], q3 277define swiftcc <4 x float> @test11() #0 { 278entry: 279 %call = call swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @gen11() 280 281 %v3 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 0 282 %v5 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 1 283 %v6 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 2 284 %v7 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %call, 3 285 286 %add = fadd <4 x float> %v3, %v5 287 %add1 = fadd <4 x float> %add, %v6 288 %add2 = fadd <4 x float> %add1, %v7 289 ret <4 x float> %add2 290} 291 292declare swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @gen11() 293 294; CHECK-LABEL: test12 295; CHECK-DAG: vadd.f32 [[TMP:q.*]], q0, q1 296; CHECK-DAG: vmov.f32 s4, s12 297; CHECK-DAG: vadd.f32 q0, [[TMP]], q2 298define swiftcc { <4 x float>, float } @test12() #0 { 299entry: 300 %call = call swiftcc { <4 x float>, <4 x float>, <4 x float>, float } @gen12() 301 302 %v3 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 0 303 %v5 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 1 304 %v6 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 2 305 %v8 = extractvalue { <4 x float>, <4 x float>, <4 x float>, float } %call, 3 306 307 %add = fadd <4 x float> %v3, %v5 308 %add1 = fadd <4 x float> %add, %v6 309 %res.0 = insertvalue { <4 x float>, float } undef, <4 x float> %add1, 0 310 %res = insertvalue { <4 x float>, float } %res.0, float %v8, 1 311 ret { <4 x float>, float } %res 312} 313 314declare swiftcc { <4 x float>, <4 x float>, <4 x float>, float } @gen12() 315