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