OSDN Git Service

Codegen copysign[f] into a FCOPYSIGN node
authorChris Lattner <sabre@nondot.org>
Sun, 5 Mar 2006 05:09:38 +0000 (05:09 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 5 Mar 2006 05:09:38 +0000 (05:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26542 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

index dd8a4f3..5c3787e 100644 (file)
@@ -1775,7 +1775,48 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       break;
     }
     break;
-  
+    
+  case ISD::FCOPYSIGN:  // FCOPYSIGN does not require LHS/RHS to match type!
+    Tmp1 = LegalizeOp(Node->getOperand(0));   // LHS
+    switch (getTypeAction(Node->getOperand(1).getValueType())) {
+      case Expand: assert(0 && "Not possible");
+      case Legal:
+        Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the RHS.
+        break;
+      case Promote:
+        Tmp2 = PromoteOp(Node->getOperand(1));  // Promote the RHS.
+        break;
+    }
+      
+    Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+    
+    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+    default: assert(0 && "Operation not supported");
+    case TargetLowering::Custom:
+      Tmp1 = TLI.LowerOperation(Result, DAG);
+      if (Tmp1.Val) Result = Tmp1;
+        break;
+    case TargetLowering::Legal: break;
+    case TargetLowering::Expand:
+      // Floating point mod -> fmod libcall.
+      const char *FnName;
+      if (Node->getValueType(0) == MVT::f32) {
+        FnName = "copysignf";
+        if (Tmp2.getValueType() != MVT::f32)  // Force operands to match type.
+          Result = DAG.UpdateNodeOperands(Result, Tmp1, 
+                                    DAG.getNode(ISD::FP_ROUND, MVT::f32, Tmp2));
+      } else {
+        FnName = "copysign";
+        if (Tmp2.getValueType() != MVT::f64)  // Force operands to match type.
+          Result = DAG.UpdateNodeOperands(Result, Tmp1, 
+                                   DAG.getNode(ISD::FP_EXTEND, MVT::f64, Tmp2));
+      }
+      SDOperand Dummy;
+      Result = ExpandLibCall(FnName, Node, Dummy);
+      break;
+    }
+    break;
+    
   case ISD::ADDC:
   case ISD::SUBC:
     Tmp1 = LegalizeOp(Node->getOperand(0));
@@ -2604,13 +2645,14 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
     break;
   case ISD::FDIV:
   case ISD::FREM:
+  case ISD::FCOPYSIGN:
     // These operators require that their input be fp extended.
     Tmp1 = PromoteOp(Node->getOperand(0));
     Tmp2 = PromoteOp(Node->getOperand(1));
     Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
     
     // Perform FP_ROUND: this is probably overly pessimistic.
-    if (NoExcessFPPrecision)
+    if (NoExcessFPPrecision && Node->getOpcode() != ISD::FCOPYSIGN)
       Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result,
                            DAG.getValueType(VT));
     break;
index 7312d66..534015c 100644 (file)
@@ -1152,7 +1152,12 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
     assert(N1.getValueType() == N2.getValueType() &&
            N1.getValueType() == VT && "Binary operator types must match!");
     break;
-
+  case ISD::FCOPYSIGN:   // N1 and result must match.  N1/N2 need not match.
+    assert(N1.getValueType() == VT &&
+           MVT::isFloatingPoint(N1.getValueType()) && 
+           MVT::isFloatingPoint(N2.getValueType()) &&
+           "Invalid FCOPYSIGN!");
+    break;
   case ISD::SHL:
   case ISD::SRA:
   case ISD::SRL:
@@ -2635,6 +2640,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
   case ISD::FMUL:   return "fmul";
   case ISD::FDIV:   return "fdiv";
   case ISD::FREM:   return "frem";
+  case ISD::FCOPYSIGN: return "fcopysign";
   case ISD::VADD:   return "vadd";
   case ISD::VSUB:   return "vsub";
   case ISD::VMUL:   return "vmul";
index 3069465..f011281 100644 (file)
@@ -1120,7 +1120,18 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
           return;
       } else {    // Not an LLVM intrinsic.
         const std::string &Name = F->getName();
-        if (Name[0] == 'f' && (Name == "fabs" || Name == "fabsf")) {
+        if (Name[0] == 'c' && (Name == "copysign" || Name == "copysignf")) {
+          if (I.getNumOperands() == 3 &&   // Basic sanity checks.
+              I.getOperand(1)->getType()->isFloatingPoint() &&
+              I.getType() == I.getOperand(1)->getType() &&
+              I.getType() == I.getOperand(2)->getType()) {
+            SDOperand LHS = getValue(I.getOperand(1));
+            SDOperand RHS = getValue(I.getOperand(2));
+            setValue(&I, DAG.getNode(ISD::FCOPYSIGN, LHS.getValueType(),
+                                     LHS, RHS));
+            return;
+          }
+        } else if (Name[0] == 'f' && (Name == "fabs" || Name == "fabsf")) {
           if (I.getNumOperands() == 2 &&   // Basic sanity checks.
               I.getOperand(1)->getType()->isFloatingPoint() &&
               I.getType() == I.getOperand(1)->getType()) {