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