First try of the post-inc operands handling... Not fully worked, though :(

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86386 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
index b45690b..ac01bf8 100644
--- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
+++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
@@ -43,6 +43,9 @@
 static const bool ViewRMWDAGs = false;
 #endif
 
+static cl::opt<bool>
+EnablePostIncOps("enable-msp430-post-inc-ops", cl::Hidden);
+
 STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
 
 
@@ -148,6 +151,9 @@
     void PreprocessForRMW();
     SDNode *Select(SDValue Op);
     SDNode *SelectIndexedLoad(SDValue Op);
+    SDNode *SelectIndexedBinOp(SDValue Op, SDValue N1, SDValue N2,
+                               unsigned Opc8, unsigned Opc16);
+
     bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp);
 
   #ifndef NDEBUG
@@ -598,39 +604,85 @@
 }
 
 
-SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDValue Op) {
-  LoadSDNode *LD = cast<LoadSDNode>(Op);
+static bool isValidIndexedLoad(const LoadSDNode *LD) {
   ISD::MemIndexedMode AM = LD->getAddressingMode();
   if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
-    return NULL;
+    return false;
 
   EVT VT = LD->getMemoryVT();
 
-  unsigned Opcode = 0;
   switch (VT.getSimpleVT().SimpleTy) {
   case MVT::i8:
     // Sanity check
     if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
-      return NULL;
+      return false;
 
-    Opcode = MSP430::MOV8rm_POST;
     break;
   case MVT::i16:
     // Sanity check
     if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
-      return NULL;
+      return false;
 
+    break;
+  default:
+    return false;
+  }
+
+  return true;
+}
+
+SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDValue Op) {
+  LoadSDNode *LD = cast<LoadSDNode>(Op);
+  if (!isValidIndexedLoad(LD))
+    return NULL;
+
+  MVT VT = LD->getMemoryVT().getSimpleVT();
+
+  unsigned Opcode = 0;
+  switch (VT.SimpleTy) {
+  case MVT::i8:
+    Opcode = MSP430::MOV8rm_POST;
+    break;
+  case MVT::i16:
     Opcode = MSP430::MOV16rm_POST;
     break;
   default:
     return NULL;
   }
 
-  return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(),
-                                VT.getSimpleVT().SimpleTy, MVT::i16, MVT::Other,
-                                LD->getBasePtr(), LD->getChain());
+   return CurDAG->getMachineNode(Opcode, Op.getDebugLoc(),
+                                 VT, MVT::i16, MVT::Other,
+                                 LD->getBasePtr(), LD->getChain());
 }
 
+SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDValue Op,
+                                               SDValue N1, SDValue N2,
+                                               unsigned Opc8, unsigned Opc16) {
+  if (N1.getOpcode() == ISD::LOAD &&
+      N1.hasOneUse() &&
+      IsLegalAndProfitableToFold(N1.getNode(), Op.getNode(), Op.getNode())) {
+    LoadSDNode *LD = cast<LoadSDNode>(N1);
+    if (!isValidIndexedLoad(LD))
+      return NULL;
+
+    MVT VT = LD->getMemoryVT().getSimpleVT();
+    unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
+    MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
+    MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
+    SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
+    SDNode *ResNode =
+      CurDAG->SelectNodeTo(Op.getNode(), Opc,
+                           VT, MVT::i16, MVT::Other,
+                           Ops0, 3);
+    cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
+    ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 3));
+    return ResNode;
+  }
+
+  return NULL;
+}
+
+
 /// InstructionSelect - This callback is invoked by
 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
 void MSP430DAGToDAGISel::InstructionSelect() {
@@ -693,6 +745,21 @@
       return ResNode;
     // Other cases are autogenerated.
     break;
+    case ISD::ADD:
+     if (EnablePostIncOps) {
+      if (SDNode *ResNode =
+           SelectIndexedBinOp(Op,
+                              Op.getOperand(0), Op.getOperand(1),
+                              MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
+        return ResNode;
+      else if (SDNode *ResNode =
+                SelectIndexedBinOp(Op, Op.getOperand(1), Op.getOperand(0),
+                                   MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
+        return ResNode;
+     }
+
+    // Other cases are autogenerated.
+    break;
   }
 
   // Select the default instruction