[x86] replace integer 'and' ops with packed SSE FP 'and' ops when operating on FP...
authorSanjay Patel <spatel@rotateright.com>
Wed, 23 Sep 2015 17:00:06 +0000 (17:00 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 23 Sep 2015 17:00:06 +0000 (17:00 +0000)
Turn this:
   movd %xmm0, %eax
   movd %xmm1, %ecx
   andl %eax, %ecx
   movd %ecx, %xmm0

into this:
   andps %xmm1, %xmm0

This is related to, but does not solve:
https://llvm.org/bugs/show_bug.cgi?id=22428

Differential Revision: http://reviews.llvm.org/D13065

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248395 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/fp-logic.ll

index fbead736ec0678ee7c5e66768233b502fe4a36b6..a19ffcfbe54a23b41e0d2ae5093156f93921462a 100644 (file)
@@ -24447,6 +24447,24 @@ static SDValue PerformAndCombine(SDNode *N, SelectionDAG &DAG,
       }
     } // BEXTR
 
+    // If both input operands are being cast from floating point types,
+    // try to convert this into a floating point logic node to avoid
+    // unnecessary moves from SSE to integer registers.
+    // FIXME: Split this into a helper function, so it can also be used with
+    //        or/xor combining.
+    if (N0.getOpcode() == ISD::BITCAST && N1.getOpcode() == ISD::BITCAST &&
+        ((Subtarget->hasSSE1() && VT == MVT::i32) ||
+         (Subtarget->hasSSE2() && VT == MVT::i64))) {
+      SDValue N00 = N0.getOperand(0);
+      SDValue N10 = N1.getOperand(0);
+      EVT N00Type = N00.getValueType();
+      EVT N10Type = N10.getValueType();
+      if (N00Type.isFloatingPoint() && N10Type.isFloatingPoint()) {
+        SDValue FLogic = DAG.getNode(X86ISD::FAND, DL, N00Type, N00, N10);
+        return DAG.getBitcast(VT, FLogic);
+      }
+    }
+
     return SDValue();
   }
 
index d047f7742c82aeba9fe76743a3423e4b6f6d22d0..0b714ffe36f0b25b680f547226738c97bf647bc9 100644 (file)
@@ -142,9 +142,8 @@ define float @f8(float %x) {
 define i32 @f9(float %x, float %y) {
 ; CHECK-LABEL: f9:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movd %xmm0, %ecx
-; CHECK-NEXT:    movd %xmm1, %eax
-; CHECK-NEXT:    andl %ecx, %eax
+; CHECK-NEXT:    andps %xmm1, %xmm0
+; CHECK-NEXT:    movd %xmm0, %eax
 ; CHECK-NEXT:    retq
 
   %bc1 = bitcast float %x to i32
@@ -158,10 +157,7 @@ define i32 @f9(float %x, float %y) {
 define float @f10(float %x, float %y) {
 ; CHECK-LABEL: f10:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movd %xmm0, %eax
-; CHECK-NEXT:    movd %xmm1, %ecx
-; CHECK-NEXT:    andl %eax, %ecx
-; CHECK-NEXT:    movd %ecx, %xmm0
+; CHECK-NEXT:    andps %xmm1, %xmm0
 ; CHECK-NEXT:    retq
 
   %bc1 = bitcast float %x to i32
@@ -208,10 +204,7 @@ define float @xor(float %x, float %y) {
 define double @doubles(double %x, double %y) {
 ; CHECK-LABEL: doubles:
 ; CHECK:       # BB#0:
-; CHECK-NEXT:    movd %xmm0, %rax
-; CHECK-NEXT:    movd %xmm1, %rcx
-; CHECK-NEXT:    andq %rax, %rcx
-; CHECK-NEXT:    movd %rcx, %xmm0
+; CHECK-NEXT:    andpd %xmm1, %xmm0
 ; CHECK-NEXT:    retq
 
   %bc1 = bitcast double %x to i64