EltNo);
}
-static SDValue PerformBITCASTCombine(SDNode *N, SelectionDAG &DAG) {
+static SDValue PerformBITCASTCombine(SDNode *N, SelectionDAG &DAG,
+ const X86Subtarget *Subtarget) {
SDValue N0 = N->getOperand(0);
EVT VT = N->getValueType(0);
return DAG.getNode(X86ISD::MMX_MOVW2D, SDLoc(N00), VT, N00);
}
+ // Convert a bitcasted integer logic operation that has one bitcasted
+ // floating-point operand and one constant operand into a floating-point
+ // logic operation. This may create a load of the constant, but that is
+ // cheaper than materializing the constant in an integer register and
+ // transferring it to an SSE register or transferring the SSE operand to
+ // integer register and back.
+ unsigned FPOpcode;
+ switch (N0.getOpcode()) {
+ case ISD::AND: FPOpcode = X86ISD::FAND; break;
+ case ISD::OR: FPOpcode = X86ISD::FOR; break;
+ case ISD::XOR: FPOpcode = X86ISD::FXOR; break;
+ default: return SDValue();
+ }
+ if (((Subtarget->hasSSE1() && VT == MVT::f32) ||
+ (Subtarget->hasSSE2() && VT == MVT::f64)) &&
+ isa<ConstantSDNode>(N0.getOperand(1)) &&
+ N0.getOperand(0).getOpcode() == ISD::BITCAST &&
+ N0.getOperand(0).getOperand(0).getValueType() == VT) {
+ SDValue N000 = N0.getOperand(0).getOperand(0);
+ SDValue FPConst = DAG.getBitcast(VT, N0.getOperand(1));
+ return DAG.getNode(FPOpcode, SDLoc(N0), VT, N000, FPConst);
+ }
+
return SDValue();
}
case ISD::SELECT:
case X86ISD::SHRUNKBLEND:
return PerformSELECTCombine(N, DAG, DCI, Subtarget);
- case ISD::BITCAST: return PerformBITCASTCombine(N, DAG);
+ case ISD::BITCAST: return PerformBITCASTCombine(N, DAG, Subtarget);
case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI, Subtarget);
case ISD::ADD: return PerformAddCombine(N, DAG, Subtarget);
case ISD::SUB: return PerformSubCombine(N, DAG, Subtarget);
define float @f7(float %x) {
; CHECK-LABEL: f7:
; CHECK: # BB#0:
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: andl $3, %eax
-; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast float %x to i32
define float @f8(float %x) {
; CHECK-LABEL: f8:
; CHECK: # BB#0:
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: andl $4, %eax
-; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast float %x to i32
define float @f7_or(float %x) {
; CHECK-LABEL: f7_or:
; CHECK: # BB#0:
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: orl $3, %eax
-; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: orps %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast float %x to i32
define float @f7_xor(float %x) {
; CHECK-LABEL: f7_xor:
; CHECK: # BB#0:
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: xorl $3, %eax
-; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: xorps %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast float %x to i32
define double @f7_double(double %x) {
; CHECK-LABEL: f7_double:
; CHECK: # BB#0:
-; CHECK-NEXT: movd %xmm0, %rax
-; CHECK-NEXT: andl $3, %eax
-; CHECK-NEXT: movd %rax, %xmm0
+; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; CHECK-NEXT: andpd %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast double %x to i64
define float @movmsk(float %x) {
; CHECK-LABEL: movmsk:
; CHECK: # BB#0:
-; CHECK-NEXT: movmskps %xmm0, %eax
-; CHECK-NEXT: shll $31, %eax
-; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
%bc1 = bitcast float %x to i32