1 ; RUN: llc < %s -asm-verbose=false -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=CHECK --check-prefix=CMOV 2 ; RUN: llc < %s -asm-verbose=false -mtriple=i686-unknown-linux | FileCheck %s --check-prefix=CHECK --check-prefix=NOCMOV 3 4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 5 6 ; Test 2xCMOV patterns exposed after legalization. 7 ; One way to do that is with (select (fcmp une/oeq)), which gets 8 ; legalized to setp/setne. 9 10 ; CHECK-LABEL: test_select_fcmp_oeq_i32: 11 12 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 13 ; CMOV-NEXT: cmovnel %esi, %edi 14 ; CMOV-NEXT: cmovpl %esi, %edi 15 ; CMOV-NEXT: movl %edi, %eax 16 ; CMOV-NEXT: retq 17 18 ; NOCMOV-NEXT: flds 8(%esp) 19 ; NOCMOV-NEXT: flds 4(%esp) 20 ; NOCMOV-NEXT: fucompp 21 ; NOCMOV-NEXT: fnstsw %ax 22 ; NOCMOV-NEXT: sahf 23 ; NOCMOV-NEXT: leal 16(%esp), %eax 24 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 25 ; NOCMOV-NEXT: jp [[TBB]] 26 ; NOCMOV-NEXT: leal 12(%esp), %eax 27 ; NOCMOV-NEXT:[[TBB]]: 28 ; NOCMOV-NEXT: movl (%eax), %eax 29 ; NOCMOV-NEXT: retl 30 define i32 @test_select_fcmp_oeq_i32(float %a, float %b, i32 %c, i32 %d) #0 { 31 entry: 32 %cmp = fcmp oeq float %a, %b 33 %r = select i1 %cmp, i32 %c, i32 %d 34 ret i32 %r 35 } 36 37 ; CHECK-LABEL: test_select_fcmp_oeq_i64: 38 39 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 40 ; CMOV-NEXT: cmovneq %rsi, %rdi 41 ; CMOV-NEXT: cmovpq %rsi, %rdi 42 ; CMOV-NEXT: movq %rdi, %rax 43 ; CMOV-NEXT: retq 44 45 ; NOCMOV-NEXT: flds 8(%esp) 46 ; NOCMOV-NEXT: flds 4(%esp) 47 ; NOCMOV-NEXT: fucompp 48 ; NOCMOV-NEXT: fnstsw %ax 49 ; NOCMOV-NEXT: sahf 50 ; NOCMOV-NEXT: leal 20(%esp), %ecx 51 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 52 ; NOCMOV-NEXT: jp [[TBB]] 53 ; NOCMOV-NEXT: leal 12(%esp), %ecx 54 ; NOCMOV-NEXT: [[TBB]]: 55 ; NOCMOV-NEXT: movl (%ecx), %eax 56 ; NOCMOV-NEXT: orl $4, %ecx 57 ; NOCMOV-NEXT: movl (%ecx), %edx 58 ; NOCMOV-NEXT: retl 59 define i64 @test_select_fcmp_oeq_i64(float %a, float %b, i64 %c, i64 %d) #0 { 60 entry: 61 %cmp = fcmp oeq float %a, %b 62 %r = select i1 %cmp, i64 %c, i64 %d 63 ret i64 %r 64 } 65 66 ; CHECK-LABEL: test_select_fcmp_une_i64: 67 68 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 69 ; CMOV-NEXT: cmovneq %rdi, %rsi 70 ; CMOV-NEXT: cmovpq %rdi, %rsi 71 ; CMOV-NEXT: movq %rsi, %rax 72 ; CMOV-NEXT: retq 73 74 ; NOCMOV-NEXT: flds 8(%esp) 75 ; NOCMOV-NEXT: flds 4(%esp) 76 ; NOCMOV-NEXT: fucompp 77 ; NOCMOV-NEXT: fnstsw %ax 78 ; NOCMOV-NEXT: sahf 79 ; NOCMOV-NEXT: leal 12(%esp), %ecx 80 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 81 ; NOCMOV-NEXT: jp [[TBB]] 82 ; NOCMOV-NEXT: leal 20(%esp), %ecx 83 ; NOCMOV-NEXT: [[TBB]]: 84 ; NOCMOV-NEXT: movl (%ecx), %eax 85 ; NOCMOV-NEXT: orl $4, %ecx 86 ; NOCMOV-NEXT: movl (%ecx), %edx 87 ; NOCMOV-NEXT: retl 88 define i64 @test_select_fcmp_une_i64(float %a, float %b, i64 %c, i64 %d) #0 { 89 entry: 90 %cmp = fcmp une float %a, %b 91 %r = select i1 %cmp, i64 %c, i64 %d 92 ret i64 %r 93 } 94 95 ; CHECK-LABEL: test_select_fcmp_oeq_f64: 96 97 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 98 ; CMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 99 ; CMOV-NEXT: jp [[TBB]] 100 ; CMOV-NEXT: movaps %xmm2, %xmm3 101 ; CMOV-NEXT: [[TBB]]: 102 ; CMOV-NEXT: movaps %xmm3, %xmm0 103 ; CMOV-NEXT: retq 104 105 ; NOCMOV-NEXT: flds 8(%esp) 106 ; NOCMOV-NEXT: flds 4(%esp) 107 ; NOCMOV-NEXT: fucompp 108 ; NOCMOV-NEXT: fnstsw %ax 109 ; NOCMOV-NEXT: sahf 110 ; NOCMOV-NEXT: leal 20(%esp), %eax 111 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 112 ; NOCMOV-NEXT: jp [[TBB]] 113 ; NOCMOV-NEXT: leal 12(%esp), %eax 114 ; NOCMOV-NEXT: [[TBB]]: 115 ; NOCMOV-NEXT: fldl (%eax) 116 ; NOCMOV-NEXT: retl 117 define double @test_select_fcmp_oeq_f64(float %a, float %b, double %c, double %d) #0 { 118 entry: 119 %cmp = fcmp oeq float %a, %b 120 %r = select i1 %cmp, double %c, double %d 121 ret double %r 122 } 123 124 ; CHECK-LABEL: test_select_fcmp_oeq_v4i32: 125 126 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 127 ; CMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 128 ; CMOV-NEXT: jp [[TBB]] 129 ; CMOV-NEXT: movaps %xmm2, %xmm3 130 ; CMOV-NEXT: [[TBB]]: 131 ; CMOV-NEXT: movaps %xmm3, %xmm0 132 ; CMOV-NEXT: retq 133 134 ; NOCMOV-NEXT: pushl %edi 135 ; NOCMOV-NEXT: pushl %esi 136 ; NOCMOV-NEXT: flds 20(%esp) 137 ; NOCMOV-NEXT: flds 16(%esp) 138 ; NOCMOV-NEXT: fucompp 139 ; NOCMOV-NEXT: fnstsw %ax 140 ; NOCMOV-NEXT: sahf 141 ; NOCMOV-NEXT: leal 40(%esp), %eax 142 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 143 ; NOCMOV-NEXT: jp [[TBB]] 144 ; NOCMOV-NEXT: leal 24(%esp), %eax 145 ; NOCMOV-NEXT: [[TBB]]: 146 ; NOCMOV-NEXT: movl (%eax), %ecx 147 ; NOCMOV-NEXT: leal 44(%esp), %edx 148 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 149 ; NOCMOV-NEXT: jp [[TBB]] 150 ; NOCMOV-NEXT: leal 28(%esp), %edx 151 ; NOCMOV-NEXT: [[TBB]]: 152 ; NOCMOV-NEXT: movl 12(%esp), %eax 153 ; NOCMOV-NEXT: movl (%edx), %edx 154 ; NOCMOV-NEXT: leal 48(%esp), %esi 155 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 156 ; NOCMOV-NEXT: jp [[TBB]] 157 ; NOCMOV-NEXT: leal 32(%esp), %esi 158 ; NOCMOV-NEXT: [[TBB]]: 159 ; NOCMOV-NEXT: movl (%esi), %esi 160 ; NOCMOV-NEXT: leal 52(%esp), %edi 161 ; NOCMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 162 ; NOCMOV-NEXT: jp [[TBB]] 163 ; NOCMOV-NEXT: leal 36(%esp), %edi 164 ; NOCMOV-NEXT: [[TBB]]: 165 ; NOCMOV-NEXT: movl (%edi), %edi 166 ; NOCMOV-NEXT: movl %edi, 12(%eax) 167 ; NOCMOV-NEXT: movl %esi, 8(%eax) 168 ; NOCMOV-NEXT: movl %edx, 4(%eax) 169 ; NOCMOV-NEXT: movl %ecx, (%eax) 170 ; NOCMOV-NEXT: popl %esi 171 ; NOCMOV-NEXT: popl %edi 172 ; NOCMOV-NEXT: retl $4 173 define <4 x i32> @test_select_fcmp_oeq_v4i32(float %a, float %b, <4 x i32> %c, <4 x i32> %d) #0 { 174 entry: 175 %cmp = fcmp oeq float %a, %b 176 %r = select i1 %cmp, <4 x i32> %c, <4 x i32> %d 177 ret <4 x i32> %r 178 } 179 180 ; Also make sure we catch the original code-sequence of interest: 181 182 ; CMOV: [[ONE_F32_LCPI:.LCPI.*]]: 183 ; CMOV-NEXT: .long 1065353216 184 185 ; CHECK-LABEL: test_zext_fcmp_une: 186 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 187 ; CMOV-NEXT: movss [[ONE_F32_LCPI]](%rip), %xmm0 188 ; CMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 189 ; CMOV-NEXT: jp [[TBB]] 190 ; CMOV-NEXT: xorps %xmm0, %xmm0 191 ; CMOV-NEXT: [[TBB]]: 192 ; CMOV-NEXT: retq 193 194 ; NOCMOV: jne 195 ; NOCMOV-NEXT: jp 196 define float @test_zext_fcmp_une(float %a, float %b) #0 { 197 entry: 198 %cmp = fcmp une float %a, %b 199 %conv1 = zext i1 %cmp to i32 200 %conv2 = sitofp i32 %conv1 to float 201 ret float %conv2 202 } 203 204 ; CMOV: [[ONE_F32_LCPI:.LCPI.*]]: 205 ; CMOV-NEXT: .long 1065353216 206 207 ; CHECK-LABEL: test_zext_fcmp_oeq: 208 ; CMOV-NEXT: ucomiss %xmm1, %xmm0 209 ; CMOV-NEXT: xorps %xmm0, %xmm0 210 ; CMOV-NEXT: jne [[TBB:.LBB[0-9_]+]] 211 ; CMOV-NEXT: jp [[TBB]] 212 ; CMOV-NEXT: movss [[ONE_F32_LCPI]](%rip), %xmm0 213 ; CMOV-NEXT: [[TBB]]: 214 ; CMOV-NEXT: retq 215 216 ; NOCMOV: jne 217 ; NOCMOV-NEXT: jp 218 define float @test_zext_fcmp_oeq(float %a, float %b) #0 { 219 entry: 220 %cmp = fcmp oeq float %a, %b 221 %conv1 = zext i1 %cmp to i32 222 %conv2 = sitofp i32 %conv1 to float 223 ret float %conv2 224 } 225 226 attributes #0 = { nounwind } 227