1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s 3 4; cmp with single-use load, should not form branch. 5define i32 @test1(double %a, double* nocapture %b, i32 %x, i32 %y) { 6; CHECK-LABEL: test1: 7; CHECK: # BB#0: 8; CHECK-NEXT: ucomisd (%rdi), %xmm0 9; CHECK-NEXT: cmovbel %edx, %esi 10; CHECK-NEXT: movl %esi, %eax 11; CHECK-NEXT: retq 12; 13 %load = load double, double* %b, align 8 14 %cmp = fcmp olt double %load, %a 15 %cond = select i1 %cmp, i32 %x, i32 %y 16 ret i32 %cond 17} 18 19; Sanity check: no load. 20define i32 @test2(double %a, double %b, i32 %x, i32 %y) { 21; CHECK-LABEL: test2: 22; CHECK: # BB#0: 23; CHECK-NEXT: ucomisd %xmm1, %xmm0 24; CHECK-NEXT: cmovbel %esi, %edi 25; CHECK-NEXT: movl %edi, %eax 26; CHECK-NEXT: retq 27; 28 %cmp = fcmp ogt double %a, %b 29 %cond = select i1 %cmp, i32 %x, i32 %y 30 ret i32 %cond 31} 32 33; Multiple uses of the load. 34define i32 @test4(i32 %a, i32* nocapture %b, i32 %x, i32 %y) { 35; CHECK-LABEL: test4: 36; CHECK: # BB#0: 37; CHECK-NEXT: movl (%rsi), %eax 38; CHECK-NEXT: cmpl %edi, %eax 39; CHECK-NEXT: cmovael %ecx, %edx 40; CHECK-NEXT: addl %edx, %eax 41; CHECK-NEXT: retq 42; 43 %load = load i32, i32* %b, align 4 44 %cmp = icmp ult i32 %load, %a 45 %cond = select i1 %cmp, i32 %x, i32 %y 46 %add = add i32 %cond, %load 47 ret i32 %add 48} 49 50; Multiple uses of the cmp. 51define i32 @test5(i32 %a, i32* nocapture %b, i32 %x, i32 %y) { 52; CHECK-LABEL: test5: 53; CHECK: # BB#0: 54; CHECK-NEXT: cmpl %edi, (%rsi) 55; CHECK-NEXT: cmoval %edi, %ecx 56; CHECK-NEXT: cmovael %edx, %ecx 57; CHECK-NEXT: movl %ecx, %eax 58; CHECK-NEXT: retq 59; 60 %load = load i32, i32* %b, align 4 61 %cmp = icmp ult i32 %load, %a 62 %cmp1 = icmp ugt i32 %load, %a 63 %cond = select i1 %cmp1, i32 %a, i32 %y 64 %cond5 = select i1 %cmp, i32 %cond, i32 %x 65 ret i32 %cond5 66} 67 68; If a select is not obviously predictable, don't turn it into a branch. 69define i32 @weighted_select1(i32 %a, i32 %b) { 70; CHECK-LABEL: weighted_select1: 71; CHECK: # BB#0: 72; CHECK-NEXT: testl %edi, %edi 73; CHECK-NEXT: cmovnel %edi, %esi 74; CHECK-NEXT: movl %esi, %eax 75; CHECK-NEXT: retq 76; 77 %cmp = icmp ne i32 %a, 0 78 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !0 79 ret i32 %sel 80} 81 82; If a select is obviously predictable, turn it into a branch. 83define i32 @weighted_select2(i32 %a, i32 %b) { 84; CHECK-LABEL: weighted_select2: 85; CHECK: # BB#0: 86; CHECK-NEXT: testl %edi, %edi 87; CHECK-NEXT: jne [[LABEL_BB5:.*]] 88; CHECK: movl %esi, %edi 89; CHECK-NEXT: [[LABEL_BB5]] 90; CHECK-NEXT: movl %edi, %eax 91; CHECK-NEXT: retq 92; 93 %cmp = icmp ne i32 %a, 0 94 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !1 95 ret i32 %sel 96} 97 98; Note the reversed profile weights: it doesn't matter if it's 99; obviously true or obviously false. 100; Either one should become a branch rather than conditional move. 101; TODO: But likely true vs. likely false should affect basic block placement? 102define i32 @weighted_select3(i32 %a, i32 %b) { 103; CHECK-LABEL: weighted_select3: 104; CHECK: # BB#0: 105; CHECK-NEXT: testl %edi, %edi 106; CHECK-NEXT: jne [[LABEL_BB6:.*]] 107; CHECK: movl %esi, %edi 108; CHECK-NEXT: [[LABEL_BB6]] 109; CHECK-NEXT: movl %edi, %eax 110; CHECK-NEXT: retq 111; 112 %cmp = icmp ne i32 %a, 0 113 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !2 114 ret i32 %sel 115} 116 117; Weightlessness is no reason to die. 118define i32 @unweighted_select(i32 %a, i32 %b) { 119; CHECK-LABEL: unweighted_select: 120; CHECK: # BB#0: 121; CHECK-NEXT: testl %edi, %edi 122; CHECK-NEXT: cmovnel %edi, %esi 123; CHECK-NEXT: movl %esi, %eax 124; CHECK-NEXT: retq 125; 126 %cmp = icmp ne i32 %a, 0 127 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !3 128 ret i32 %sel 129} 130 131!0 = !{!"branch_weights", i32 1, i32 99} 132!1 = !{!"branch_weights", i32 1, i32 100} 133!2 = !{!"branch_weights", i32 100, i32 1} 134!3 = !{!"branch_weights", i32 0, i32 0} 135 136