xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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