1 ; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s 2 3 ; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428 4 ; f1, f2, f3, and f4 should use an integer logic instruction. 5 ; f9 and f10 should use an FP (SSE) logic instruction. 6 ; 7 ; f5, f6, f7, and f8 are less clear. 8 ; 9 ; For f5 and f6, we can save a register move by using an FP logic instruction, 10 ; but we may need to calculate the relative costs of an SSE op vs. int op vs. 11 ; scalar <-> SSE register moves. 12 ; 13 ; For f7 and f8, the SSE instructions don't take immediate operands, so if we 14 ; use one of those, we either have to load a constant from memory or move the 15 ; scalar immediate value from an integer register over to an SSE register. 16 ; Optimizing for size may affect that decision. Also, note that there are no 17 ; scalar versions of the FP logic ops, so if we want to fold a load into a 18 ; logic op, we have to load or splat a 16-byte vector constant. 19 20 ; 1 FP operand, 1 int operand, int result 21 22 define i32 @f1(float %x, i32 %y) { 23 ; CHECK-LABEL: f1: 24 ; CHECK: # BB#0: 25 ; CHECK-NEXT: movd %xmm0, %eax 26 ; CHECK-NEXT: andl %edi, %eax 27 ; CHECK-NEXT: retq 28 29 %bc1 = bitcast float %x to i32 30 %and = and i32 %bc1, %y 31 ret i32 %and 32 } 33 34 ; Swap operands of the logic op. 35 36 define i32 @f2(float %x, i32 %y) { 37 ; CHECK-LABEL: f2: 38 ; CHECK: # BB#0: 39 ; CHECK-NEXT: movd %xmm0, %eax 40 ; CHECK-NEXT: andl %edi, %eax 41 ; CHECK-NEXT: retq 42 43 %bc1 = bitcast float %x to i32 44 %and = and i32 %y, %bc1 45 ret i32 %and 46 } 47 48 ; 1 FP operand, 1 constant operand, int result 49 50 define i32 @f3(float %x) { 51 ; CHECK-LABEL: f3: 52 ; CHECK: # BB#0: 53 ; CHECK-NEXT: movd %xmm0, %eax 54 ; CHECK-NEXT: andl $1, %eax 55 ; CHECK-NEXT: retq 56 57 %bc1 = bitcast float %x to i32 58 %and = and i32 %bc1, 1 59 ret i32 %and 60 } 61 62 ; Swap operands of the logic op. 63 64 define i32 @f4(float %x) { 65 ; CHECK-LABEL: f4: 66 ; CHECK: # BB#0: 67 ; CHECK-NEXT: movd %xmm0, %eax 68 ; CHECK-NEXT: andl $2, %eax 69 ; CHECK-NEXT: retq 70 71 %bc1 = bitcast float %x to i32 72 %and = and i32 2, %bc1 73 ret i32 %and 74 } 75 76 ; 1 FP operand, 1 integer operand, FP result 77 78 define float @f5(float %x, i32 %y) { 79 ; CHECK-LABEL: f5: 80 ; CHECK: # BB#0: 81 ; CHECK-NEXT: movd %xmm0, %eax 82 ; CHECK-NEXT: andl %edi, %eax 83 ; CHECK-NEXT: movd %eax, %xmm0 84 ; CHECK-NEXT: retq 85 86 %bc1 = bitcast float %x to i32 87 %and = and i32 %bc1, %y 88 %bc2 = bitcast i32 %and to float 89 ret float %bc2 90 } 91 92 ; Swap operands of the logic op. 93 94 define float @f6(float %x, i32 %y) { 95 ; CHECK-LABEL: f6: 96 ; CHECK: # BB#0: 97 ; CHECK-NEXT: movd %xmm0, %eax 98 ; CHECK-NEXT: andl %edi, %eax 99 ; CHECK-NEXT: movd %eax, %xmm0 100 ; CHECK-NEXT: retq 101 102 %bc1 = bitcast float %x to i32 103 %and = and i32 %y, %bc1 104 %bc2 = bitcast i32 %and to float 105 ret float %bc2 106 } 107 108 ; 1 FP operand, 1 constant operand, FP result 109 110 define float @f7(float %x) { 111 ; CHECK-LABEL: f7: 112 ; CHECK: # BB#0: 113 ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 114 ; CHECK-NEXT: andps %xmm1, %xmm0 115 ; CHECK-NEXT: retq 116 117 %bc1 = bitcast float %x to i32 118 %and = and i32 %bc1, 3 119 %bc2 = bitcast i32 %and to float 120 ret float %bc2 121 } 122 123 ; Swap operands of the logic op. 124 125 define float @f8(float %x) { 126 ; CHECK-LABEL: f8: 127 ; CHECK: # BB#0: 128 ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 129 ; CHECK-NEXT: andps %xmm1, %xmm0 130 ; CHECK-NEXT: retq 131 132 %bc1 = bitcast float %x to i32 133 %and = and i32 4, %bc1 134 %bc2 = bitcast i32 %and to float 135 ret float %bc2 136 } 137 138 ; 2 FP operands, int result 139 140 define i32 @f9(float %x, float %y) { 141 ; CHECK-LABEL: f9: 142 ; CHECK: # BB#0: 143 ; CHECK-NEXT: andps %xmm1, %xmm0 144 ; CHECK-NEXT: movd %xmm0, %eax 145 ; CHECK-NEXT: retq 146 147 %bc1 = bitcast float %x to i32 148 %bc2 = bitcast float %y to i32 149 %and = and i32 %bc1, %bc2 150 ret i32 %and 151 } 152 153 ; 2 FP operands, FP result 154 155 define float @f10(float %x, float %y) { 156 ; CHECK-LABEL: f10: 157 ; CHECK: # BB#0: 158 ; CHECK-NEXT: andps %xmm1, %xmm0 159 ; CHECK-NEXT: retq 160 161 %bc1 = bitcast float %x to i32 162 %bc2 = bitcast float %y to i32 163 %and = and i32 %bc1, %bc2 164 %bc3 = bitcast i32 %and to float 165 ret float %bc3 166 } 167 168 define float @or(float %x, float %y) { 169 ; CHECK-LABEL: or: 170 ; CHECK: # BB#0: 171 ; CHECK-NEXT: orps %xmm1, %xmm0 172 ; CHECK-NEXT: retq 173 174 %bc1 = bitcast float %x to i32 175 %bc2 = bitcast float %y to i32 176 %and = or i32 %bc1, %bc2 177 %bc3 = bitcast i32 %and to float 178 ret float %bc3 179 } 180 181 define float @xor(float %x, float %y) { 182 ; CHECK-LABEL: xor: 183 ; CHECK: # BB#0: 184 ; CHECK-NEXT: xorps %xmm1, %xmm0 185 ; CHECK-NEXT: retq 186 187 %bc1 = bitcast float %x to i32 188 %bc2 = bitcast float %y to i32 189 %and = xor i32 %bc1, %bc2 190 %bc3 = bitcast i32 %and to float 191 ret float %bc3 192 } 193 194 define float @f7_or(float %x) { 195 ; CHECK-LABEL: f7_or: 196 ; CHECK: # BB#0: 197 ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 198 ; CHECK-NEXT: orps %xmm1, %xmm0 199 ; CHECK-NEXT: retq 200 201 %bc1 = bitcast float %x to i32 202 %and = or i32 %bc1, 3 203 %bc2 = bitcast i32 %and to float 204 ret float %bc2 205 } 206 207 define float @f7_xor(float %x) { 208 ; CHECK-LABEL: f7_xor: 209 ; CHECK: # BB#0: 210 ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 211 ; CHECK-NEXT: xorps %xmm1, %xmm0 212 ; CHECK-NEXT: retq 213 214 %bc1 = bitcast float %x to i32 215 %and = xor i32 %bc1, 3 216 %bc2 = bitcast i32 %and to float 217 ret float %bc2 218 } 219 220 ; Make sure that doubles work too. 221 222 define double @doubles(double %x, double %y) { 223 ; CHECK-LABEL: doubles: 224 ; CHECK: # BB#0: 225 ; CHECK-NEXT: andpd %xmm1, %xmm0 226 ; CHECK-NEXT: retq 227 228 %bc1 = bitcast double %x to i64 229 %bc2 = bitcast double %y to i64 230 %and = and i64 %bc1, %bc2 231 %bc3 = bitcast i64 %and to double 232 ret double %bc3 233 } 234 235 define double @f7_double(double %x) { 236 ; CHECK-LABEL: f7_double: 237 ; CHECK: # BB#0: 238 ; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero 239 ; CHECK-NEXT: andpd %xmm1, %xmm0 240 ; CHECK-NEXT: retq 241 242 %bc1 = bitcast double %x to i64 243 %and = and i64 %bc1, 3 244 %bc2 = bitcast i64 %and to double 245 ret double %bc2 246 } 247 248 ; Grabbing the sign bit is a special case that could be handled 249 ; by movmskps/movmskpd, but if we're not shifting it over, then 250 ; a simple FP logic op is cheaper. 251 252 define float @movmsk(float %x) { 253 ; CHECK-LABEL: movmsk: 254 ; CHECK: # BB#0: 255 ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 256 ; CHECK-NEXT: andps %xmm1, %xmm0 257 ; CHECK-NEXT: retq 258 259 %bc1 = bitcast float %x to i32 260 %and = and i32 %bc1, 2147483648 261 %bc2 = bitcast i32 %and to float 262 ret float %bc2 263 } 264 265