canonicalize a bunch of operations involving fneg


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21160 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 04ccc77..93ef372 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -565,6 +565,8 @@
 
   if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Operand.Val))
     switch (Opcode) {
+    case ISD::FNEG:
+      return getConstantFP(-C->getValue(), VT);
     case ISD::FP_ROUND:
     case ISD::FP_EXTEND:
       return getConstantFP(C->getValue(), VT);
@@ -602,6 +604,17 @@
         return Operand.Val->getOperand(0);
     }
     break;
+  case ISD::FNEG:
+    if (OpOpcode == ISD::SUB)   // -(X-Y) -> (Y-X)
+      return getNode(ISD::SUB, VT, Operand.Val->getOperand(1),
+                     Operand.Val->getOperand(0));
+    if (OpOpcode == ISD::FNEG)  // --X -> X
+      return Operand.Val->getOperand(0);
+    break;
+  case ISD::FABS:
+    if (OpOpcode == ISD::FNEG)  // abs(-X) -> abs(X)
+      return getNode(ISD::FABS, VT, Operand.Val->getOperand(0));
+    break;
   }
 
   SDNode *&N = UnaryOps[std::make_pair(Opcode, std::make_pair(Operand, VT))];
@@ -859,6 +872,12 @@
   case ISD::XOR:
     if (N1 == N2) return getConstant(0, VT);  // xor X, Y -> 0
     break;
+  case ISD::ADD:
+    if (N2.getOpcode() == ISD::FNEG)          // (A+ (-B) -> A-B
+      return getNode(ISD::SUB, VT, N1, N2.getOperand(0));
+    if (N1.getOpcode() == ISD::FNEG)          // ((-A)+B) -> B-A
+      return getNode(ISD::SUB, VT, N2, N1.getOperand(0));
+    break;
   case ISD::SUB:
     if (N1.getOpcode() == ISD::ADD) {
       if (N1.Val->getOperand(0) == N2)
@@ -866,6 +885,8 @@
       if (N1.Val->getOperand(1) == N2)
         return N1.Val->getOperand(0);         // (A+B)-B == A
     }
+    if (N2.getOpcode() == ISD::FNEG)          // (A- (-B) -> A+B
+      return getNode(ISD::ADD, VT, N1, N2.getOperand(0));
     break;
   }