Home | History | Annotate | Download | only in MSP430
      1 //===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines an instruction selector for the MSP430 target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "MSP430.h"
     15 #include "MSP430TargetMachine.h"
     16 #include "llvm/CodeGen/MachineFrameInfo.h"
     17 #include "llvm/CodeGen/MachineFunction.h"
     18 #include "llvm/CodeGen/MachineInstrBuilder.h"
     19 #include "llvm/CodeGen/MachineRegisterInfo.h"
     20 #include "llvm/CodeGen/SelectionDAG.h"
     21 #include "llvm/CodeGen/SelectionDAGISel.h"
     22 #include "llvm/IR/CallingConv.h"
     23 #include "llvm/IR/Constants.h"
     24 #include "llvm/IR/DerivedTypes.h"
     25 #include "llvm/IR/Function.h"
     26 #include "llvm/IR/Intrinsics.h"
     27 #include "llvm/Support/Compiler.h"
     28 #include "llvm/Support/Debug.h"
     29 #include "llvm/Support/ErrorHandling.h"
     30 #include "llvm/Support/raw_ostream.h"
     31 #include "llvm/Target/TargetLowering.h"
     32 using namespace llvm;
     33 
     34 namespace {
     35   struct MSP430ISelAddressMode {
     36     enum {
     37       RegBase,
     38       FrameIndexBase
     39     } BaseType;
     40 
     41     struct {            // This is really a union, discriminated by BaseType!
     42       SDValue Reg;
     43       int FrameIndex;
     44     } Base;
     45 
     46     int16_t Disp;
     47     const GlobalValue *GV;
     48     const Constant *CP;
     49     const BlockAddress *BlockAddr;
     50     const char *ES;
     51     int JT;
     52     unsigned Align;    // CP alignment.
     53 
     54     MSP430ISelAddressMode()
     55       : BaseType(RegBase), Disp(0), GV(0), CP(0), BlockAddr(0),
     56         ES(0), JT(-1), Align(0) {
     57     }
     58 
     59     bool hasSymbolicDisplacement() const {
     60       return GV != 0 || CP != 0 || ES != 0 || JT != -1;
     61     }
     62 
     63     void dump() {
     64       errs() << "MSP430ISelAddressMode " << this << '\n';
     65       if (BaseType == RegBase && Base.Reg.getNode() != 0) {
     66         errs() << "Base.Reg ";
     67         Base.Reg.getNode()->dump();
     68       } else if (BaseType == FrameIndexBase) {
     69         errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
     70       }
     71       errs() << " Disp " << Disp << '\n';
     72       if (GV) {
     73         errs() << "GV ";
     74         GV->dump();
     75       } else if (CP) {
     76         errs() << " CP ";
     77         CP->dump();
     78         errs() << " Align" << Align << '\n';
     79       } else if (ES) {
     80         errs() << "ES ";
     81         errs() << ES << '\n';
     82       } else if (JT != -1)
     83         errs() << " JT" << JT << " Align" << Align << '\n';
     84     }
     85   };
     86 }
     87 
     88 /// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
     89 /// instructions for SelectionDAG operations.
     90 ///
     91 namespace {
     92   class MSP430DAGToDAGISel : public SelectionDAGISel {
     93     const MSP430TargetLowering &Lowering;
     94     const MSP430Subtarget &Subtarget;
     95 
     96   public:
     97     MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
     98       : SelectionDAGISel(TM, OptLevel),
     99         Lowering(*TM.getTargetLowering()),
    100         Subtarget(*TM.getSubtargetImpl()) { }
    101 
    102     virtual const char *getPassName() const {
    103       return "MSP430 DAG->DAG Pattern Instruction Selection";
    104     }
    105 
    106     bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
    107     bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
    108     bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
    109 
    110     virtual bool
    111     SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
    112                                  std::vector<SDValue> &OutOps);
    113 
    114     // Include the pieces autogenerated from the target description.
    115   #include "MSP430GenDAGISel.inc"
    116 
    117   private:
    118     SDNode *Select(SDNode *N);
    119     SDNode *SelectIndexedLoad(SDNode *Op);
    120     SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
    121                                unsigned Opc8, unsigned Opc16);
    122 
    123     bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
    124   };
    125 }  // end anonymous namespace
    126 
    127 /// createMSP430ISelDag - This pass converts a legalized DAG into a
    128 /// MSP430-specific DAG, ready for instruction scheduling.
    129 ///
    130 FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
    131                                         CodeGenOpt::Level OptLevel) {
    132   return new MSP430DAGToDAGISel(TM, OptLevel);
    133 }
    134 
    135 
    136 /// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
    137 /// These wrap things that will resolve down into a symbol reference.  If no
    138 /// match is possible, this returns true, otherwise it returns false.
    139 bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
    140   // If the addressing mode already has a symbol as the displacement, we can
    141   // never match another symbol.
    142   if (AM.hasSymbolicDisplacement())
    143     return true;
    144 
    145   SDValue N0 = N.getOperand(0);
    146 
    147   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
    148     AM.GV = G->getGlobal();
    149     AM.Disp += G->getOffset();
    150     //AM.SymbolFlags = G->getTargetFlags();
    151   } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
    152     AM.CP = CP->getConstVal();
    153     AM.Align = CP->getAlignment();
    154     AM.Disp += CP->getOffset();
    155     //AM.SymbolFlags = CP->getTargetFlags();
    156   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
    157     AM.ES = S->getSymbol();
    158     //AM.SymbolFlags = S->getTargetFlags();
    159   } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
    160     AM.JT = J->getIndex();
    161     //AM.SymbolFlags = J->getTargetFlags();
    162   } else {
    163     AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
    164     //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
    165   }
    166   return false;
    167 }
    168 
    169 /// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
    170 /// specified addressing mode without any further recursion.
    171 bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
    172   // Is the base register already occupied?
    173   if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
    174     // If so, we cannot select it.
    175     return true;
    176   }
    177 
    178   // Default, generate it as a register.
    179   AM.BaseType = MSP430ISelAddressMode::RegBase;
    180   AM.Base.Reg = N;
    181   return false;
    182 }
    183 
    184 bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
    185   DEBUG(errs() << "MatchAddress: "; AM.dump());
    186 
    187   switch (N.getOpcode()) {
    188   default: break;
    189   case ISD::Constant: {
    190     uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
    191     AM.Disp += Val;
    192     return false;
    193   }
    194 
    195   case MSP430ISD::Wrapper:
    196     if (!MatchWrapper(N, AM))
    197       return false;
    198     break;
    199 
    200   case ISD::FrameIndex:
    201     if (AM.BaseType == MSP430ISelAddressMode::RegBase
    202         && AM.Base.Reg.getNode() == 0) {
    203       AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
    204       AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
    205       return false;
    206     }
    207     break;
    208 
    209   case ISD::ADD: {
    210     MSP430ISelAddressMode Backup = AM;
    211     if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
    212         !MatchAddress(N.getNode()->getOperand(1), AM))
    213       return false;
    214     AM = Backup;
    215     if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
    216         !MatchAddress(N.getNode()->getOperand(0), AM))
    217       return false;
    218     AM = Backup;
    219 
    220     break;
    221   }
    222 
    223   case ISD::OR:
    224     // Handle "X | C" as "X + C" iff X is known to have C bits clear.
    225     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
    226       MSP430ISelAddressMode Backup = AM;
    227       uint64_t Offset = CN->getSExtValue();
    228       // Start with the LHS as an addr mode.
    229       if (!MatchAddress(N.getOperand(0), AM) &&
    230           // Address could not have picked a GV address for the displacement.
    231           AM.GV == NULL &&
    232           // Check to see if the LHS & C is zero.
    233           CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
    234         AM.Disp += Offset;
    235         return false;
    236       }
    237       AM = Backup;
    238     }
    239     break;
    240   }
    241 
    242   return MatchAddressBase(N, AM);
    243 }
    244 
    245 /// SelectAddr - returns true if it is able pattern match an addressing mode.
    246 /// It returns the operands which make up the maximal addressing mode it can
    247 /// match by reference.
    248 bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
    249                                     SDValue &Base, SDValue &Disp) {
    250   MSP430ISelAddressMode AM;
    251 
    252   if (MatchAddress(N, AM))
    253     return false;
    254 
    255   EVT VT = N.getValueType();
    256   if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
    257     if (!AM.Base.Reg.getNode())
    258       AM.Base.Reg = CurDAG->getRegister(0, VT);
    259   }
    260 
    261   Base  = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) ?
    262     CurDAG->getTargetFrameIndex(AM.Base.FrameIndex,
    263                                 getTargetLowering()->getPointerTy()) :
    264     AM.Base.Reg;
    265 
    266   if (AM.GV)
    267     Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
    268                                           MVT::i16, AM.Disp,
    269                                           0/*AM.SymbolFlags*/);
    270   else if (AM.CP)
    271     Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
    272                                          AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
    273   else if (AM.ES)
    274     Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
    275   else if (AM.JT != -1)
    276     Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
    277   else if (AM.BlockAddr)
    278     Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
    279                                          0/*AM.SymbolFlags*/);
    280   else
    281     Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i16);
    282 
    283   return true;
    284 }
    285 
    286 bool MSP430DAGToDAGISel::
    287 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
    288                              std::vector<SDValue> &OutOps) {
    289   SDValue Op0, Op1;
    290   switch (ConstraintCode) {
    291   default: return true;
    292   case 'm':   // memory
    293     if (!SelectAddr(Op, Op0, Op1))
    294       return true;
    295     break;
    296   }
    297 
    298   OutOps.push_back(Op0);
    299   OutOps.push_back(Op1);
    300   return false;
    301 }
    302 
    303 static bool isValidIndexedLoad(const LoadSDNode *LD) {
    304   ISD::MemIndexedMode AM = LD->getAddressingMode();
    305   if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
    306     return false;
    307 
    308   EVT VT = LD->getMemoryVT();
    309 
    310   switch (VT.getSimpleVT().SimpleTy) {
    311   case MVT::i8:
    312     // Sanity check
    313     if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
    314       return false;
    315 
    316     break;
    317   case MVT::i16:
    318     // Sanity check
    319     if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
    320       return false;
    321 
    322     break;
    323   default:
    324     return false;
    325   }
    326 
    327   return true;
    328 }
    329 
    330 SDNode *MSP430DAGToDAGISel::SelectIndexedLoad(SDNode *N) {
    331   LoadSDNode *LD = cast<LoadSDNode>(N);
    332   if (!isValidIndexedLoad(LD))
    333     return NULL;
    334 
    335   MVT VT = LD->getMemoryVT().getSimpleVT();
    336 
    337   unsigned Opcode = 0;
    338   switch (VT.SimpleTy) {
    339   case MVT::i8:
    340     Opcode = MSP430::MOV8rm_POST;
    341     break;
    342   case MVT::i16:
    343     Opcode = MSP430::MOV16rm_POST;
    344     break;
    345   default:
    346     return NULL;
    347   }
    348 
    349    return CurDAG->getMachineNode(Opcode, SDLoc(N),
    350                                  VT, MVT::i16, MVT::Other,
    351                                  LD->getBasePtr(), LD->getChain());
    352 }
    353 
    354 SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op,
    355                                                SDValue N1, SDValue N2,
    356                                                unsigned Opc8, unsigned Opc16) {
    357   if (N1.getOpcode() == ISD::LOAD &&
    358       N1.hasOneUse() &&
    359       IsLegalToFold(N1, Op, Op, OptLevel)) {
    360     LoadSDNode *LD = cast<LoadSDNode>(N1);
    361     if (!isValidIndexedLoad(LD))
    362       return NULL;
    363 
    364     MVT VT = LD->getMemoryVT().getSimpleVT();
    365     unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
    366     MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
    367     MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
    368     SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
    369     SDNode *ResNode =
    370       CurDAG->SelectNodeTo(Op, Opc,
    371                            VT, MVT::i16, MVT::Other,
    372                            Ops0, 3);
    373     cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
    374     // Transfer chain.
    375     ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
    376     // Transfer writeback.
    377     ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
    378     return ResNode;
    379   }
    380 
    381   return NULL;
    382 }
    383 
    384 
    385 SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) {
    386   SDLoc dl(Node);
    387 
    388   // Dump information about the Node being selected
    389   DEBUG(errs() << "Selecting: ");
    390   DEBUG(Node->dump(CurDAG));
    391   DEBUG(errs() << "\n");
    392 
    393   // If we have a custom node, we already have selected!
    394   if (Node->isMachineOpcode()) {
    395     DEBUG(errs() << "== ";
    396           Node->dump(CurDAG);
    397           errs() << "\n");
    398     return NULL;
    399   }
    400 
    401   // Few custom selection stuff.
    402   switch (Node->getOpcode()) {
    403   default: break;
    404   case ISD::FrameIndex: {
    405     assert(Node->getValueType(0) == MVT::i16);
    406     int FI = cast<FrameIndexSDNode>(Node)->getIndex();
    407     SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
    408     if (Node->hasOneUse())
    409       return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16,
    410                                   TFI, CurDAG->getTargetConstant(0, MVT::i16));
    411     return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16,
    412                                   TFI, CurDAG->getTargetConstant(0, MVT::i16));
    413   }
    414   case ISD::LOAD:
    415     if (SDNode *ResNode = SelectIndexedLoad(Node))
    416       return ResNode;
    417     // Other cases are autogenerated.
    418     break;
    419   case ISD::ADD:
    420     if (SDNode *ResNode =
    421         SelectIndexedBinOp(Node,
    422                            Node->getOperand(0), Node->getOperand(1),
    423                            MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
    424       return ResNode;
    425     else if (SDNode *ResNode =
    426              SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
    427                                 MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
    428       return ResNode;
    429 
    430     // Other cases are autogenerated.
    431     break;
    432   case ISD::SUB:
    433     if (SDNode *ResNode =
    434         SelectIndexedBinOp(Node,
    435                            Node->getOperand(0), Node->getOperand(1),
    436                            MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
    437       return ResNode;
    438 
    439     // Other cases are autogenerated.
    440     break;
    441   case ISD::AND:
    442     if (SDNode *ResNode =
    443         SelectIndexedBinOp(Node,
    444                            Node->getOperand(0), Node->getOperand(1),
    445                            MSP430::AND8rm_POST, MSP430::AND16rm_POST))
    446       return ResNode;
    447     else if (SDNode *ResNode =
    448              SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
    449                                 MSP430::AND8rm_POST, MSP430::AND16rm_POST))
    450       return ResNode;
    451 
    452     // Other cases are autogenerated.
    453     break;
    454   case ISD::OR:
    455     if (SDNode *ResNode =
    456         SelectIndexedBinOp(Node,
    457                            Node->getOperand(0), Node->getOperand(1),
    458                            MSP430::OR8rm_POST, MSP430::OR16rm_POST))
    459       return ResNode;
    460     else if (SDNode *ResNode =
    461              SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
    462                                 MSP430::OR8rm_POST, MSP430::OR16rm_POST))
    463       return ResNode;
    464 
    465     // Other cases are autogenerated.
    466     break;
    467   case ISD::XOR:
    468     if (SDNode *ResNode =
    469         SelectIndexedBinOp(Node,
    470                            Node->getOperand(0), Node->getOperand(1),
    471                            MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
    472       return ResNode;
    473     else if (SDNode *ResNode =
    474              SelectIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
    475                                 MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
    476       return ResNode;
    477 
    478     // Other cases are autogenerated.
    479     break;
    480   }
    481 
    482   // Select the default instruction
    483   SDNode *ResNode = SelectCode(Node);
    484 
    485   DEBUG(errs() << "=> ");
    486   if (ResNode == NULL || ResNode == Node)
    487     DEBUG(Node->dump(CurDAG));
    488   else
    489     DEBUG(ResNode->dump(CurDAG));
    490   DEBUG(errs() << "\n");
    491 
    492   return ResNode;
    493 }
    494