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