1*0fca6ea1SDimitry Andric //===- XtensaISelDAGToDAG.cpp - A dag to dag inst selector for Xtensa -----===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file defines an instruction selector for the Xtensa target. 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "Xtensa.h" 14*0fca6ea1SDimitry Andric #include "XtensaTargetMachine.h" 15*0fca6ea1SDimitry Andric #include "XtensaUtils.h" 16*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h" 19*0fca6ea1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 20*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 21*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 22*0fca6ea1SDimitry Andric 23*0fca6ea1SDimitry Andric using namespace llvm; 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric #define DEBUG_TYPE "xtensa-isel" 26*0fca6ea1SDimitry Andric 27*0fca6ea1SDimitry Andric namespace { 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric class XtensaDAGToDAGISel : public SelectionDAGISel { 30*0fca6ea1SDimitry Andric public: 31*0fca6ea1SDimitry Andric XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel) 32*0fca6ea1SDimitry Andric : SelectionDAGISel(TM, OptLevel) {} 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric void Select(SDNode *Node) override; 35*0fca6ea1SDimitry Andric 36*0fca6ea1SDimitry Andric // For load/store instructions generate (base+offset) pair from 37*0fca6ea1SDimitry Andric // memory address. The offset must be a multiple of scale argument. 38*0fca6ea1SDimitry Andric bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset, 39*0fca6ea1SDimitry Andric int Scale) { 40*0fca6ea1SDimitry Andric EVT ValTy = Addr.getValueType(); 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric // if Address is FI, get the TargetFrameIndex. 43*0fca6ea1SDimitry Andric if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 44*0fca6ea1SDimitry Andric Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 45*0fca6ea1SDimitry Andric Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric return true; 48*0fca6ea1SDimitry Andric } 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric if (TM.isPositionIndependent()) { 51*0fca6ea1SDimitry Andric DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(), 52*0fca6ea1SDimitry Andric "PIC relocations are not supported ", 53*0fca6ea1SDimitry Andric Addr.getDebugLoc()); 54*0fca6ea1SDimitry Andric CurDAG->getContext()->diagnose(Diag); 55*0fca6ea1SDimitry Andric } 56*0fca6ea1SDimitry Andric 57*0fca6ea1SDimitry Andric if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 58*0fca6ea1SDimitry Andric Addr.getOpcode() == ISD::TargetGlobalAddress)) 59*0fca6ea1SDimitry Andric return false; 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric // Addresses of the form FI+const 62*0fca6ea1SDimitry Andric bool Valid = false; 63*0fca6ea1SDimitry Andric if (CurDAG->isBaseWithConstantOffset(Addr)) { 64*0fca6ea1SDimitry Andric ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); 65*0fca6ea1SDimitry Andric int64_t OffsetVal = CN->getSExtValue(); 66*0fca6ea1SDimitry Andric 67*0fca6ea1SDimitry Andric Valid = isValidAddrOffset(Scale, OffsetVal); 68*0fca6ea1SDimitry Andric 69*0fca6ea1SDimitry Andric if (Valid) { 70*0fca6ea1SDimitry Andric // If the first operand is a FI, get the TargetFI Node 71*0fca6ea1SDimitry Andric if (FrameIndexSDNode *FIN = 72*0fca6ea1SDimitry Andric dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 73*0fca6ea1SDimitry Andric Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 74*0fca6ea1SDimitry Andric else 75*0fca6ea1SDimitry Andric Base = Addr.getOperand(0); 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric Offset = 78*0fca6ea1SDimitry Andric CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy); 79*0fca6ea1SDimitry Andric return true; 80*0fca6ea1SDimitry Andric } 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric // Last case 84*0fca6ea1SDimitry Andric Base = Addr; 85*0fca6ea1SDimitry Andric Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); 86*0fca6ea1SDimitry Andric return true; 87*0fca6ea1SDimitry Andric } 88*0fca6ea1SDimitry Andric 89*0fca6ea1SDimitry Andric bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) { 90*0fca6ea1SDimitry Andric return selectMemRegAddr(Addr, Base, Offset, 1); 91*0fca6ea1SDimitry Andric } 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) { 94*0fca6ea1SDimitry Andric return selectMemRegAddr(Addr, Base, Offset, 2); 95*0fca6ea1SDimitry Andric } 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andric bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) { 98*0fca6ea1SDimitry Andric return selectMemRegAddr(Addr, Base, Offset, 4); 99*0fca6ea1SDimitry Andric } 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric // Include the pieces autogenerated from the target description. 102*0fca6ea1SDimitry Andric #include "XtensaGenDAGISel.inc" 103*0fca6ea1SDimitry Andric }; // namespace 104*0fca6ea1SDimitry Andric 105*0fca6ea1SDimitry Andric class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy { 106*0fca6ea1SDimitry Andric public: 107*0fca6ea1SDimitry Andric static char ID; 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel) 110*0fca6ea1SDimitry Andric : SelectionDAGISelLegacy( 111*0fca6ea1SDimitry Andric ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {} 112*0fca6ea1SDimitry Andric 113*0fca6ea1SDimitry Andric StringRef getPassName() const override { 114*0fca6ea1SDimitry Andric return "Xtensa DAG->DAG Pattern Instruction Selection"; 115*0fca6ea1SDimitry Andric } 116*0fca6ea1SDimitry Andric }; 117*0fca6ea1SDimitry Andric } // end anonymous namespace 118*0fca6ea1SDimitry Andric 119*0fca6ea1SDimitry Andric char XtensaDAGToDAGISelLegacy::ID = 0; 120*0fca6ea1SDimitry Andric 121*0fca6ea1SDimitry Andric FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM, 122*0fca6ea1SDimitry Andric CodeGenOptLevel OptLevel) { 123*0fca6ea1SDimitry Andric return new XtensaDAGToDAGISelLegacy(TM, OptLevel); 124*0fca6ea1SDimitry Andric } 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric void XtensaDAGToDAGISel::Select(SDNode *Node) { 127*0fca6ea1SDimitry Andric SDLoc DL(Node); 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric // If we have a custom node, we already have selected! 130*0fca6ea1SDimitry Andric if (Node->isMachineOpcode()) { 131*0fca6ea1SDimitry Andric Node->setNodeId(-1); 132*0fca6ea1SDimitry Andric return; 133*0fca6ea1SDimitry Andric } 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric SelectCode(Node); 136*0fca6ea1SDimitry Andric } 137