Add target-specific dag combines for FAND(x,0) and FOR(x,0). This allows
authorChris Lattner <sabre@nondot.org>
Fri, 25 Jan 2008 05:46:26 +0000 (05:46 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 25 Jan 2008 05:46:26 +0000 (05:46 +0000)
us to compile:

double test(double X) {
  return copysign(0.0, X);
}

into:

_test:
andpd LCPI1_0(%rip), %xmm0
ret

instead of:
_test:
pxor %xmm1, %xmm1
andpd LCPI1_0(%rip), %xmm1
movapd %xmm0, %xmm2
andpd LCPI1_1(%rip), %xmm2
movapd %xmm1, %xmm0
orpd %xmm2, %xmm0
ret

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

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/copysign-zero.ll [new file with mode: 0644]

index 9ca99fe6dd0278670b0ce60af46a69bda6e12650..cef8e4b3e695bc13ba2516b80a70dc2ff42114e8 100644 (file)
@@ -5627,16 +5627,42 @@ static SDOperand PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
   return SDOperand();
 }
 
+/// PerformFORCombine - Do target-specific dag combines on X86ISD::FOR nodes.
+static SDOperand PerformFORCombine(SDNode *N, SelectionDAG &DAG) {
+  // FOR(0.0, x) -> x
+  // FOR(x, 0.0) -> x
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N->getOperand(0)))
+    if (C->getValueAPF().isPosZero())
+      return N->getOperand(1);
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N->getOperand(1)))
+    if (C->getValueAPF().isPosZero())
+      return N->getOperand(0);
+  return SDOperand();
+}
+
+/// PerformFANDCombine - Do target-specific dag combines on X86ISD::FAND nodes.
+static SDOperand PerformFANDCombine(SDNode *N, SelectionDAG &DAG) {
+  // FAND(0.0, x) -> 0.0
+  // FAND(x, 0.0) -> 0.0
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N->getOperand(0)))
+    if (C->getValueAPF().isPosZero())
+      return N->getOperand(0);
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N->getOperand(1)))
+    if (C->getValueAPF().isPosZero())
+      return N->getOperand(1);
+  return SDOperand();
+}
+
 
 SDOperand X86TargetLowering::PerformDAGCombine(SDNode *N,
                                                DAGCombinerInfo &DCI) const {
   SelectionDAG &DAG = DCI.DAG;
   switch (N->getOpcode()) {
   default: break;
-  case ISD::VECTOR_SHUFFLE:
-    return PerformShuffleCombine(N, DAG, Subtarget);
-  case ISD::SELECT:
-    return PerformSELECTCombine(N, DAG, Subtarget);
+  case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, Subtarget);
+  case ISD::SELECT:         return PerformSELECTCombine(N, DAG, Subtarget);
+  case X86ISD::FOR:         return PerformFORCombine(N, DAG);
+  case X86ISD::FAND:        return PerformFANDCombine(N, DAG);
   }
 
   return SDOperand();
diff --git a/test/CodeGen/X86/copysign-zero.ll b/test/CodeGen/X86/copysign-zero.ll
new file mode 100644 (file)
index 0000000..a08fa65
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llc | not grep orpd
+; RUN: llvm-as < %s | llc | grep andpd | count 1
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin8"
+
+define double @test(double %X) nounwind  {
+entry:
+       %tmp2 = tail call double @copysign( double 0.000000e+00, double %X ) nounwind readnone          ; <double> [#uses=1]
+       ret double %tmp2
+}
+
+declare double @copysign(double, double) nounwind readnone 
+