274 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-unknown-unknown -disable-cgp-select2branch -x86-cmov-converter=false | FileCheck %s3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"4 5define i32 @test1(i32 %x, i32 %n, i32 %w, ptr %vp) nounwind readnone {6; CHECK-LABEL: test1:7; CHECK: # %bb.0: # %entry8; CHECK-NEXT: btl %esi, %edi9; CHECK-NEXT: movl $12, %eax10; CHECK-NEXT: cmovael (%rcx), %eax11; CHECK-NEXT: retq12entry:13 %0 = lshr i32 %x, %n14 %1 = and i32 %0, 115 %toBool = icmp eq i32 %1, 016 %v = load i32, ptr %vp17 %.0 = select i1 %toBool, i32 %v, i32 1218 ret i32 %.019}20 21define i32 @test2(i32 %x, i32 %n, i32 %w, ptr %vp) nounwind readnone {22; CHECK-LABEL: test2:23; CHECK: # %bb.0: # %entry24; CHECK-NEXT: btl %esi, %edi25; CHECK-NEXT: movl $12, %eax26; CHECK-NEXT: cmovbl (%rcx), %eax27; CHECK-NEXT: retq28entry:29 %0 = lshr i32 %x, %n30 %1 = and i32 %0, 131 %toBool = icmp eq i32 %1, 032 %v = load i32, ptr %vp33 %.0 = select i1 %toBool, i32 12, i32 %v34 ret i32 %.035}36 37 38; x86's 32-bit cmov zeroes the high 32 bits of the destination. Make39; sure CodeGen takes advantage of that to avoid an unnecessary40; zero-extend (movl) after the cmov.41 42declare void @bar(i64) nounwind43 44define void @test3(i64 %a, i64 %b, i1 %p) nounwind {45; CHECK-LABEL: test3:46; CHECK: # %bb.0:47; CHECK-NEXT: pushq %rax48; CHECK-NEXT: testb $1, %dl49; CHECK-NEXT: cmovel %esi, %edi50; CHECK-NEXT: callq bar@PLT51; CHECK-NEXT: popq %rax52; CHECK-NEXT: retq53 %c = trunc i64 %a to i3254 %d = trunc i64 %b to i3255 %e = select i1 %p, i32 %c, i32 %d56 %f = zext i32 %e to i6457 call void @bar(i64 %f)58 ret void59}60 61 62 63; CodeGen shouldn't try to do a setne after an expanded 8-bit conditional64; move without recomputing EFLAGS, because the expansion of the conditional65; move with control flow may clobber EFLAGS (e.g., with xor, to set the66; register to zero).67 68; The test is a little awkward; the important part is that there's a test before the69; setne.70; PR481471 72 73@g_3 = external dso_local global i874@g_96 = external dso_local global i875@g_100 = external dso_local global i876@_2E_str = external dso_local constant [15 x i8], align 177 78define i1 @test4() nounwind {79; CHECK-LABEL: test4:80; CHECK: # %bb.0: # %entry81; CHECK-NEXT: movsbl g_3(%rip), %edx82; CHECK-NEXT: movzbl %dl, %ecx83; CHECK-NEXT: shrl $7, %ecx84; CHECK-NEXT: xorb $1, %cl85; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx86; CHECK-NEXT: sarl %cl, %edx87; CHECK-NEXT: movzbl g_96(%rip), %eax88; CHECK-NEXT: testb %al, %al89; CHECK-NEXT: je .LBB3_290; CHECK-NEXT: # %bb.1: # %bb.i.i.i91; CHECK-NEXT: movzbl g_100(%rip), %ecx92; CHECK-NEXT: .LBB3_2: # %func_4.exit.i93; CHECK-NEXT: pushq %rbx94; CHECK-NEXT: xorl %esi, %esi95; CHECK-NEXT: testb %dl, %dl96; CHECK-NEXT: setne %bl97; CHECK-NEXT: movzbl %al, %ecx98; CHECK-NEXT: cmovnel %esi, %ecx99; CHECK-NEXT: testb %al, %al100; CHECK-NEXT: je .LBB3_5101; CHECK-NEXT: # %bb.3: # %func_4.exit.i102; CHECK-NEXT: testb %bl, %bl103; CHECK-NEXT: jne .LBB3_5104; CHECK-NEXT: # %bb.4: # %bb.i.i105; CHECK-NEXT: movzbl g_100(%rip), %ecx106; CHECK-NEXT: xorl %ebx, %ebx107; CHECK-NEXT: movl %eax, %ecx108; CHECK-NEXT: .LBB3_5: # %func_1.exit109; CHECK-NEXT: movb %cl, g_96(%rip)110; CHECK-NEXT: movzbl %cl, %esi111; CHECK-NEXT: movl $_2E_str, %edi112; CHECK-NEXT: xorl %eax, %eax113; CHECK-NEXT: callq printf@PLT114; CHECK-NEXT: movl %ebx, %eax115; CHECK-NEXT: popq %rbx116; CHECK-NEXT: retq117entry:118 %0 = load i8, ptr @g_3, align 1119 %1 = sext i8 %0 to i32120 %.lobit.i = lshr i8 %0, 7121 %tmp.i = zext i8 %.lobit.i to i32122 %tmp.not.i = xor i32 %tmp.i, 1123 %iftmp.17.0.i.i = ashr i32 %1, %tmp.not.i124 %retval56.i.i = trunc i32 %iftmp.17.0.i.i to i8125 %2 = icmp eq i8 %retval56.i.i, 0126 %g_96.promoted.i = load i8, ptr @g_96127 %3 = icmp eq i8 %g_96.promoted.i, 0128 br i1 %3, label %func_4.exit.i, label %bb.i.i.i129 130bb.i.i.i:131 %4 = load volatile i8, ptr @g_100, align 1132 br label %func_4.exit.i133 134func_4.exit.i:135 %.not.i = xor i1 %2, true136 %brmerge.i = or i1 %3, %.not.i137 %.mux.i = select i1 %2, i8 %g_96.promoted.i, i8 0138 br i1 %brmerge.i, label %func_1.exit, label %bb.i.i139 140bb.i.i:141 %5 = load volatile i8, ptr @g_100, align 1142 br label %func_1.exit143 144func_1.exit:145 %g_96.tmp.0.i = phi i8 [ %g_96.promoted.i, %bb.i.i ], [ %.mux.i, %func_4.exit.i ]146 %ret = phi i1 [ 0, %bb.i.i ], [ %.not.i, %func_4.exit.i ]147 store i8 %g_96.tmp.0.i, ptr @g_96148 %6 = zext i8 %g_96.tmp.0.i to i32149 %7 = tail call i32 (ptr, ...) @printf(ptr noalias @_2E_str, i32 %6) nounwind150 ret i1 %ret151}152 153declare i32 @printf(ptr nocapture, ...) nounwind154 155 156; Should compile to setcc | -2.157; rdar://6668608158define i32 @test5(ptr nocapture %P) nounwind readonly {159; CHECK-LABEL: test5:160; CHECK: # %bb.0: # %entry161; CHECK-NEXT: xorl %eax, %eax162; CHECK-NEXT: cmpl $42, (%rdi)163; CHECK-NEXT: setge %al164; CHECK-NEXT: orl $-2, %eax165; CHECK-NEXT: retq166entry:167 %0 = load i32, ptr %P, align 4168 %1 = icmp sgt i32 %0, 41169 %iftmp.0.0 = select i1 %1, i32 -1, i32 -2170 ret i32 %iftmp.0.0171}172 173define i32 @test6(ptr nocapture %P) nounwind readonly {174; CHECK-LABEL: test6:175; CHECK: # %bb.0: # %entry176; CHECK-NEXT: xorl %eax, %eax177; CHECK-NEXT: cmpl $42, (%rdi)178; CHECK-NEXT: setl %al179; CHECK-NEXT: leal 4(%rax,%rax,8), %eax180; CHECK-NEXT: retq181entry:182 %0 = load i32, ptr %P, align 4183 %1 = icmp sgt i32 %0, 41184 %iftmp.0.0 = select i1 %1, i32 4, i32 13185 ret i32 %iftmp.0.0186}187 188 189define i8 @test7(i1 inreg %c, i8 inreg %a, i8 inreg %b) nounwind {190; CHECK-LABEL: test7:191; CHECK: # %bb.0:192; CHECK-NEXT: movl %esi, %eax193; CHECK-NEXT: testb $1, %dil194; CHECK-NEXT: cmovel %edx, %eax195; CHECK-NEXT: # kill: def $al killed $al killed $eax196; CHECK-NEXT: retq197 %d = select i1 %c, i8 %a, i8 %b198 ret i8 %d199}200 201define i64 @test8(i64 %0, i64 %1, i64 %2) {202; CHECK-LABEL: test8:203; CHECK: # %bb.0:204; CHECK-NEXT: movq %rsi, %rax205; CHECK-NEXT: cmpq $-2147483648, %rdi # imm = 0x80000000206; CHECK-NEXT: cmovlq %rdx, %rax207; CHECK-NEXT: retq208 %4 = icmp sgt i64 %0, -2147483649209 %5 = select i1 %4, i64 %1, i64 %2210 ret i64 %5211}212 213define i32 @smin(i32 %x) {214; CHECK-LABEL: smin:215; CHECK: # %bb.0:216; CHECK-NEXT: testl %edi, %edi217; CHECK-NEXT: notl %edi218; CHECK-NEXT: movl $-1, %eax219; CHECK-NEXT: cmovnsl %edi, %eax220; CHECK-NEXT: retq221 %not_x = xor i32 %x, -1222 %1 = icmp slt i32 %not_x, -1223 %sel = select i1 %1, i32 %not_x, i32 -1224 ret i32 %sel225}226 227define i32 @pr47049_1(i32 %0) {228; CHECK-LABEL: pr47049_1:229; CHECK: # %bb.0:230; CHECK-NEXT: testl %edi, %edi231; CHECK-NEXT: movl $1, %eax232; CHECK-NEXT: cmovlel %edi, %eax233; CHECK-NEXT: retq234 %2 = icmp slt i32 %0, 1235 %3 = select i1 %2, i32 %0, i32 1236 ret i32 %3237}238 239define i32 @pr47049_2(i32 %0) {240; CHECK-LABEL: pr47049_2:241; CHECK: # %bb.0:242; CHECK-NEXT: testl %edi, %edi243; CHECK-NEXT: movl $-1, %eax244; CHECK-NEXT: cmovnsl %edi, %eax245; CHECK-NEXT: retq246 %2 = icmp sgt i32 %0, -1247 %3 = select i1 %2, i32 %0, i32 -1248 ret i32 %3249}250 251define i32 @pr47049_3(i32 %0) {252; CHECK-LABEL: pr47049_3:253; CHECK: # %bb.0:254; CHECK-NEXT: testl %edi, %edi255; CHECK-NEXT: movl $1, %eax256; CHECK-NEXT: cmovgl %edi, %eax257; CHECK-NEXT: retq258 %2 = icmp sgt i32 %0, 1259 %3 = select i1 %2, i32 %0, i32 1260 ret i32 %3261}262 263define i32 @pr47049_4(i32 %0) {264; CHECK-LABEL: pr47049_4:265; CHECK: # %bb.0:266; CHECK-NEXT: testl %edi, %edi267; CHECK-NEXT: movl $1, %eax268; CHECK-NEXT: cmovnel %edi, %eax269; CHECK-NEXT: retq270 %2 = icmp ugt i32 %0, 1271 %3 = select i1 %2, i32 %0, i32 1272 ret i32 %3273}274