Use MVN for ~t2_so_imm immediates.
[oota-llvm.git] / lib / Target / MSP430 / MSP430ISelDAGToDAG.cpp
index 3b28668f550658bcc497f4a52796372b0f0ab61a..bf49ec0bff4621464d73249e71704b1e61de3105 100644 (file)
@@ -28,8 +28,6 @@
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
-#include <queue>
-#include <set>
 using namespace llvm;
 
 /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
@@ -41,8 +39,8 @@ namespace {
     const MSP430Subtarget &Subtarget;
 
   public:
-    MSP430DAGToDAGISel(MSP430TargetMachine &TM)
-      : SelectionDAGISel(TM),
+    MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
+      : SelectionDAGISel(TM, OptLevel),
         Lowering(*TM.getTargetLowering()),
         Subtarget(*TM.getSubtargetImpl()) { }
 
@@ -57,7 +55,7 @@ namespace {
 
   private:
     SDNode *Select(SDValue Op);
-    bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Disp, SDValue &Base);
+    bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp);
 
   #ifndef NDEBUG
     unsigned Indent;
@@ -68,33 +66,52 @@ namespace {
 /// createMSP430ISelDag - This pass converts a legalized DAG into a
 /// MSP430-specific DAG, ready for instruction scheduling.
 ///
-FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) {
-  return new MSP430DAGToDAGISel(TM);
+FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
+                                        CodeGenOpt::Level OptLevel) {
+  return new MSP430DAGToDAGISel(TM, OptLevel);
 }
 
+// FIXME: This is pretty dummy routine and needs to be rewritten in the future.
 bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr,
-                                    SDValue &Disp, SDValue &Base) {
-  // We don't support frame index stuff yet.
-  if (isa<FrameIndexSDNode>(Addr))
-    return false;
-
-  // Operand is a result from ADD with constant operand which fits into i16.
-  if (Addr.getOpcode() == ISD::ADD) {
-    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
+                                    SDValue &Base, SDValue &Disp) {
+  // Try to match frame address first.
+  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
+    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16);
+    Disp = CurDAG->getTargetConstant(0, MVT::i16);
+    return true;
+  }
+
+  switch (Addr.getOpcode()) {
+  case ISD::ADD:
+   // Operand is a result from ADD with constant operand which fits into i16.
+   if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
       uint64_t CVal = CN->getZExtValue();
       // Offset should fit into 16 bits.
       if (((CVal << 48) >> 48) == CVal) {
-        // We don't support frame index stuff yet.
-        if (isa<FrameIndexSDNode>(Addr.getOperand(0)))
-          return false;
+        SDValue N0 = Addr.getOperand(0);
+        if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N0))
+          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16);
+        else
+          Base = N0;
 
-        Base = Addr.getOperand(0);
         Disp = CurDAG->getTargetConstant(CVal, MVT::i16);
-
         return true;
       }
     }
-  }
+    break;
+  case MSP430ISD::Wrapper:
+    SDValue N0 = Addr.getOperand(0);
+    if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
+      Base = CurDAG->getTargetGlobalAddress(G->getGlobal(),
+                                            MVT::i16, G->getOffset());
+      Disp = CurDAG->getTargetConstant(0, MVT::i16);
+      return true;
+    } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(N0)) {
+      Base = CurDAG->getTargetExternalSymbol(E->getSymbol(), MVT::i16);
+      Disp = CurDAG->getTargetConstant(0, MVT::i16);
+    }
+    break;
+  };
 
   Base = Addr;
   Disp = CurDAG->getTargetConstant(0, MVT::i16);
@@ -109,14 +126,22 @@ bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr,
 void MSP430DAGToDAGISel::InstructionSelect() {
   DEBUG(BB->dump());
 
-  // Select target instructions for the DAG.
+  // Codegen the basic block.
+#ifndef NDEBUG
+  DOUT << "===== Instruction selection begins:\n";
+  Indent = 0;
+#endif
   SelectRoot(*CurDAG);
+#ifndef NDEBUG
+  DOUT << "===== Instruction selection ends:\n";
+#endif
 
   CurDAG->RemoveDeadNodes();
 }
 
 SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
   SDNode *Node = Op.getNode();
+  DebugLoc dl = Op.getDebugLoc();
 
   // Dump information about the Node being selected
   #ifndef NDEBUG
@@ -137,15 +162,20 @@ SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
     return NULL;
   }
 
-  // Instruction Selection not handled by the auto-generated tablegen selection
-  // should be handled here.
-  // Something like this:
-  //   unsigned Opcode = Node->getOpcode();
-  //   switch (Opcode) {
-  //   default: break;
-  //   case ISD::Foo:
-  //    return SelectFoo(Node)
-  //  }
+  // Few custom selection stuff.
+  switch (Node->getOpcode()) {
+  default: break;
+  case ISD::FrameIndex: {
+    assert(Op.getValueType() == MVT::i16);
+    int FI = cast<FrameIndexSDNode>(Node)->getIndex();
+    SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
+    if (Node->hasOneUse())
+      return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
+                                  TFI, CurDAG->getTargetConstant(0, MVT::i16));
+    return CurDAG->getTargetNode(MSP430::ADD16ri, dl, MVT::i16,
+                                 TFI, CurDAG->getTargetConstant(0, MVT::i16));
+  }
+  }
 
   // Select the default instruction
   SDNode *ResNode = SelectCode(Op);