Implement handling of most long operators through libcalls.
Fix a bug legalizing "ret (Val,Val)"


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19375 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index e42d7f2..964c511 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -19,6 +19,20 @@
 #include <iostream>
 using namespace llvm;
 
+static const Type *getTypeFor(MVT::ValueType VT) {
+  switch (VT) {
+  default: assert(0 && "Unknown MVT!");
+  case MVT::i1: return Type::BoolTy;
+  case MVT::i8: return Type::UByteTy;
+  case MVT::i16: return Type::UShortTy;
+  case MVT::i32: return Type::UIntTy;
+  case MVT::i64: return Type::ULongTy;
+  case MVT::f32: return Type::FloatTy;
+  case MVT::f64: return Type::DoubleTy;
+  }
+}
+
+
 //===----------------------------------------------------------------------===//
 /// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and
 /// hacks on it until the target machine can handle it.  This involves
@@ -403,7 +417,7 @@
       for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i)
         switch (getTypeAction(Node->getOperand(i).getValueType())) {
         case Legal:
-          NewValues.push_back(LegalizeOp(Node->getOperand(1)));
+          NewValues.push_back(LegalizeOp(Node->getOperand(i)));
           break;
         case Expand: {
           SDOperand Lo, Hi;
@@ -638,10 +652,11 @@
     }
   }
 
-  // If we are lowering to a type that the target doesn't support, we will have
-  // to iterate lowering.
-  if (!isTypeLegal(NVT))
-    NeedsAnotherIteration = true;
+  // Expanding to multiple registers needs to perform an optimization step, and
+  // is not careful to avoid operations the target does not support.  Make sure
+  // that all generated operations are legalized in the next iteration.
+  NeedsAnotherIteration = true;
+  const char *LibCallName = 0;
 
   LegalizeAction Action;
   switch (Node->getOpcode()) {
@@ -750,6 +765,51 @@
     // The high part is just a zero.
     Hi = DAG.getConstant(0, NVT);
     break;
+
+    // These operators cannot be expanded directly, emit them as calls to
+    // library functions.
+  case ISD::FP_TO_SINT:
+    if (Node->getOperand(0).getValueType() == MVT::f32)
+      LibCallName = "__fixsfdi";
+    else
+      LibCallName = "__fixdfdi";
+    break;
+  case ISD::FP_TO_UINT:
+    if (Node->getOperand(0).getValueType() == MVT::f32)
+      LibCallName = "__fixunssfdi";
+    else
+      LibCallName = "__fixunsdfdi";
+    break;
+
+  case ISD::ADD:  LibCallName = "__adddi3"; break;
+  case ISD::SUB:  LibCallName = "__subdi3"; break;
+  case ISD::MUL:  LibCallName = "__muldi3"; break;
+  case ISD::SDIV: LibCallName = "__divdi3"; break;
+  case ISD::UDIV: LibCallName = "__udivdi3"; break;
+  case ISD::SREM: LibCallName = "__moddi3"; break;
+  case ISD::UREM: LibCallName = "__umoddi3"; break;
+  case ISD::SHL:  LibCallName = "__lshrdi3"; break;
+  case ISD::SRA:  LibCallName = "__ashrdi3"; break;
+  case ISD::SRL:  LibCallName = "__ashldi3"; break;
+  }
+
+  // Int2FP -> __floatdisf/__floatdidf
+
+  // If this is to be expanded into a libcall... do so now.
+  if (LibCallName) {
+    TargetLowering::ArgListTy Args;
+    for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
+      Args.push_back(std::make_pair(Node->getOperand(i),
+                               getTypeFor(Node->getOperand(i).getValueType())));
+    SDOperand Callee = DAG.getExternalSymbol(LibCallName, TLI.getPointerTy());
+
+    // We don't care about token chains for libcalls.  We just use the entry
+    // node as our input and ignore the output chain.  This allows us to place
+    // calls wherever we need them to satisfy data dependences.
+    SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(),
+                                       getTypeFor(Op.getValueType()), Callee,
+                                       Args, DAG).first;
+    ExpandOp(Result, Lo, Hi);
   }
 
   // Remember in a map if the values will be reused later.