Add gfx950 mfma instructions to ROCDL dialect (#123361)
[llvm-project.git] / llvm / lib / Target / Xtensa / XtensaISelDAGToDAG.cpp
blobef14095d18efbfc57c416d1fce762ea9569f31c7
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.
11 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm;
25 #define DEBUG_TYPE "xtensa-isel"
27 namespace {
29 class XtensaDAGToDAGISel : public SelectionDAGISel {
30 const XtensaSubtarget *Subtarget = nullptr;
32 public:
33 explicit XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
34 : SelectionDAGISel(TM, OptLevel) {}
36 bool runOnMachineFunction(MachineFunction &MF) override {
37 Subtarget = &MF.getSubtarget<XtensaSubtarget>();
38 return SelectionDAGISel::runOnMachineFunction(MF);
41 void Select(SDNode *Node) override;
43 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
44 InlineAsm::ConstraintCode ConstraintID,
45 std::vector<SDValue> &OutOps) override;
47 // For load/store instructions generate (base+offset) pair from
48 // memory address. The offset must be a multiple of scale argument.
49 bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
50 int Scale) {
51 EVT ValTy = Addr.getValueType();
53 // if Address is FI, get the TargetFrameIndex.
54 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
55 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
56 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy);
58 return true;
61 if (TM.isPositionIndependent()) {
62 DiagnosticInfoUnsupported Diag(CurDAG->getMachineFunction().getFunction(),
63 "PIC relocations are not supported ",
64 Addr.getDebugLoc());
65 CurDAG->getContext()->diagnose(Diag);
68 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
69 Addr.getOpcode() == ISD::TargetGlobalAddress))
70 return false;
72 // Addresses of the form FI+const
73 bool Valid = false;
74 if (CurDAG->isBaseWithConstantOffset(Addr)) {
75 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
76 int64_t OffsetVal = CN->getSExtValue();
78 Valid = isValidAddrOffset(Scale, OffsetVal);
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 else
86 Base = Addr.getOperand(0);
88 Offset =
89 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);
90 return true;
94 // Last case
95 Base = Addr;
96 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());
97 return true;
100 bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {
101 return selectMemRegAddr(Addr, Base, Offset, 1);
104 bool selectMemRegAddrISH2(SDValue Addr, SDValue &Base, SDValue &Offset) {
105 return selectMemRegAddr(Addr, Base, Offset, 2);
108 bool selectMemRegAddrISH4(SDValue Addr, SDValue &Base, SDValue &Offset) {
109 return selectMemRegAddr(Addr, Base, Offset, 4);
112 // Include the pieces autogenerated from the target description.
113 #include "XtensaGenDAGISel.inc"
114 }; // namespace
116 class XtensaDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
117 public:
118 static char ID;
120 XtensaDAGToDAGISelLegacy(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
121 : SelectionDAGISelLegacy(
122 ID, std::make_unique<XtensaDAGToDAGISel>(TM, OptLevel)) {}
124 StringRef getPassName() const override {
125 return "Xtensa DAG->DAG Pattern Instruction Selection";
128 } // end anonymous namespace
130 char XtensaDAGToDAGISelLegacy::ID = 0;
132 FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
133 CodeGenOptLevel OptLevel) {
134 return new XtensaDAGToDAGISelLegacy(TM, OptLevel);
137 void XtensaDAGToDAGISel::Select(SDNode *Node) {
138 SDLoc DL(Node);
139 EVT VT = Node->getValueType(0);
141 // If we have a custom node, we already have selected!
142 if (Node->isMachineOpcode()) {
143 Node->setNodeId(-1);
144 return;
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 SLLI
153 // 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;
161 break;
163 case ISD::SRL: {
164 SDValue N0 = Node->getOperand(0);
165 SDValue N1 = Node->getOperand(1);
166 auto *C = dyn_cast<ConstantSDNode>(N1);
168 // If C is constant then we can generate SRLI
169 // 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;
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;
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 SRAI
192 // 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;
200 break;
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;
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;
224 SelectCode(Node);
227 bool 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;
236 selectMemRegAddr(Op, Base, Offset, 4);
237 OutOps.push_back(Base);
238 OutOps.push_back(Offset);
240 return false;
243 return false;