Combine ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD into ISD::LOADX. Add an
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAG.cpp
index 3545b246894f5e9a9eecfb4a01b8836e140270c7..07b72a63729385403e25f9a376f76b62e0c2e738 100644 (file)
@@ -558,6 +558,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 #endif
     assert(0 && "Do not know how to legalize this operator!");
     abort();
+  case ISD::JumpTableRelocBase:
+    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+    case TargetLowering::Custom:
+      Tmp1 = TLI.LowerOperation(Op, DAG);
+      if (Tmp1.Val) Result = Tmp1;
+      break;
+    default:
+      Result = LegalizeOp(Node->getOperand(0));
+      break;
+    }
+    break;
   case ISD::GlobalAddress:
   case ISD::ExternalSymbol:
   case ISD::ConstantPool:
@@ -788,7 +799,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       if (isDouble && CFP->isExactlyValue((float)CFP->getValue()) &&
           // Only do this if the target has a native EXTLOAD instruction from
           // f32.
-          TLI.isOperationLegal(ISD::EXTLOAD, MVT::f32)) {
+          TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
         LLVMC = cast<ConstantFP>(ConstantExpr::getCast(LLVMC, Type::FloatTy));
         VT = MVT::f32;
         Extend = true;
@@ -1361,19 +1372,19 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     AddLegalizedOperand(SDOperand(Node, 1), Tmp4);
     return Op.ResNo ? Tmp4 : Tmp3;
   }
-  case ISD::EXTLOAD:
-  case ISD::SEXTLOAD:
-  case ISD::ZEXTLOAD: {
+  case ISD::LOADX: {
     Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
     Tmp2 = LegalizeOp(Node->getOperand(1));  // Legalize the pointer.
 
     MVT::ValueType SrcVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
-    switch (TLI.getOperationAction(Node->getOpcode(), SrcVT)) {
+    unsigned LType = cast<ConstantSDNode>(Node->getOperand(4))->getValue();
+    switch (TLI.getLoadXAction(LType, SrcVT)) {
     default: assert(0 && "This action is not supported yet!");
     case TargetLowering::Promote:
-      assert(SrcVT == MVT::i1 && "Can only promote EXTLOAD from i1 -> i8!");
+      assert(SrcVT == MVT::i1 && "Can only promote LOADX from i1 -> i8!");
       Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2),
-                                      DAG.getValueType(MVT::i8));
+                                      DAG.getValueType(MVT::i8),
+                                      Node->getOperand(4));
       Tmp1 = Result.getValue(0);
       Tmp2 = Result.getValue(1);
       break;
@@ -1382,12 +1393,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       // FALLTHROUGH
     case TargetLowering::Legal:
       Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2),
-                                      Node->getOperand(3));
+                                      Node->getOperand(3), Node->getOperand(4));
       Tmp1 = Result.getValue(0);
       Tmp2 = Result.getValue(1);
       
       if (isCustom) {
-        Tmp3 = TLI.LowerOperation(Tmp3, DAG);
+        Tmp3 = TLI.LowerOperation(Result, DAG);
         if (Tmp3.Val) {
           Tmp1 = LegalizeOp(Tmp3);
           Tmp2 = LegalizeOp(Tmp3.getValue(1));
@@ -1403,14 +1414,13 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         Tmp2 = LegalizeOp(Load.getValue(1));
         break;
       }
-      assert(Node->getOpcode() != ISD::EXTLOAD &&
-             "EXTLOAD should always be supported!");
+      assert(LType != ISD::EXTLOAD && "EXTLOAD should always be supported!");
       // Turn the unsupported load into an EXTLOAD followed by an explicit
       // zero/sign extend inreg.
       Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0),
                               Tmp1, Tmp2, Node->getOperand(2), SrcVT);
       SDOperand ValRes;
-      if (Node->getOpcode() == ISD::SEXTLOAD)
+      if (LType == ISD::SEXTLOAD)
         ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
                              Result, DAG.getValueType(SrcVT));
       else
@@ -2148,6 +2158,19 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       if (Tmp1.Val) Result = Tmp1;
       break;
     case TargetLowering::Expand: {
+      if (Node->getValueType(0) == MVT::i32) {
+        switch (Node->getOpcode()) {
+        default:  assert(0 && "Do not know how to expand this integer BinOp!");
+        case ISD::UDIV:
+        case ISD::SDIV:
+          const char *FnName = Node->getOpcode() == ISD::UDIV
+            ? "__udivsi3" : "__divsi3";
+          SDOperand Dummy;
+          Result = ExpandLibCall(FnName, Node, Dummy);
+        };
+        break;
+      }
+
       assert(MVT::isVector(Node->getValueType(0)) &&
              "Cannot expand this binary operator!");
       // Expand the operation into a bunch of nasty scalar code.
@@ -2318,13 +2341,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       }
       break;
     case TargetLowering::Expand:
+      unsigned DivOpc= (Node->getOpcode() == ISD::UREM) ? ISD::UDIV : ISD::SDIV;
       if (MVT::isInteger(Node->getValueType(0))) {
-        // X % Y -> X-X/Y*Y
-        MVT::ValueType VT = Node->getValueType(0);
-        unsigned Opc = Node->getOpcode() == ISD::UREM ? ISD::UDIV : ISD::SDIV;
-        Result = DAG.getNode(Opc, VT, Tmp1, Tmp2);
-        Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
-        Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
+        if (TLI.getOperationAction(DivOpc, Node->getValueType(0)) ==
+            TargetLowering::Legal) {
+          // X % Y -> X-X/Y*Y
+          MVT::ValueType VT = Node->getValueType(0);
+          Result = DAG.getNode(DivOpc, VT, Tmp1, Tmp2);
+          Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
+          Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
+        } else {
+          assert(Node->getValueType(0) == MVT::i32 &&
+                 "Cannot expand this binary operator!");
+          const char *FnName = Node->getOpcode() == ISD::UREM
+            ? "__umodsi3" : "__modsi3";
+          SDOperand Dummy;
+          Result = ExpandLibCall(FnName, Node, Dummy);
+        }
       } else {
         // Floating point mod -> fmod libcall.
         const char *FnName = Node->getValueType(0) == MVT::f32 ? "fmodf":"fmod";
@@ -3208,12 +3241,12 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
     // Remember that we legalized the chain.
     AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
     break;
-  case ISD::SEXTLOAD:
-  case ISD::ZEXTLOAD:
-  case ISD::EXTLOAD:
-    Result = DAG.getExtLoad(Node->getOpcode(), NVT, Node->getOperand(0),
-                            Node->getOperand(1), Node->getOperand(2),
-                            cast<VTSDNode>(Node->getOperand(3))->getVT());
+  case ISD::LOADX:
+    Result =
+      DAG.getExtLoad((ISD::LoadExtType)Node->getConstantOperandVal(4),
+                     NVT, Node->getOperand(0), Node->getOperand(1),
+                     Node->getOperand(2),
+                     cast<VTSDNode>(Node->getOperand(3))->getVT());
     // Remember that we legalized the chain.
     AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
     break;
@@ -3758,6 +3791,72 @@ bool SelectionDAGLegalize::ExpandShift(unsigned Opc, SDOperand Op,SDOperand Amt,
       return true;
     }
   }
+  
+  // Okay, the shift amount isn't constant.  However, if we can tell that it is
+  // >= 32 or < 32, we can still simplify it, without knowing the actual value.
+  uint64_t Mask = NVTBits, KnownZero, KnownOne;
+  TLI.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
+  
+  // If we know that the high bit of the shift amount is one, then we can do
+  // this as a couple of simple shifts.
+  if (KnownOne & Mask) {
+    // Mask out the high bit, which we know is set.
+    Amt = DAG.getNode(ISD::AND, Amt.getValueType(), Amt,
+                      DAG.getConstant(NVTBits-1, Amt.getValueType()));
+    
+    // Expand the incoming operand to be shifted, so that we have its parts
+    SDOperand InL, InH;
+    ExpandOp(Op, InL, InH);
+    switch(Opc) {
+    case ISD::SHL:
+      Lo = DAG.getConstant(0, NVT);              // Low part is zero.
+      Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part.
+      return true;
+    case ISD::SRL:
+      Hi = DAG.getConstant(0, NVT);              // Hi part is zero.
+      Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part.
+      return true;
+    case ISD::SRA:
+      Hi = DAG.getNode(ISD::SRA, NVT, InH,       // Sign extend high part.
+                       DAG.getConstant(NVTBits-1, Amt.getValueType()));
+      Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part.
+      return true;
+    }
+  }
+  
+  // If we know that the high bit of the shift amount is zero, then we can do
+  // this as a couple of simple shifts.
+  if (KnownZero & Mask) {
+    // Compute 32-amt.
+    SDOperand Amt2 = DAG.getNode(ISD::SUB, Amt.getValueType(),
+                                 DAG.getConstant(NVTBits, Amt.getValueType()),
+                                 Amt);
+    
+    // Expand the incoming operand to be shifted, so that we have its parts
+    SDOperand InL, InH;
+    ExpandOp(Op, InL, InH);
+    switch(Opc) {
+    case ISD::SHL:
+      Lo = DAG.getNode(ISD::SHL, NVT, InL, Amt);
+      Hi = DAG.getNode(ISD::OR, NVT,
+                       DAG.getNode(ISD::SHL, NVT, InH, Amt),
+                       DAG.getNode(ISD::SRL, NVT, InL, Amt2));
+      return true;
+    case ISD::SRL:
+      Hi = DAG.getNode(ISD::SRL, NVT, InH, Amt);
+      Lo = DAG.getNode(ISD::OR, NVT,
+                       DAG.getNode(ISD::SRL, NVT, InL, Amt),
+                       DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+      return true;
+    case ISD::SRA:
+      Hi = DAG.getNode(ISD::SRA, NVT, InH, Amt);
+      Lo = DAG.getNode(ISD::OR, NVT,
+                       DAG.getNode(ISD::SRL, NVT, InL, Amt),
+                       DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+      return true;
+    }
+  }
+  
   return false;
 }
 
@@ -4379,10 +4478,11 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
                      Node->getOperand(1), TH, FH, Node->getOperand(4));
     break;
   }
-  case ISD::SEXTLOAD: {
+  case ISD::LOADX: {
     SDOperand Chain = Node->getOperand(0);
     SDOperand Ptr   = Node->getOperand(1);
     MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
+    unsigned LType = Node->getConstantOperandVal(4);
     
     if (EVT == NVT)
       Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
@@ -4392,48 +4492,20 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
     
     // Remember that we legalized the chain.
     AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
-    
-    // The high part is obtained by SRA'ing all but one of the bits of the lo
-    // part.
-    unsigned LoSize = MVT::getSizeInBits(Lo.getValueType());
-    Hi = DAG.getNode(ISD::SRA, NVT, Lo, DAG.getConstant(LoSize-1,
-                                                       TLI.getShiftAmountTy()));
-    break;
-  }
-  case ISD::ZEXTLOAD: {
-    SDOperand Chain = Node->getOperand(0);
-    SDOperand Ptr   = Node->getOperand(1);
-    MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
-    
-    if (EVT == NVT)
-      Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
-    else
-      Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Chain, Ptr, Node->getOperand(2),
-                          EVT);
-    
-    // Remember that we legalized the chain.
-    AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
 
-    // The high part is just a zero.
-    Hi = DAG.getConstant(0, NVT);
-    break;
-  }
-  case ISD::EXTLOAD: {
-    SDOperand Chain = Node->getOperand(0);
-    SDOperand Ptr   = Node->getOperand(1);
-    MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
-    
-    if (EVT == NVT)
-      Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
-    else
-      Lo = DAG.getExtLoad(ISD::EXTLOAD, NVT, Chain, Ptr, Node->getOperand(2),
-                          EVT);
-    
-    // Remember that we legalized the chain.
-    AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
-    
-    // The high part is undefined.
-    Hi = DAG.getNode(ISD::UNDEF, NVT);
+    if (LType == ISD::SEXTLOAD) {
+      // The high part is obtained by SRA'ing all but one of the bits of the lo
+      // part.
+      unsigned LoSize = MVT::getSizeInBits(Lo.getValueType());
+      Hi = DAG.getNode(ISD::SRA, NVT, Lo, DAG.getConstant(LoSize-1,
+                                                          TLI.getShiftAmountTy()));
+    } else if (LType == ISD::ZEXTLOAD) {
+      // The high part is just a zero.
+      Hi = DAG.getConstant(0, NVT);
+    } else /* if (LType == ISD::EXTLOAD) */ {
+      // The high part is undefined.
+      Hi = DAG.getNode(ISD::UNDEF, NVT);
+    }
     break;
   }
   case ISD::ANY_EXTEND:
@@ -4559,6 +4631,24 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       }
     }
     
+    // If ADDC/ADDE are supported and if the shift amount is a constant 1, emit 
+    // this X << 1 as X+X.
+    if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(ShiftAmt)) {
+      if (ShAmt->getValue() == 1 && TLI.isOperationLegal(ISD::ADDC, NVT) && 
+          TLI.isOperationLegal(ISD::ADDE, NVT)) {
+        SDOperand LoOps[2], HiOps[3];
+        ExpandOp(Node->getOperand(0), LoOps[0], HiOps[0]);
+        SDVTList VTList = DAG.getVTList(LoOps[0].getValueType(), MVT::Flag);
+        LoOps[1] = LoOps[0];
+        Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+
+        HiOps[1] = HiOps[0];
+        HiOps[2] = Lo.getValue(1);
+        Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+        break;
+      }
+    }
+    
     // If we can emit an efficient shift operation, do so now.
     if (ExpandShift(ISD::SHL, Node->getOperand(0), ShiftAmt, Lo, Hi))
       break;
@@ -4657,25 +4747,33 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
     SDOperand LHSL, LHSH, RHSL, RHSH;
     ExpandOp(Node->getOperand(0), LHSL, LHSH);
     ExpandOp(Node->getOperand(1), RHSL, RHSH);
-    const MVT::ValueType *VTs =
-      DAG.getNodeValueTypes(LHSL.getValueType(),MVT::Flag);
-    SDOperand LoOps[2], HiOps[2];
+    SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+    SDOperand LoOps[2], HiOps[3];
     LoOps[0] = LHSL;
     LoOps[1] = RHSL;
     HiOps[0] = LHSH;
     HiOps[1] = RHSH;
     if (Node->getOpcode() == ISD::ADD) {
-      Lo = DAG.getNode(ISD::ADDC, VTs, 2, LoOps, 2);
+      Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
       HiOps[2] = Lo.getValue(1);
-      Hi = DAG.getNode(ISD::ADDE, VTs, 2, HiOps, 3);
+      Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
     } else {
-      Lo = DAG.getNode(ISD::SUBC, VTs, 2, LoOps, 2);
+      Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
       HiOps[2] = Lo.getValue(1);
-      Hi = DAG.getNode(ISD::SUBE, VTs, 2, HiOps, 3);
+      Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
     }
     break;
   }
   case ISD::MUL: {
+    // If the target wants to custom expand this, let them.
+    if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) {
+      SDOperand New = TLI.LowerOperation(Op, DAG);
+      if (New.Val) {
+        ExpandOp(New, Lo, Hi);
+        break;
+      }
+    }
+    
     bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
     bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
     bool UseLibCall = true;
@@ -4697,22 +4795,28 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
           LH.getOpcode() == ISD::SRA && LH.getOperand(0) == LL &&
           LH.getOperand(1).getOpcode() == ISD::Constant &&
           cast<ConstantSDNode>(LH.getOperand(1))->getValue() == SH) {
+        // FIXME: Move this to the dag combiner.
+        
+        // Low part:
+        Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+        // High part:
         Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
-        UseLibCall = false;
+        break;
       } else if (HasMULHU) {
+        // Low part:
+        Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+        
+        // High part:
         Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
         RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
         LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
         Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
         Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
-        UseLibCall = false;
+        break;
       }
-      if (!UseLibCall)
-        Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
     }
 
-    if (UseLibCall)
-      Lo = ExpandLibCall("__muldi3" , Node, Hi);
+    Lo = ExpandLibCall("__muldi3" , Node, Hi);
     break;
   }
   case ISD::SDIV: Lo = ExpandLibCall("__divdi3" , Node, Hi); break;