Add support for 128 bit multiplicative operations.
Lack of these caused a bootstrap failure with Fortran
on x86-64 with LegalizeTypes turned on.  While there,
be nice to 16 bit machines and support expansion of
i32 too.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53408 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 9452d9e..aae95bf 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -35,14 +35,19 @@
     SRA_I64,
     MUL_I32,
     MUL_I64,
+    MUL_I128,
     SDIV_I32,
     SDIV_I64,
+    SDIV_I128,
     UDIV_I32,
     UDIV_I64,
+    UDIV_I128,
     SREM_I32,
     SREM_I64,
+    SREM_I128,
     UREM_I32,
     UREM_I64,
+    UREM_I128,
     NEG_I32,
     NEG_I64,
 
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index bde61ad..0db87e9 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -1077,8 +1077,8 @@
 
   MVT VT = N->getValueType(0);
   MVT NVT = TLI.getTypeToTransformTo(VT);
-  SDOperand Ch  = N->getChain();    // Legalize the chain.
-  SDOperand Ptr = N->getBasePtr();  // Legalize the pointer.
+  SDOperand Ch  = N->getChain();
+  SDOperand Ptr = N->getBasePtr();
   ISD::LoadExtType ExtType = N->getExtensionType();
   int SVOffset = N->getSrcValueOffset();
   unsigned Alignment = N->getAlignment();
@@ -1330,14 +1330,14 @@
   }
 
   // If nothing else, we can make a libcall.
-  RTLIB::Libcall LC;
-  switch (VT.getSimpleVT()) {
-  default:
-    assert(false && "Unsupported MUL!");
-  case MVT::i64:
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::MUL_I32;
+  else if (VT == MVT::i64)
     LC = RTLIB::MUL_I64;
-    break;
-  }
+  else if (VT == MVT::i128)
+    LC = RTLIB::MUL_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!");
 
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
   SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*sign irrelevant*/), Lo, Hi);
@@ -1345,34 +1345,70 @@
 
 void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::SDIV_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::SDIV_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::SDIV_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::SREM_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::SREM_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::SREM_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::UDIV_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::UDIV_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::UDIV_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
-  assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!");
+  MVT VT = N->getValueType(0);
+
+  RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+  if (VT == MVT::i32)
+    LC = RTLIB::UREM_I32;
+  else if (VT == MVT::i64)
+    LC = RTLIB::UREM_I64;
+  else if (VT == MVT::i128)
+    LC = RTLIB::UREM_I128;
+  assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!");
+
   SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
-  SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false),
-               Lo, Hi);
+  SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi);
 }
 
 void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 18e1c87..ee720121 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -37,14 +37,19 @@
   Names[RTLIB::SRA_I64] = "__ashrdi3";
   Names[RTLIB::MUL_I32] = "__mulsi3";
   Names[RTLIB::MUL_I64] = "__muldi3";
+  Names[RTLIB::MUL_I128] = "__multi3";
   Names[RTLIB::SDIV_I32] = "__divsi3";
   Names[RTLIB::SDIV_I64] = "__divdi3";
+  Names[RTLIB::SDIV_I128] = "__divti3";
   Names[RTLIB::UDIV_I32] = "__udivsi3";
   Names[RTLIB::UDIV_I64] = "__udivdi3";
+  Names[RTLIB::UDIV_I128] = "__udivti3";
   Names[RTLIB::SREM_I32] = "__modsi3";
   Names[RTLIB::SREM_I64] = "__moddi3";
+  Names[RTLIB::SREM_I128] = "__modti3";
   Names[RTLIB::UREM_I32] = "__umodsi3";
   Names[RTLIB::UREM_I64] = "__umoddi3";
+  Names[RTLIB::UREM_I128] = "__umodti3";
   Names[RTLIB::NEG_I32] = "__negsi2";
   Names[RTLIB::NEG_I64] = "__negdi2";
   Names[RTLIB::ADD_F32] = "__addsf3";