| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
 | ; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s | 
 |  | 
 | ; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428 | 
 | ; f1, f2, f3, and f4 should use an integer logic instruction. | 
 | ; f5, f6, f9, and f10 should use an FP (SSE) logic instruction. | 
 | ; | 
 | ; f7 and f8 are less clear. | 
 | ; | 
 | ; For f7 and f8, the SSE instructions don't take immediate operands, so if we | 
 | ; use one of those, we either have to load a constant from memory or move the | 
 | ; scalar immediate value from an integer register over to an SSE register. | 
 | ; Optimizing for size may affect that decision. Also, note that there are no | 
 | ; scalar versions of the FP logic ops, so if we want to fold a load into a | 
 | ; logic op, we have to load or splat a 16-byte vector constant. | 
 |  | 
 | ; 1 FP operand, 1 int operand, int result | 
 |  | 
 | define i32 @f1(float %x, i32 %y) { | 
 | ; CHECK-LABEL: f1: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %xmm0, %eax | 
 | ; CHECK-NEXT:    andl %edi, %eax | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %bc1, %y | 
 |   ret i32 %and | 
 | } | 
 |  | 
 | ; Swap operands of the logic op. | 
 |  | 
 | define i32 @f2(float %x, i32 %y) { | 
 | ; CHECK-LABEL: f2: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %xmm0, %eax | 
 | ; CHECK-NEXT:    andl %edi, %eax | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %y, %bc1 | 
 |   ret i32 %and | 
 | } | 
 |  | 
 | ; 1 FP operand, 1 constant operand, int result | 
 |  | 
 | define i32 @f3(float %x) { | 
 | ; CHECK-LABEL: f3: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %xmm0, %eax | 
 | ; CHECK-NEXT:    andl $1, %eax | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %bc1, 1 | 
 |   ret i32 %and | 
 | } | 
 |  | 
 | ; Swap operands of the logic op. | 
 |  | 
 | define i32 @f4(float %x) { | 
 | ; CHECK-LABEL: f4: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %xmm0, %eax | 
 | ; CHECK-NEXT:    andl $2, %eax | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 2, %bc1 | 
 |   ret i32 %and | 
 | } | 
 |  | 
 | ; 1 FP operand, 1 integer operand, FP result | 
 |  | 
 | define float @f5(float %x, i32 %y) { | 
 | ; CHECK-LABEL: f5: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %edi, %xmm1 | 
 | ; CHECK-NEXT:    pand %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %bc1, %y | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | ; Swap operands of the logic op. | 
 |  | 
 | define float @f6(float %x, i32 %y) { | 
 | ; CHECK-LABEL: f6: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movd %edi, %xmm1 | 
 | ; CHECK-NEXT:    pand %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %y, %bc1 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | ; 1 FP operand, 1 constant operand, FP result | 
 |  | 
 | define float @f7(float %x) { | 
 | ; CHECK-LABEL: f7: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %bc1, 3 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | ; Swap operands of the logic op. | 
 |  | 
 | define float @f8(float %x) { | 
 | ; CHECK-LABEL: f8: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 4, %bc1 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | ; 2 FP operands, int result | 
 |  | 
 | define i32 @f9(float %x, float %y) { | 
 | ; CHECK-LABEL: f9: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    pand %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    movd %xmm0, %eax | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %bc2 = bitcast float %y to i32 | 
 |   %and = and i32 %bc1, %bc2 | 
 |   ret i32 %and | 
 | } | 
 |  | 
 | ; 2 FP operands, FP result | 
 |  | 
 | define float @f10(float %x, float %y) { | 
 | ; CHECK-LABEL: f10: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %bc2 = bitcast float %y to i32 | 
 |   %and = and i32 %bc1, %bc2 | 
 |   %bc3 = bitcast i32 %and to float | 
 |   ret float %bc3 | 
 | } | 
 |  | 
 | define float @or(float %x, float %y) { | 
 | ; CHECK-LABEL: or: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    orps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %bc2 = bitcast float %y to i32 | 
 |   %and = or i32 %bc1, %bc2 | 
 |   %bc3 = bitcast i32 %and to float | 
 |   ret float %bc3 | 
 | } | 
 |  | 
 | define float @xor(float %x, float %y) { | 
 | ; CHECK-LABEL: xor: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    xorps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %bc2 = bitcast float %y to i32 | 
 |   %and = xor i32 %bc1, %bc2 | 
 |   %bc3 = bitcast i32 %and to float | 
 |   ret float %bc3 | 
 | } | 
 |  | 
 | define float @f7_or(float %x) { | 
 | ; CHECK-LABEL: f7_or: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero | 
 | ; CHECK-NEXT:    orps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = or i32 %bc1, 3 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | define float @f7_xor(float %x) { | 
 | ; CHECK-LABEL: f7_xor: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero | 
 | ; CHECK-NEXT:    xorps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = xor i32 %bc1, 3 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | ; Make sure that doubles work too. | 
 |  | 
 | define double @doubles(double %x, double %y) { | 
 | ; CHECK-LABEL: doubles: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast double %x to i64 | 
 |   %bc2 = bitcast double %y to i64 | 
 |   %and = and i64 %bc1, %bc2 | 
 |   %bc3 = bitcast i64 %and to double | 
 |   ret double %bc3 | 
 | } | 
 |  | 
 | define double @f7_double(double %x) { | 
 | ; CHECK-LABEL: f7_double: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movsd {{.*#+}} xmm1 = mem[0],zero | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast double %x to i64 | 
 |   %and = and i64 %bc1, 3 | 
 |   %bc2 = bitcast i64 %and to double | 
 |   ret double %bc2 | 
 | } | 
 |  | 
 | ; Grabbing the sign bit is a special case that could be handled | 
 | ; by movmskps/movmskpd, but if we're not shifting it over, then | 
 | ; a simple FP logic op is cheaper. | 
 |  | 
 | define float @movmsk(float %x) { | 
 | ; CHECK-LABEL: movmsk: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero | 
 | ; CHECK-NEXT:    andps %xmm1, %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %and = and i32 %bc1, 2147483648 | 
 |   %bc2 = bitcast i32 %and to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | define double @bitcast_fabs(double %x) { | 
 | ; CHECK-LABEL: bitcast_fabs: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast double %x to i64 | 
 |   %and = and i64 %bc1, 9223372036854775807 | 
 |   %bc2 = bitcast i64 %and to double | 
 |   ret double %bc2 | 
 | } | 
 |  | 
 | define float @bitcast_fneg(float %x) { | 
 | ; CHECK-LABEL: bitcast_fneg: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast float %x to i32 | 
 |   %xor = xor i32 %bc1, 2147483648 | 
 |   %bc2 = bitcast i32 %xor to float | 
 |   ret float %bc2 | 
 | } | 
 |  | 
 | define <2 x double> @bitcast_fabs_vec(<2 x double> %x) { | 
 | ; CHECK-LABEL: bitcast_fabs_vec: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    andps {{.*}}(%rip), %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast <2 x double> %x to <2 x i64> | 
 |   %and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807> | 
 |   %bc2 = bitcast <2 x i64> %and to <2 x double> | 
 |   ret <2 x double> %bc2 | 
 | } | 
 |  | 
 | define <4 x float> @bitcast_fneg_vec(<4 x float> %x) { | 
 | ; CHECK-LABEL: bitcast_fneg_vec: | 
 | ; CHECK:       # %bb.0: | 
 | ; CHECK-NEXT:    xorps {{.*}}(%rip), %xmm0 | 
 | ; CHECK-NEXT:    retq | 
 |   %bc1 = bitcast <4 x float> %x to <4 x i32> | 
 |   %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> | 
 |   %bc2 = bitcast <4 x i32> %xor to <4 x float> | 
 |   ret <4 x float> %bc2 | 
 | } | 
 |  |