1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 2; RUN: llc -mtriple=armv7-eabi -mattr=-fpregs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ARM 3; RUN: llc -mtriple=armv7-eabi -mattr=+vfp2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-VFP 4; RUN: llc -mtriple=thumbv7-apple-darwin -mattr=+neon,+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK-NEON 5 6define i32 @f1(i32 %a.s) { 7; CHECK-LABEL: f1: 8; CHECK: @ %bb.0: @ %entry 9; CHECK-NEXT: mov r1, #3 10; CHECK-NEXT: cmp r0, #4 11; CHECK-NEXT: movweq r1, #2 12; CHECK-NEXT: mov r0, r1 13; CHECK-NEXT: bx lr 14; 15; CHECK-NEON-LABEL: f1: 16; CHECK-NEON: @ %bb.0: @ %entry 17; CHECK-NEON-NEXT: movs r1, #3 18; CHECK-NEON-NEXT: cmp r0, #4 19; CHECK-NEON-NEXT: it eq 20; CHECK-NEON-NEXT: moveq r1, #2 21; CHECK-NEON-NEXT: mov r0, r1 22; CHECK-NEON-NEXT: bx lr 23entry: 24 %tmp = icmp eq i32 %a.s, 4 25 %tmp1.s = select i1 %tmp, i32 2, i32 3 26 ret i32 %tmp1.s 27} 28 29define i32 @f2(i32 %a.s) { 30; CHECK-LABEL: f2: 31; CHECK: @ %bb.0: @ %entry 32; CHECK-NEXT: mov r1, #3 33; CHECK-NEXT: cmp r0, #4 34; CHECK-NEXT: movwgt r1, #2 35; CHECK-NEXT: mov r0, r1 36; CHECK-NEXT: bx lr 37; 38; CHECK-NEON-LABEL: f2: 39; CHECK-NEON: @ %bb.0: @ %entry 40; CHECK-NEON-NEXT: movs r1, #3 41; CHECK-NEON-NEXT: cmp r0, #4 42; CHECK-NEON-NEXT: it gt 43; CHECK-NEON-NEXT: movgt r1, #2 44; CHECK-NEON-NEXT: mov r0, r1 45; CHECK-NEON-NEXT: bx lr 46entry: 47 %tmp = icmp sgt i32 %a.s, 4 48 %tmp1.s = select i1 %tmp, i32 2, i32 3 49 ret i32 %tmp1.s 50} 51 52define i32 @f3(i32 %a.s, i32 %b.s) { 53; CHECK-LABEL: f3: 54; CHECK: @ %bb.0: @ %entry 55; CHECK-NEXT: mov r2, #3 56; CHECK-NEXT: cmp r0, r1 57; CHECK-NEXT: movwlt r2, #2 58; CHECK-NEXT: mov r0, r2 59; CHECK-NEXT: bx lr 60; 61; CHECK-NEON-LABEL: f3: 62; CHECK-NEON: @ %bb.0: @ %entry 63; CHECK-NEON-NEXT: movs r2, #3 64; CHECK-NEON-NEXT: cmp r0, r1 65; CHECK-NEON-NEXT: it lt 66; CHECK-NEON-NEXT: movlt r2, #2 67; CHECK-NEON-NEXT: mov r0, r2 68; CHECK-NEON-NEXT: bx lr 69entry: 70 %tmp = icmp slt i32 %a.s, %b.s 71 %tmp1.s = select i1 %tmp, i32 2, i32 3 72 ret i32 %tmp1.s 73} 74 75define i32 @f4(i32 %a.s, i32 %b.s) { 76; CHECK-LABEL: f4: 77; CHECK: @ %bb.0: @ %entry 78; CHECK-NEXT: mov r2, #3 79; CHECK-NEXT: cmp r0, r1 80; CHECK-NEXT: movwle r2, #2 81; CHECK-NEXT: mov r0, r2 82; CHECK-NEXT: bx lr 83; 84; CHECK-NEON-LABEL: f4: 85; CHECK-NEON: @ %bb.0: @ %entry 86; CHECK-NEON-NEXT: movs r2, #3 87; CHECK-NEON-NEXT: cmp r0, r1 88; CHECK-NEON-NEXT: it le 89; CHECK-NEON-NEXT: movle r2, #2 90; CHECK-NEON-NEXT: mov r0, r2 91; CHECK-NEON-NEXT: bx lr 92entry: 93 %tmp = icmp sle i32 %a.s, %b.s 94 %tmp1.s = select i1 %tmp, i32 2, i32 3 95 ret i32 %tmp1.s 96} 97 98define i32 @f5(i32 %a.u, i32 %b.u) { 99; CHECK-LABEL: f5: 100; CHECK: @ %bb.0: @ %entry 101; CHECK-NEXT: mov r2, #3 102; CHECK-NEXT: cmp r0, r1 103; CHECK-NEXT: movwls r2, #2 104; CHECK-NEXT: mov r0, r2 105; CHECK-NEXT: bx lr 106; 107; CHECK-NEON-LABEL: f5: 108; CHECK-NEON: @ %bb.0: @ %entry 109; CHECK-NEON-NEXT: movs r2, #3 110; CHECK-NEON-NEXT: cmp r0, r1 111; CHECK-NEON-NEXT: it ls 112; CHECK-NEON-NEXT: movls r2, #2 113; CHECK-NEON-NEXT: mov r0, r2 114; CHECK-NEON-NEXT: bx lr 115entry: 116 %tmp = icmp ule i32 %a.u, %b.u 117 %tmp1.s = select i1 %tmp, i32 2, i32 3 118 ret i32 %tmp1.s 119} 120 121define i32 @f6(i32 %a.u, i32 %b.u) { 122; CHECK-LABEL: f6: 123; CHECK: @ %bb.0: @ %entry 124; CHECK-NEXT: mov r2, #3 125; CHECK-NEXT: cmp r0, r1 126; CHECK-NEXT: movwhi r2, #2 127; CHECK-NEXT: mov r0, r2 128; CHECK-NEXT: bx lr 129; 130; CHECK-NEON-LABEL: f6: 131; CHECK-NEON: @ %bb.0: @ %entry 132; CHECK-NEON-NEXT: movs r2, #3 133; CHECK-NEON-NEXT: cmp r0, r1 134; CHECK-NEON-NEXT: it hi 135; CHECK-NEON-NEXT: movhi r2, #2 136; CHECK-NEON-NEXT: mov r0, r2 137; CHECK-NEON-NEXT: bx lr 138entry: 139 %tmp = icmp ugt i32 %a.u, %b.u 140 %tmp1.s = select i1 %tmp, i32 2, i32 3 141 ret i32 %tmp1.s 142} 143 144define double @f7(double %a, double %b) { 145; CHECK-ARM-LABEL: f7: 146; CHECK-ARM: @ %bb.0: 147; CHECK-ARM-NEXT: .save {r4, r5, r11, lr} 148; CHECK-ARM-NEXT: push {r4, r5, r11, lr} 149; CHECK-ARM-NEXT: mov r4, r3 150; CHECK-ARM-NEXT: movw r3, #48758 151; CHECK-ARM-NEXT: mov r5, r2 152; CHECK-ARM-NEXT: movw r2, #14680 153; CHECK-ARM-NEXT: movt r2, #51380 154; CHECK-ARM-NEXT: movt r3, #16371 155; CHECK-ARM-NEXT: bl __aeabi_dcmplt 156; CHECK-ARM-NEXT: cmp r0, #0 157; CHECK-ARM-NEXT: movwne r4, #0 158; CHECK-ARM-NEXT: movwne r5, #0 159; CHECK-ARM-NEXT: movtne r4, #49136 160; CHECK-ARM-NEXT: mov r0, r5 161; CHECK-ARM-NEXT: mov r1, r4 162; CHECK-ARM-NEXT: pop {r4, r5, r11, pc} 163; 164; CHECK-VFP-LABEL: f7: 165; CHECK-VFP: @ %bb.0: 166; CHECK-VFP-NEXT: vldr d17, .LCPI6_0 167; CHECK-VFP-NEXT: vmov d18, r0, r1 168; CHECK-VFP-NEXT: vmov.f64 d16, #-1.000000e+00 169; CHECK-VFP-NEXT: vcmp.f64 d18, d17 170; CHECK-VFP-NEXT: vmrs APSR_nzcv, fpscr 171; CHECK-VFP-NEXT: vmov d19, r2, r3 172; CHECK-VFP-NEXT: vmovmi.f64 d19, d16 173; CHECK-VFP-NEXT: vmov r0, r1, d19 174; CHECK-VFP-NEXT: bx lr 175; CHECK-VFP-NEXT: .p2align 3 176; CHECK-VFP-NEXT: @ %bb.1: 177; CHECK-VFP-NEXT: .LCPI6_0: 178; CHECK-VFP-NEXT: .long 3367254360 @ double 1.234 179; CHECK-VFP-NEXT: .long 1072938614 180; 181; CHECK-NEON-LABEL: f7: 182; CHECK-NEON: @ %bb.0: 183; CHECK-NEON-NEXT: vldr d17, LCPI6_0 184; CHECK-NEON-NEXT: vmov d18, r0, r1 185; CHECK-NEON-NEXT: vmov d19, r2, r3 186; CHECK-NEON-NEXT: vcmp.f64 d18, d17 187; CHECK-NEON-NEXT: vmov.f64 d16, #-1.000000e+00 188; CHECK-NEON-NEXT: vmrs APSR_nzcv, fpscr 189; CHECK-NEON-NEXT: it mi 190; CHECK-NEON-NEXT: vmovmi.f64 d19, d16 191; CHECK-NEON-NEXT: vmov r0, r1, d19 192; CHECK-NEON-NEXT: bx lr 193; CHECK-NEON-NEXT: .p2align 3 194; CHECK-NEON-NEXT: @ %bb.1: 195; CHECK-NEON-NEXT: .data_region 196; CHECK-NEON-NEXT: LCPI6_0: 197; CHECK-NEON-NEXT: .long 3367254360 @ double 1.234 198; CHECK-NEON-NEXT: .long 1072938614 199; CHECK-NEON-NEXT: .end_data_region 200 %tmp = fcmp olt double %a, 1.234e+00 201 %tmp1 = select i1 %tmp, double -1.000e+00, double %b 202 ret double %tmp1 203} 204 205; <rdar://problem/7260094> 206; 207; We used to generate really horrible code for this function. The main cause was 208; a lack of a custom lowering routine for an ISD::SELECT. This would result in 209; two "it" blocks in the code: one for the "icmp" and another to move the index 210; into the constant pool based on the value of the "icmp". If we have one "it" 211; block generated, odds are good that we have close to the ideal code for this. 212define arm_apcscc float @f8(i32 %a) nounwind { 213; CHECK-ARM-LABEL: f8: 214; CHECK-ARM: @ %bb.0: 215; CHECK-ARM-NEXT: movw r1, #29905 216; CHECK-ARM-NEXT: movw r2, #1123 217; CHECK-ARM-NEXT: movt r1, #16408 218; CHECK-ARM-NEXT: cmp r0, r2 219; CHECK-ARM-NEXT: movweq r1, #62390 220; CHECK-ARM-NEXT: movteq r1, #16285 221; CHECK-ARM-NEXT: mov r0, r1 222; CHECK-ARM-NEXT: bx lr 223; 224; CHECK-VFP-LABEL: f8: 225; CHECK-VFP: @ %bb.0: 226; CHECK-VFP-NEXT: movw r2, #1123 227; CHECK-VFP-NEXT: adr r1, .LCPI7_0 228; CHECK-VFP-NEXT: cmp r0, r2 229; CHECK-VFP-NEXT: addeq r1, r1, #4 230; CHECK-VFP-NEXT: ldr r0, [r1] 231; CHECK-VFP-NEXT: bx lr 232; CHECK-VFP-NEXT: .p2align 2 233; CHECK-VFP-NEXT: @ %bb.1: 234; CHECK-VFP-NEXT: .LCPI7_0: 235; CHECK-VFP-NEXT: .long 0x401874d1 @ float 2.38212991 236; CHECK-VFP-NEXT: .long 0x3f9df3b6 @ float 1.23399997 237; 238; CHECK-NEON-LABEL: f8: 239; CHECK-NEON: @ %bb.0: 240; CHECK-NEON-NEXT: adr r1, LCPI7_0 241; CHECK-NEON-NEXT: movw r2, #1123 242; CHECK-NEON-NEXT: cmp r0, r2 243; CHECK-NEON-NEXT: it eq 244; CHECK-NEON-NEXT: addeq r1, #4 245; CHECK-NEON-NEXT: ldr r0, [r1] 246; CHECK-NEON-NEXT: bx lr 247; CHECK-NEON-NEXT: .p2align 2 248; CHECK-NEON-NEXT: @ %bb.1: 249; CHECK-NEON-NEXT: .data_region 250; CHECK-NEON-NEXT: LCPI7_0: 251; CHECK-NEON-NEXT: .long 0x401874d1 @ float 2.38212991 252; CHECK-NEON-NEXT: .long 0x3f9df3b6 @ float 1.23399997 253; CHECK-NEON-NEXT: .end_data_region 254 %tmp = icmp eq i32 %a, 1123 255 %tmp1 = select i1 %tmp, float 0x3FF3BE76C0000000, float 0x40030E9A20000000 256 ret float %tmp1 257} 258 259; <rdar://problem/9049552> 260; Glue values can only have a single use, but the following test exposed a 261; case where a SELECT was lowered with 2 uses of a comparison, causing the 262; scheduler to assert. 263declare ptr @objc_msgSend(ptr, ptr, ...) 264define void @f9() optsize { 265; CHECK-LABEL: f9: 266; CHECK: @ %bb.0: @ %entry 267; CHECK-NEXT: .save {r11, lr} 268; CHECK-NEXT: push {r11, lr} 269; CHECK-NEXT: .pad #8 270; CHECK-NEXT: sub sp, sp, #8 271; CHECK-NEXT: movw r2, #0 272; CHECK-NEXT: movw r3, #0 273; CHECK-NEXT: mov r1, #1065353216 274; CHECK-NEXT: mov r0, #0 275; CHECK-NEXT: movt r2, #16672 276; CHECK-NEXT: movt r3, #32704 277; CHECK-NEXT: strd r0, r1, [sp] 278; CHECK-NEXT: bl objc_msgSend 279; CHECK-NEXT: add sp, sp, #8 280; CHECK-NEXT: pop {r11, pc} 281; 282; CHECK-NEON-LABEL: f9: 283; CHECK-NEON: @ %bb.0: @ %entry 284; CHECK-NEON-NEXT: str lr, [sp, #-4]! 285; CHECK-NEON-NEXT: sub sp, #8 286; CHECK-NEON-NEXT: movs r2, #0 287; CHECK-NEON-NEXT: movs r3, #0 288; CHECK-NEON-NEXT: mov.w r0, #1065353216 289; CHECK-NEON-NEXT: movs r1, #0 290; CHECK-NEON-NEXT: movt r2, #16672 291; CHECK-NEON-NEXT: movt r3, #32704 292; CHECK-NEON-NEXT: strd r1, r0, [sp] 293; CHECK-NEON-NEXT: bl _objc_msgSend 294; CHECK-NEON-NEXT: add sp, #8 295; CHECK-NEON-NEXT: ldr lr, [sp], #4 296; CHECK-NEON-NEXT: bx lr 297entry: 298 %cmp = icmp eq ptr undef, inttoptr (i32 4 to ptr) 299 %conv191 = select i1 %cmp, float -3.000000e+00, float 0.000000e+00 300 %conv195 = select i1 %cmp, double -1.000000e+00, double 0.000000e+00 301 %add = fadd double %conv195, 1.100000e+01 302 %conv196 = fptrunc double %add to float 303 %add201 = fadd float undef, %conv191 304 %tmp484 = bitcast float %conv196 to i32 305 %tmp478 = bitcast float %add201 to i32 306 %tmp490 = insertvalue [2 x i32] undef, i32 %tmp484, 0 307 %tmp493 = insertvalue [2 x i32] %tmp490, i32 %tmp478, 1 308 call void @objc_msgSend(ptr undef, ptr undef, [2 x i32] %tmp493, i32 0, float 1.000000e+00) optsize 309 ret void 310} 311 312define float @f10(i32 %a, i32 %b) nounwind uwtable readnone ssp { 313; CHECK-ARM-LABEL: f10: 314; CHECK-ARM: @ %bb.0: 315; CHECK-ARM-NEXT: mov r2, #0 316; CHECK-ARM-NEXT: cmp r0, r1 317; CHECK-ARM-NEXT: moveq r2, #1065353216 318; CHECK-ARM-NEXT: mov r0, r2 319; CHECK-ARM-NEXT: bx lr 320; 321; CHECK-VFP-LABEL: f10: 322; CHECK-VFP: @ %bb.0: 323; CHECK-VFP-NEXT: vmov.f32 s0, #1.000000e+00 324; CHECK-VFP-NEXT: vldr s2, .LCPI9_0 325; CHECK-VFP-NEXT: cmp r0, r1 326; CHECK-VFP-NEXT: vmoveq.f32 s2, s0 327; CHECK-VFP-NEXT: vmov r0, s2 328; CHECK-VFP-NEXT: bx lr 329; CHECK-VFP-NEXT: .p2align 2 330; CHECK-VFP-NEXT: @ %bb.1: 331; CHECK-VFP-NEXT: .LCPI9_0: 332; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 333; 334; CHECK-NEON-LABEL: f10: 335; CHECK-NEON: @ %bb.0: 336; CHECK-NEON-NEXT: vldr s2, LCPI9_0 337; CHECK-NEON-NEXT: vmov.f32 s0, #1.000000e+00 338; CHECK-NEON-NEXT: cmp r0, r1 339; CHECK-NEON-NEXT: it eq 340; CHECK-NEON-NEXT: vmoveq.f32 s2, s0 341; CHECK-NEON-NEXT: vmov r0, s2 342; CHECK-NEON-NEXT: bx lr 343; CHECK-NEON-NEXT: .p2align 2 344; CHECK-NEON-NEXT: @ %bb.1: 345; CHECK-NEON-NEXT: .data_region 346; CHECK-NEON-NEXT: LCPI9_0: 347; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 348; CHECK-NEON-NEXT: .end_data_region 349 %1 = icmp eq i32 %a, %b 350 %2 = zext i1 %1 to i32 351 %3 = sitofp i32 %2 to float 352 ret float %3 353} 354 355define float @f11(i32 %a, i32 %b) nounwind uwtable readnone ssp { 356; CHECK-ARM-LABEL: f11: 357; CHECK-ARM: @ %bb.0: 358; CHECK-ARM-NEXT: mov r2, #0 359; CHECK-ARM-NEXT: cmp r0, r1 360; CHECK-ARM-NEXT: movweq r2, #0 361; CHECK-ARM-NEXT: movteq r2, #49024 362; CHECK-ARM-NEXT: mov r0, r2 363; CHECK-ARM-NEXT: bx lr 364; 365; CHECK-VFP-LABEL: f11: 366; CHECK-VFP: @ %bb.0: 367; CHECK-VFP-NEXT: vmov.f32 s0, #-1.000000e+00 368; CHECK-VFP-NEXT: vldr s2, .LCPI10_0 369; CHECK-VFP-NEXT: cmp r0, r1 370; CHECK-VFP-NEXT: vmoveq.f32 s2, s0 371; CHECK-VFP-NEXT: vmov r0, s2 372; CHECK-VFP-NEXT: bx lr 373; CHECK-VFP-NEXT: .p2align 2 374; CHECK-VFP-NEXT: @ %bb.1: 375; CHECK-VFP-NEXT: .LCPI10_0: 376; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 377; 378; CHECK-NEON-LABEL: f11: 379; CHECK-NEON: @ %bb.0: 380; CHECK-NEON-NEXT: vldr s2, LCPI10_0 381; CHECK-NEON-NEXT: vmov.f32 s0, #-1.000000e+00 382; CHECK-NEON-NEXT: cmp r0, r1 383; CHECK-NEON-NEXT: it eq 384; CHECK-NEON-NEXT: vmoveq.f32 s2, s0 385; CHECK-NEON-NEXT: vmov r0, s2 386; CHECK-NEON-NEXT: bx lr 387; CHECK-NEON-NEXT: .p2align 2 388; CHECK-NEON-NEXT: @ %bb.1: 389; CHECK-NEON-NEXT: .data_region 390; CHECK-NEON-NEXT: LCPI10_0: 391; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 392; CHECK-NEON-NEXT: .end_data_region 393 %1 = icmp eq i32 %a, %b 394 %2 = sitofp i1 %1 to float 395 ret float %2 396} 397 398define float @f12(i32 %a, i32 %b) nounwind uwtable readnone ssp { 399; CHECK-ARM-LABEL: f12: 400; CHECK-ARM: @ %bb.0: 401; CHECK-ARM-NEXT: mov r2, #0 402; CHECK-ARM-NEXT: cmp r0, r1 403; CHECK-ARM-NEXT: moveq r2, #1065353216 404; CHECK-ARM-NEXT: mov r0, r2 405; CHECK-ARM-NEXT: bx lr 406; 407; CHECK-VFP-LABEL: f12: 408; CHECK-VFP: @ %bb.0: 409; CHECK-VFP-NEXT: vmov.f32 s0, #1.000000e+00 410; CHECK-VFP-NEXT: vldr s2, .LCPI11_0 411; CHECK-VFP-NEXT: cmp r0, r1 412; CHECK-VFP-NEXT: vmoveq.f32 s2, s0 413; CHECK-VFP-NEXT: vmov r0, s2 414; CHECK-VFP-NEXT: bx lr 415; CHECK-VFP-NEXT: .p2align 2 416; CHECK-VFP-NEXT: @ %bb.1: 417; CHECK-VFP-NEXT: .LCPI11_0: 418; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 419; 420; CHECK-NEON-LABEL: f12: 421; CHECK-NEON: @ %bb.0: 422; CHECK-NEON-NEXT: vldr s2, LCPI11_0 423; CHECK-NEON-NEXT: vmov.f32 s0, #1.000000e+00 424; CHECK-NEON-NEXT: cmp r0, r1 425; CHECK-NEON-NEXT: it eq 426; CHECK-NEON-NEXT: vmoveq.f32 s2, s0 427; CHECK-NEON-NEXT: vmov r0, s2 428; CHECK-NEON-NEXT: bx lr 429; CHECK-NEON-NEXT: .p2align 2 430; CHECK-NEON-NEXT: @ %bb.1: 431; CHECK-NEON-NEXT: .data_region 432; CHECK-NEON-NEXT: LCPI11_0: 433; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 434; CHECK-NEON-NEXT: .end_data_region 435 %1 = icmp eq i32 %a, %b 436 %2 = uitofp i1 %1 to float 437 ret float %2 438} 439 440define i1 @test_overflow_recombine(i32 %in1, i32 %in2) { 441; CHECK-LABEL: test_overflow_recombine: 442; CHECK: @ %bb.0: 443; CHECK-NEXT: mul r2, r0, r1 444; CHECK-NEXT: smmul r0, r0, r1 445; CHECK-NEXT: subs r0, r0, r2, asr #31 446; CHECK-NEXT: movwne r0, #1 447; CHECK-NEXT: bx lr 448; 449; CHECK-NEON-LABEL: test_overflow_recombine: 450; CHECK-NEON: @ %bb.0: 451; CHECK-NEON-NEXT: mul r2, r0, r1 452; CHECK-NEON-NEXT: smmul r0, r0, r1 453; CHECK-NEON-NEXT: subs.w r0, r0, r2, asr #31 454; CHECK-NEON-NEXT: it ne 455; CHECK-NEON-NEXT: movne r0, #1 456; CHECK-NEON-NEXT: bx lr 457 %prod = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %in1, i32 %in2) 458 %overflow = extractvalue { i32, i1 } %prod, 1 459 ret i1 %overflow 460} 461 462declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) 463