brintos

brintos / llvm-project-archived public Read only

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