Migrate X86 and ARM from using X86ISD::{,I}DIV and ARMISD::MULHILO{U,S} to
use ISD::{S,U}DIVREM and ISD::{S,U}MUL_HIO. Move the lowering code
associated with these operators into target-independent in LegalizeDAG.cpp
and TargetLowering.cpp.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42762 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 6305073..869e68b 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -154,26 +154,41 @@
     setOperationAction(ISD::BIT_CONVERT      , MVT::i32  , Expand);
   }
 
-  // Divide and remainder are lowered to use div or idiv in legalize in
-  // order to expose the intermediate computations to trivial CSE. This is
-  // most noticeable when both x/y and x%y are being computed; they can be
-  // done with a single div or idiv.
-  setOperationAction(ISD::SDIV            , MVT::i8    , Custom);
-  setOperationAction(ISD::UDIV            , MVT::i8    , Custom);
-  setOperationAction(ISD::SREM            , MVT::i8    , Custom);
-  setOperationAction(ISD::UREM            , MVT::i8    , Custom);
-  setOperationAction(ISD::SDIV            , MVT::i16   , Custom);
-  setOperationAction(ISD::UDIV            , MVT::i16   , Custom);
-  setOperationAction(ISD::SREM            , MVT::i16   , Custom);
-  setOperationAction(ISD::UREM            , MVT::i16   , Custom);
-  setOperationAction(ISD::SDIV            , MVT::i32   , Custom);
-  setOperationAction(ISD::UDIV            , MVT::i32   , Custom);
-  setOperationAction(ISD::SREM            , MVT::i32   , Custom);
-  setOperationAction(ISD::UREM            , MVT::i32   , Custom);
-  setOperationAction(ISD::SDIV            , MVT::i64   , Custom);
-  setOperationAction(ISD::UDIV            , MVT::i64   , Custom);
-  setOperationAction(ISD::SREM            , MVT::i64   , Custom);
-  setOperationAction(ISD::UREM            , MVT::i64   , Custom);
+  // Scalar integer multiply, multiply-high, divide, and remainder are
+  // lowered to use operations that produce two results, to match the
+  // available instructions. This exposes the two-result form to trivial
+  // CSE, which is able to combine x/y and x%y into a single instruction,
+  // for example. The single-result multiply instructions are introduced
+  // in X86ISelDAGToDAG.cpp, after CSE, for uses where the the high part
+  // is not needed.
+  setOperationAction(ISD::MUL             , MVT::i8    , Expand);
+  setOperationAction(ISD::MULHS           , MVT::i8    , Expand);
+  setOperationAction(ISD::MULHU           , MVT::i8    , Expand);
+  setOperationAction(ISD::SDIV            , MVT::i8    , Expand);
+  setOperationAction(ISD::UDIV            , MVT::i8    , Expand);
+  setOperationAction(ISD::SREM            , MVT::i8    , Expand);
+  setOperationAction(ISD::UREM            , MVT::i8    , Expand);
+  setOperationAction(ISD::MUL             , MVT::i16   , Expand);
+  setOperationAction(ISD::MULHS           , MVT::i16   , Expand);
+  setOperationAction(ISD::MULHU           , MVT::i16   , Expand);
+  setOperationAction(ISD::SDIV            , MVT::i16   , Expand);
+  setOperationAction(ISD::UDIV            , MVT::i16   , Expand);
+  setOperationAction(ISD::SREM            , MVT::i16   , Expand);
+  setOperationAction(ISD::UREM            , MVT::i16   , Expand);
+  setOperationAction(ISD::MUL             , MVT::i32   , Expand);
+  setOperationAction(ISD::MULHS           , MVT::i32   , Expand);
+  setOperationAction(ISD::MULHU           , MVT::i32   , Expand);
+  setOperationAction(ISD::SDIV            , MVT::i32   , Expand);
+  setOperationAction(ISD::UDIV            , MVT::i32   , Expand);
+  setOperationAction(ISD::SREM            , MVT::i32   , Expand);
+  setOperationAction(ISD::UREM            , MVT::i32   , Expand);
+  setOperationAction(ISD::MUL             , MVT::i64   , Expand);
+  setOperationAction(ISD::MULHS           , MVT::i64   , Expand);
+  setOperationAction(ISD::MULHU           , MVT::i64   , Expand);
+  setOperationAction(ISD::SDIV            , MVT::i64   , Expand);
+  setOperationAction(ISD::UDIV            , MVT::i64   , Expand);
+  setOperationAction(ISD::SREM            , MVT::i64   , Expand);
+  setOperationAction(ISD::UREM            , MVT::i64   , Expand);
 
   setOperationAction(ISD::BR_JT            , MVT::Other, Expand);
   setOperationAction(ISD::BRCOND           , MVT::Other, Custom);
@@ -449,6 +464,10 @@
     setOperationAction(ISD::FPOWI, (MVT::ValueType)VT, Expand);
     setOperationAction(ISD::FSQRT, (MVT::ValueType)VT, Expand);
     setOperationAction(ISD::FCOPYSIGN, (MVT::ValueType)VT, Expand);
+    setOperationAction(ISD::SMUL_LOHI, (MVT::ValueType)VT, Expand);
+    setOperationAction(ISD::UMUL_LOHI, (MVT::ValueType)VT, Expand);
+    setOperationAction(ISD::SDIVREM, (MVT::ValueType)VT, Expand);
+    setOperationAction(ISD::UDIVREM, (MVT::ValueType)VT, Expand);
   }
 
   if (Subtarget->hasMMX()) {
@@ -3398,22 +3417,6 @@
     return DAG.getNode(ISD::MERGE_VALUES, VTs, 2, &Ops[0], Ops.size());
 }
 
-SDOperand X86TargetLowering::LowerIntegerDivOrRem(SDOperand Op, SelectionDAG &DAG) {
-  unsigned Opcode = Op.getOpcode();
-  MVT::ValueType NVT = Op.getValueType();
-  bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
-  bool isDiv    = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
-  unsigned Opc = isSigned ? X86ISD::IDIV : X86ISD::DIV;
-
-  SDOperand Ops[] = { Op.getOperand(0), Op.getOperand(1) };
-  SDOperand DR = DAG.getNode(Opc, DAG.getVTList(NVT, NVT), Ops, 2);
-
-  if (isDiv)
-    return DR;
-
-  return SDOperand(DR.Val, 1);
-}
-
 SDOperand X86TargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
   assert(Op.getOperand(0).getValueType() <= MVT::i64 &&
          Op.getOperand(0).getValueType() >= MVT::i16 &&
@@ -4545,10 +4548,6 @@
   case ISD::SHL_PARTS:
   case ISD::SRA_PARTS:
   case ISD::SRL_PARTS:          return LowerShift(Op, DAG);
-  case ISD::SDIV:
-  case ISD::UDIV:
-  case ISD::SREM:
-  case ISD::UREM:               return LowerIntegerDivOrRem(Op, DAG);
   case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG);
   case ISD::FP_TO_SINT:         return LowerFP_TO_SINT(Op, DAG);
   case ISD::FABS:               return LowerFABS(Op, DAG);
@@ -4620,8 +4619,6 @@
   case X86ISD::TLSADDR:            return "X86ISD::TLSADDR";
   case X86ISD::THREAD_POINTER:     return "X86ISD::THREAD_POINTER";
   case X86ISD::EH_RETURN:          return "X86ISD::EH_RETURN";
-  case X86ISD::DIV:                return "X86ISD::DIV";
-  case X86ISD::IDIV:               return "X86ISD::IDIV";
   }
 }