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