brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · 655b40f Raw
245 lines · cpp
1//===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===//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 Xtensa target.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/XtensaMCTargetDesc.h"14#include "Xtensa.h"15#include "XtensaSelectionDAGInfo.h"16#include "XtensaTargetMachine.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19#include "llvm/CodeGen/SelectionDAGISel.h"20#include "llvm/IR/DiagnosticInfo.h"21#include "llvm/Support/Debug.h"22#include "llvm/Support/raw_ostream.h"23 24using namespace llvm;25 26#define DEBUG_TYPE "xtensa-isel"27 28namespace {29 30class XtensaDAGToDAGISel : public SelectionDAGISel {31  const XtensaSubtarget *Subtarget = nullptr;32 33public:34  explicit XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)35      : SelectionDAGISel(TM, OptLevel) {}36 37  bool runOnMachineFunction(MachineFunction &MF) override {38    Subtarget = &MF.getSubtarget<XtensaSubtarget>();39    return SelectionDAGISel::runOnMachineFunction(MF);40  }41 42  void Select(SDNode *Node) override;43 44  bool SelectInlineAsmMemoryOperand(const SDValue &Op,45                                    InlineAsm::ConstraintCode ConstraintID,46                                    std::vector<SDValue> &OutOps) override;47 48  // For load/store instructions generate (base+offset) pair from49  // memory address. The offset must be a multiple of scale argument.50  bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,51                        int Scale) {52    EVT ValTy = Addr.getValueType();53 54    // if Address is FI, get the TargetFrameIndex.55    if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {56      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);57      Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy);58 59      return true;60    }61 62    if (TM.isPositionIndependent()) {63      CurDAG->getContext()->diagnose(DiagnosticInfoUnsupported(64          CurDAG->getMachineFunction().getFunction(),65          "PIC relocations are not supported", Addr.getDebugLoc()));66    }67 68    if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||69         Addr.getOpcode() == ISD::TargetGlobalAddress))70      return false;71 72    // Addresses of the form FI+const73    bool Valid = false;74    if (CurDAG->isBaseWithConstantOffset(Addr)) {75      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));76      int64_t OffsetVal = CN->getSExtValue();77 78      Valid = Xtensa::isValidAddrOffset(Scale, OffsetVal);79 80      if (Valid) {81        // If the first operand is a FI, get the TargetFI Node.82        if (FrameIndexSDNode *FIN =83                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))84          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);85        else86          Base = Addr.getOperand(0);87 88        Offset =89            CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);90        return true;91      }92    }93 94    // Last case95    Base = Addr;96    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());97    return true;98  }99 100  bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {101    return selectMemRegAddr(Addr, Base, Offset, 1);102  }103 104  bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {105    return selectMemRegAddr(Addr, Base, Offset, 2);106  }107 108  bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {109    return selectMemRegAddr(Addr, Base, Offset, 4);110  }111 112// Include the pieces autogenerated from the target description.113#include "XtensaGenDAGISel.inc"114}; // namespace115 116class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy {117public:118  static char ID;119 120  XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)121      : SelectionDAGISelLegacy(122            ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {}123 124  StringRef getPassName() const override {125    return "Xtensa DAG->DAG Pattern Instruction Selection";126  }127};128} // end anonymous namespace129 130char XtensaDAGToDAGISelLegacy::ID = 0;131 132FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,133                                        CodeGenOptLevel OptLevel) {134  return new XtensaDAGToDAGISelLegacy(TM, OptLevel);135}136 137void XtensaDAGToDAGISel::Select(SDNode *Node) {138  SDLoc DL(Node);139  EVT VT = Node->getValueType(0);140 141  // If we have a custom node, we already have selected!142  if (Node->isMachineOpcode()) {143    Node->setNodeId(-1);144    return;145  }146 147  switch (Node->getOpcode()) {148  case ISD::SHL: {149    SDValue N0 = Node->getOperand(0);150    SDValue N1 = Node->getOperand(1);151    auto *C = dyn_cast<ConstantSDNode>(N1);152    // If C is constant in range [1..31] then we can generate SLLI153    // instruction using pattern matching, otherwise generate SLL.154    if (!C || C->isZero()) {155      SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N1);156      SDNode *SLL =157          CurDAG->getMachineNode(Xtensa::SLL, DL, VT, N0, SDValue(SSL, 0));158      ReplaceNode(Node, SLL);159      return;160    }161    break;162  }163  case ISD::SRL: {164    SDValue N0 = Node->getOperand(0);165    SDValue N1 = Node->getOperand(1);166    auto *C = dyn_cast<ConstantSDNode>(N1);167 168    // If C is constant then we can generate SRLI169    // instruction using pattern matching or EXTUI, otherwise generate SRL.170    if (C) {171      if (isUInt<4>(C->getZExtValue()))172        break;173      unsigned ShAmt = C->getZExtValue();174      SDNode *EXTUI = CurDAG->getMachineNode(175          Xtensa::EXTUI, DL, VT, N0, CurDAG->getTargetConstant(ShAmt, DL, VT),176          CurDAG->getTargetConstant(32 - ShAmt, DL, VT));177      ReplaceNode(Node, EXTUI);178      return;179    }180 181    SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);182    SDNode *SRL =183        CurDAG->getMachineNode(Xtensa::SRL, DL, VT, N0, SDValue(SSR, 0));184    ReplaceNode(Node, SRL);185    return;186  }187  case ISD::SRA: {188    SDValue N0 = Node->getOperand(0);189    SDValue N1 = Node->getOperand(1);190    auto *C = dyn_cast<ConstantSDNode>(N1);191    // If C is constant then we can generate SRAI192    // instruction using pattern matching, otherwise generate SRA.193    if (!C) {194      SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);195      SDNode *SRA =196          CurDAG->getMachineNode(Xtensa::SRA, DL, VT, N0, SDValue(SSR, 0));197      ReplaceNode(Node, SRA);198      return;199    }200    break;201  }202  case XtensaISD::SRCL: {203    SDValue N0 = Node->getOperand(0);204    SDValue N1 = Node->getOperand(1);205    SDValue N2 = Node->getOperand(2);206    SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N2);207    SDNode *SRC =208        CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSL, 0));209    ReplaceNode(Node, SRC);210    return;211  }212  case XtensaISD::SRCR: {213    SDValue N0 = Node->getOperand(0);214    SDValue N1 = Node->getOperand(1);215    SDValue N2 = Node->getOperand(2);216    SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N2);217    SDNode *SRC =218        CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSR, 0));219    ReplaceNode(Node, SRC);220    return;221  }222  }223 224  SelectCode(Node);225}226 227bool XtensaDAGToDAGISel::SelectInlineAsmMemoryOperand(228    const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,229    std::vector<SDValue> &OutOps) {230  switch (ConstraintID) {231  default:232    llvm_unreachable("Unexpected asm memory constraint");233  case InlineAsm::ConstraintCode::m: {234    SDValue Base, Offset;235 236    selectMemRegAddr(Op, Base, Offset, 4);237    OutOps.push_back(Base);238    OutOps.push_back(Offset);239 240    return false;241  }242  }243  return false;244}245