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