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 19define 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 32define 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 45define 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 58define 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 71define 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 85define 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 99define 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 113define 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 127define 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 141define 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 153define 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 165define 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 177define 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 189define 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 203define 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 215define 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 231define 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 243define 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 254define 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 265define <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 276define <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 287define float @fadd_bitcast_fneg(float %x, float %y) { 288; CHECK-LABEL: fadd_bitcast_fneg: 289; CHECK: # %bb.0: 290; CHECK-NEXT: subss %xmm1, %xmm0 291; CHECK-NEXT: retq 292 %bc1 = bitcast float %y to i32 293 %xor = xor i32 %bc1, 2147483648 294 %bc2 = bitcast i32 %xor to float 295 %fadd = fadd float %x, %bc2 296 ret float %fadd 297} 298 299define float @fsub_bitcast_fneg(float %x, float %y) { 300; CHECK-LABEL: fsub_bitcast_fneg: 301; CHECK: # %bb.0: 302; CHECK-NEXT: addss %xmm1, %xmm0 303; CHECK-NEXT: retq 304 %bc1 = bitcast float %y to i32 305 %xor = xor i32 %bc1, 2147483648 306 %bc2 = bitcast i32 %xor to float 307 %fsub = fsub float %x, %bc2 308 ret float %fsub 309} 310 311define float @nabsf(float %a) { 312; CHECK-LABEL: nabsf: 313; CHECK: # %bb.0: 314; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 315; CHECK-NEXT: retq 316 %conv = bitcast float %a to i32 317 %and = or i32 %conv, -2147483648 318 %conv1 = bitcast i32 %and to float 319 ret float %conv1 320} 321 322define double @nabsd(double %a) { 323; CHECK-LABEL: nabsd: 324; CHECK: # %bb.0: 325; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 326; CHECK-NEXT: retq 327 %conv = bitcast double %a to i64 328 %and = or i64 %conv, -9223372036854775808 329 %conv1 = bitcast i64 %and to double 330 ret double %conv1 331} 332 333define <4 x float> @nabsv4f32(<4 x float> %a) { 334; CHECK-LABEL: nabsv4f32: 335; CHECK: # %bb.0: 336; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 337; CHECK-NEXT: retq 338 %conv = bitcast <4 x float> %a to <4 x i32> 339 %and = or <4 x i32> %conv, <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648> 340 %conv1 = bitcast <4 x i32> %and to <4 x float> 341 ret <4 x float> %conv1 342} 343 344define <2 x double> @nabsv2d64(<2 x double> %a) { 345; CHECK-LABEL: nabsv2d64: 346; CHECK: # %bb.0: 347; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 348; CHECK-NEXT: retq 349 %conv = bitcast <2 x double> %a to <2 x i64> 350 %and = or <2 x i64> %conv, <i64 -9223372036854775808, i64 -9223372036854775808> 351 %conv1 = bitcast <2 x i64> %and to <2 x double> 352 ret <2 x double> %conv1 353} 354 355define <4 x float> @fadd_bitcast_fneg_vec(<4 x float> %x, <4 x float> %y) { 356; CHECK-LABEL: fadd_bitcast_fneg_vec: 357; CHECK: # %bb.0: 358; CHECK-NEXT: subps %xmm1, %xmm0 359; CHECK-NEXT: retq 360 %bc1 = bitcast <4 x float> %y to <4 x i32> 361 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> 362 %bc2 = bitcast <4 x i32> %xor to <4 x float> 363 %fadd = fadd <4 x float> %x, %bc2 364 ret <4 x float> %fadd 365} 366 367define <4 x float> @fadd_bitcast_fneg_vec_undef_elts(<4 x float> %x, <4 x float> %y) { 368; CHECK-LABEL: fadd_bitcast_fneg_vec_undef_elts: 369; CHECK: # %bb.0: 370; CHECK-NEXT: subps %xmm1, %xmm0 371; CHECK-NEXT: retq 372 %bc1 = bitcast <4 x float> %y to <4 x i32> 373 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 undef, i32 2147483648> 374 %bc2 = bitcast <4 x i32> %xor to <4 x float> 375 %fadd = fadd <4 x float> %x, %bc2 376 ret <4 x float> %fadd 377} 378 379define <4 x float> @fsub_bitcast_fneg_vec(<4 x float> %x, <4 x float> %y) { 380; CHECK-LABEL: fsub_bitcast_fneg_vec: 381; CHECK: # %bb.0: 382; CHECK-NEXT: addps %xmm1, %xmm0 383; CHECK-NEXT: retq 384 %bc1 = bitcast <4 x float> %y to <4 x i32> 385 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> 386 %bc2 = bitcast <4 x i32> %xor to <4 x float> 387 %fsub = fsub <4 x float> %x, %bc2 388 ret <4 x float> %fsub 389} 390 391define <4 x float> @fsub_bitcast_fneg_vec_undef_elts(<4 x float> %x, <4 x float> %y) { 392; CHECK-LABEL: fsub_bitcast_fneg_vec_undef_elts: 393; CHECK: # %bb.0: 394; CHECK-NEXT: addps %xmm1, %xmm0 395; CHECK-NEXT: retq 396 %bc1 = bitcast <4 x float> %y to <4 x i32> 397 %xor = xor <4 x i32> %bc1, <i32 undef, i32 2147483648, i32 undef, i32 2147483648> 398 %bc2 = bitcast <4 x i32> %xor to <4 x float> 399 %fsub = fsub <4 x float> %x, %bc2 400 ret <4 x float> %fsub 401} 402 403define <4 x float> @fadd_bitcast_fneg_vec_width(<4 x float> %x, <4 x float> %y) { 404; CHECK-LABEL: fadd_bitcast_fneg_vec_width: 405; CHECK: # %bb.0: 406; CHECK-NEXT: xorps {{.*}}(%rip), %xmm1 407; CHECK-NEXT: addps %xmm1, %xmm0 408; CHECK-NEXT: retq 409 %bc1 = bitcast <4 x float> %y to <2 x i64> 410 %xor = xor <2 x i64> %bc1, <i64 -9223372034707292160, i64 -9223372034707292160> 411 %bc2 = bitcast <2 x i64> %xor to <4 x float> 412 %fadd = fadd <4 x float> %x, %bc2 413 ret <4 x float> %fadd 414} 415 416define <4 x float> @fsub_bitcast_fneg_vec_width(<4 x float> %x, <4 x float> %y) { 417; CHECK-LABEL: fsub_bitcast_fneg_vec_width: 418; CHECK: # %bb.0: 419; CHECK-NEXT: xorps {{.*}}(%rip), %xmm1 420; CHECK-NEXT: subps %xmm1, %xmm0 421; CHECK-NEXT: retq 422 %bc1 = bitcast <4 x float> %y to <2 x i64> 423 %xor = xor <2 x i64> %bc1, <i64 -9223372034707292160, i64 -9223372034707292160> 424 %bc2 = bitcast <2 x i64> %xor to <4 x float> 425 %fsub = fsub <4 x float> %x, %bc2 426 ret <4 x float> %fsub 427} 428