Add a mysteriously missing libcall, FPTOSINT_F80_I32.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeIntegerTypes.cpp
index bad430be4d2cc6f79b11683f97ed440eed11b5f2..bde61ad81adbcef191f3cfd4fe271b8aafa53dcd 100644 (file)
@@ -19,7 +19,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "LegalizeTypes.h"
-#include "llvm/Constants.h"
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -34,6 +33,18 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n");
   SDOperand Result = SDOperand();
 
+  // See if the target wants to custom expand this node.
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+      TargetLowering::Custom) {
+    // If the target wants to, allow it to lower this itself.
+    if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
+      // Everything that once used N now uses P.  We are guaranteed that the
+      // result value types of N and the result value types of P match.
+      ReplaceNodeWith(N, P);
+      return;
+    }
+  }
+
   switch (N->getOpcode()) {
   default:
 #ifndef NDEBUG
@@ -49,7 +60,6 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::SIGN_EXTEND:
   case ISD::ZERO_EXTEND:
   case ISD::ANY_EXTEND:  Result = PromoteIntRes_INT_EXTEND(N); break;
-  case ISD::FP_ROUND:    Result = PromoteIntRes_FP_ROUND(N); break;
   case ISD::FP_TO_SINT:
   case ISD::FP_TO_UINT:  Result = PromoteIntRes_FP_TO_XINT(N); break;
   case ISD::SETCC:    Result = PromoteIntRes_SETCC(N); break;
@@ -84,6 +94,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
   case ISD::EXTRACT_VECTOR_ELT:
     Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N);
     break;
+
+  case ISD::VAARG : Result = PromoteIntRes_VAARG(N); break;
   }
 
   // If Result is null, the sub-method took care of registering the result.
@@ -156,15 +168,6 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) {
   return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
 }
 
-SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) {
-  // NOTE: Assumes input is legal.
-  if (N->getConstantOperandVal(1) == 0)
-    return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
-                       N->getOperand(0), DAG.getValueType(N->getValueType(0)));
-  // If the precision discard isn't needed, just return the operand unrounded.
-  return N->getOperand(0);
-}
-
 SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
   unsigned NewOpc = N->getOpcode();
   MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
@@ -238,11 +241,11 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) {
   case ExpandInteger:
   case ExpandFloat:
     break;
-  case Scalarize:
+  case ScalarizeVector:
     // Convert the element to an integer and promote it by hand.
     return DAG.getNode(ISD::ANY_EXTEND, OutVT,
                        BitConvertToInteger(GetScalarizedVector(InOp)));
-  case Split:
+  case SplitVector:
     // For example, i32 = BIT_CONVERT v2i16 on alpha.  Convert the split
     // pieces of the input into integers and reassemble in the final type.
     SDOperand Lo, Hi;
@@ -360,9 +363,9 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) {
   // The count is the same in the promoted type except if the original
   // value was zero.  This can be handled by setting the bit just off
   // the top of the original type.
-  Op = DAG.getNode(ISD::OR, NVT, Op,
-                   // FIXME: Do this using an APINT constant.
-                   DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
+  APInt TopBit(NVT.getSizeInBits(), 0);
+  TopBit.set(OVT.getSizeInBits());
+  Op = DAG.getNode(ISD::OR, NVT, Op, DAG.getConstant(TopBit, NVT));
   return DAG.getNode(ISD::CTTZ, NVT, Op);
 }
 
@@ -411,6 +414,37 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
   return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
 }
 
+SDOperand DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) {
+  SDOperand Chain = N->getOperand(0); // Get the chain.
+  SDOperand Ptr = N->getOperand(1); // Get the pointer.
+  MVT VT = N->getValueType(0);
+
+  const Value *V = cast<SrcValueSDNode>(N->getOperand(2))->getValue();
+  SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Chain, Ptr, V, 0);
+
+  // Increment the arg pointer, VAList, to the next vaarg
+  // FIXME: should the ABI size be used for the increment?  Think of
+  // x86 long double (10 bytes long, but aligned on 4 or 8 bytes) or
+  // integers of unusual size (such MVT::i1, which gives an increment
+  // of zero here!).
+  unsigned Increment = VT.getSizeInBits() / 8;
+  SDOperand Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
+                              DAG.getConstant(Increment, TLI.getPointerTy()));
+
+  // Store the incremented VAList to the pointer.
+  Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0);
+
+  // Load the actual argument out of the arg pointer VAList.
+  Tmp = DAG.getExtLoad(ISD::EXTLOAD, TLI.getTypeToTransformTo(VT), Tmp,
+                       VAList, NULL, 0, VT);
+
+  // Legalized the chain result - switch anything that used the old chain to
+  // use the new one.
+  ReplaceValueWith(SDOperand(N, 1), Tmp.getValue(1));
+  return Tmp;
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Integer Operand Promotion
 //===----------------------------------------------------------------------===//
@@ -421,40 +455,48 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
 /// node may need promotion or expansion as well as the specified one.
 bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
   DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n");
-  SDOperand Res;
-  switch (N->getOpcode()) {
-    default:
-#ifndef NDEBUG
-    cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
-    N->dump(&DAG); cerr << "\n";
-#endif
-    assert(0 && "Do not know how to promote this operator's operand!");
-    abort();
+  SDOperand Res = SDOperand();
 
-  case ISD::ANY_EXTEND:  Res = PromoteIntOp_ANY_EXTEND(N); break;
-  case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
-  case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
-  case ISD::TRUNCATE:    Res = PromoteIntOp_TRUNCATE(N); break;
-  case ISD::FP_EXTEND:   Res = PromoteIntOp_FP_EXTEND(N); break;
-  case ISD::FP_ROUND:    Res = PromoteIntOp_FP_ROUND(N); break;
-  case ISD::SINT_TO_FP:
-  case ISD::UINT_TO_FP:  Res = PromoteIntOp_INT_TO_FP(N); break;
-  case ISD::BUILD_PAIR:  Res = PromoteIntOp_BUILD_PAIR(N); break;
-
-  case ISD::BRCOND:      Res = PromoteIntOp_BRCOND(N, OpNo); break;
-  case ISD::BR_CC:       Res = PromoteIntOp_BR_CC(N, OpNo); break;
-  case ISD::SELECT:      Res = PromoteIntOp_SELECT(N, OpNo); break;
-  case ISD::SETCC:       Res = PromoteIntOp_SETCC(N, OpNo); break;
-
-  case ISD::STORE:       Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
-                                                    OpNo); break;
-
-  case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
-  case ISD::INSERT_VECTOR_ELT:
-    Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
-    break;
+  if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+      == TargetLowering::Custom)
+    Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
+
+  if (Res.Val == 0) {
+    switch (N->getOpcode()) {
+      default:
+  #ifndef NDEBUG
+      cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
+      N->dump(&DAG); cerr << "\n";
+  #endif
+      assert(0 && "Do not know how to promote this operator's operand!");
+      abort();
 
-  case ISD::MEMBARRIER:  Res = PromoteIntOp_MEMBARRIER(N); break;
+    case ISD::ANY_EXTEND:  Res = PromoteIntOp_ANY_EXTEND(N); break;
+    case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
+    case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
+    case ISD::TRUNCATE:    Res = PromoteIntOp_TRUNCATE(N); break;
+    case ISD::FP_EXTEND:   Res = PromoteIntOp_FP_EXTEND(N); break;
+    case ISD::FP_ROUND:    Res = PromoteIntOp_FP_ROUND(N); break;
+    case ISD::SINT_TO_FP:
+    case ISD::UINT_TO_FP:  Res = PromoteIntOp_INT_TO_FP(N); break;
+    case ISD::BUILD_PAIR:  Res = PromoteIntOp_BUILD_PAIR(N); break;
+
+    case ISD::BRCOND:      Res = PromoteIntOp_BRCOND(N, OpNo); break;
+    case ISD::BR_CC:       Res = PromoteIntOp_BR_CC(N, OpNo); break;
+    case ISD::SELECT:      Res = PromoteIntOp_SELECT(N, OpNo); break;
+    case ISD::SELECT_CC:   Res = PromoteIntOp_SELECT_CC(N, OpNo); break;
+    case ISD::SETCC:       Res = PromoteIntOp_SETCC(N, OpNo); break;
+
+    case ISD::STORE:       Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
+                                                      OpNo); break;
+
+    case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
+    case ISD::INSERT_VECTOR_ELT:
+      Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
+      break;
+
+    case ISD::MEMBARRIER:  Res = PromoteIntOp_MEMBARRIER(N); break;
+    }
   }
 
   // If the result is null, the sub-method took care of registering results etc.
@@ -568,7 +610,7 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) {
 }
 
 SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
-  assert(OpNo == 2 && "Don't know how to promote this operand");
+  assert(OpNo == 2 && "Don't know how to promote this operand!");
 
   SDOperand LHS = N->getOperand(2);
   SDOperand RHS = N->getOperand(3);
@@ -580,8 +622,20 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
                                 N->getOperand(1), LHS, RHS, N->getOperand(4));
 }
 
+SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) {
+  assert(OpNo == 0 && "Don't know how to promote this operand!");
+
+  SDOperand LHS = N->getOperand(0);
+  SDOperand RHS = N->getOperand(1);
+  PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(4))->get());
+
+  // The CC (#4) and the possible return values (#2 and #3) have legal types.
+  return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2),
+                                N->getOperand(3), N->getOperand(4));
+}
+
 SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) {
-  assert(OpNo == 0 && "Don't know how to promote this operand");
+  assert(OpNo == 0 && "Don't know how to promote this operand!");
 
   SDOperand LHS = N->getOperand(0);
   SDOperand RHS = N->getOperand(1);
@@ -732,10 +786,10 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
   Lo = Hi = SDOperand();
 
   // See if the target wants to custom expand this node.
-  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
-          TargetLowering::Custom) {
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
+      TargetLowering::Custom) {
     // If the target wants to, allow it to lower this itself.
-    if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
+    if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
       // Everything that once used N now uses P.  We are guaranteed that the
       // result value types of N and the result value types of P match.
       ReplaceNodeWith(N, P);
@@ -942,7 +996,17 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo,
   MVT VT = N->getValueType(0);
   SDOperand Op = N->getOperand(0);
   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
-  if (VT == MVT::i64) {
+
+  if (VT == MVT::i32) {
+    if (Op.getValueType() == MVT::f32)
+      LC = RTLIB::FPTOSINT_F32_I32;
+    else if (Op.getValueType() == MVT::f64)
+      LC = RTLIB::FPTOSINT_F64_I32;
+    else if (Op.getValueType() == MVT::f80)
+      LC = RTLIB::FPTOSINT_F80_I32;
+    else if (Op.getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOSINT_PPCF128_I32;
+  } else if (VT == MVT::i64) {
     if (Op.getValueType() == MVT::f32)
       LC = RTLIB::FPTOSINT_F32_I64;
     else if (Op.getValueType() == MVT::f64)
@@ -960,9 +1024,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo,
       LC = RTLIB::FPTOSINT_F80_I128;
     else if (Op.getValueType() == MVT::ppcf128)
       LC = RTLIB::FPTOSINT_PPCF128_I128;
-  } else {
-    assert(0 && "Unexpected fp-to-sint conversion!");
   }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!");
   SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi);
 }
 
@@ -971,7 +1034,16 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo,
   MVT VT = N->getValueType(0);
   SDOperand Op = N->getOperand(0);
   RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
-  if (VT == MVT::i64) {
+  if (VT == MVT::i32) {
+    if (Op.getValueType() == MVT::f32)
+      LC = RTLIB::FPTOUINT_F32_I32;
+    else if (Op.getValueType() == MVT::f64)
+      LC = RTLIB::FPTOUINT_F64_I32;
+    else if (Op.getValueType() == MVT::f80)
+      LC = RTLIB::FPTOUINT_F80_I32;
+    else if (Op.getValueType() == MVT::ppcf128)
+      LC = RTLIB::FPTOUINT_PPCF128_I32;
+  } else if (VT == MVT::i64) {
     if (Op.getValueType() == MVT::f32)
       LC = RTLIB::FPTOUINT_F32_I64;
     else if (Op.getValueType() == MVT::f64)
@@ -989,9 +1061,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo,
       LC = RTLIB::FPTOUINT_F80_I128;
     else if (Op.getValueType() == MVT::ppcf128)
       LC = RTLIB::FPTOUINT_PPCF128_I128;
-  } else {
-    assert(0 && "Unexpected fp-to-uint conversion!");
   }
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!");
   SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi);
 }
 
@@ -1577,11 +1648,11 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
 /// node may need promotion or expansion as well as the specified one.
 bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
   DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n");
-  SDOperand Res(0, 0);
+  SDOperand Res = SDOperand();
 
   if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
       == TargetLowering::Custom)
-    Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+    Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG);
 
   if (Res.Val == 0) {
     switch (N->getOpcode()) {