xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp (revision d409305fa3838fb39b38c26fc085fb729b8766d5)
10b57cec5SDimitry Andric //===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines an instruction selector for the RISCV target.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
135ffd83dbSDimitry Andric #include "RISCVISelDAGToDAG.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h"
15e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVMatInt.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
17e8d8bef9SDimitry Andric #include "llvm/IR/IntrinsicsRISCV.h"
185ffd83dbSDimitry Andric #include "llvm/Support/Alignment.h"
190b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
200b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
225ffd83dbSDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define DEBUG_TYPE "riscv-isel"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric void RISCVDAGToDAGISel::PostprocessISelDAG() {
280b57cec5SDimitry Andric   doPeepholeLoadStoreADDI();
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm,
320b57cec5SDimitry Andric                          MVT XLenVT) {
330b57cec5SDimitry Andric   RISCVMatInt::InstSeq Seq;
340b57cec5SDimitry Andric   RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64, Seq);
350b57cec5SDimitry Andric 
368bcb0991SDimitry Andric   SDNode *Result = nullptr;
370b57cec5SDimitry Andric   SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT);
380b57cec5SDimitry Andric   for (RISCVMatInt::Inst &Inst : Seq) {
390b57cec5SDimitry Andric     SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT);
400b57cec5SDimitry Andric     if (Inst.Opc == RISCV::LUI)
410b57cec5SDimitry Andric       Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm);
420b57cec5SDimitry Andric     else
430b57cec5SDimitry Andric       Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm);
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric     // Only the first instruction has X0 as its source.
460b57cec5SDimitry Andric     SrcReg = SDValue(Result, 0);
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   return Result;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
52e8d8bef9SDimitry Andric static RISCVVLMUL getLMUL(EVT VT) {
53e8d8bef9SDimitry Andric   switch (VT.getSizeInBits().getKnownMinValue() / 8) {
54e8d8bef9SDimitry Andric   default:
55e8d8bef9SDimitry Andric     llvm_unreachable("Invalid LMUL.");
56e8d8bef9SDimitry Andric   case 1:
57e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_F8;
58e8d8bef9SDimitry Andric   case 2:
59e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_F4;
60e8d8bef9SDimitry Andric   case 4:
61e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_F2;
62e8d8bef9SDimitry Andric   case 8:
63e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_1;
64e8d8bef9SDimitry Andric   case 16:
65e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_2;
66e8d8bef9SDimitry Andric   case 32:
67e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_4;
68e8d8bef9SDimitry Andric   case 64:
69e8d8bef9SDimitry Andric     return RISCVVLMUL::LMUL_8;
700b57cec5SDimitry Andric   }
71e8d8bef9SDimitry Andric }
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric static unsigned getSubregIndexByEVT(EVT VT, unsigned Index) {
74e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
75e8d8bef9SDimitry Andric   if (LMUL == RISCVVLMUL::LMUL_F8 || LMUL == RISCVVLMUL::LMUL_F4 ||
76e8d8bef9SDimitry Andric       LMUL == RISCVVLMUL::LMUL_F2 || LMUL == RISCVVLMUL::LMUL_1) {
77e8d8bef9SDimitry Andric     static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
78e8d8bef9SDimitry Andric                   "Unexpected subreg numbering");
79e8d8bef9SDimitry Andric     return RISCV::sub_vrm1_0 + Index;
80e8d8bef9SDimitry Andric   } else if (LMUL == RISCVVLMUL::LMUL_2) {
81e8d8bef9SDimitry Andric     static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
82e8d8bef9SDimitry Andric                   "Unexpected subreg numbering");
83e8d8bef9SDimitry Andric     return RISCV::sub_vrm2_0 + Index;
84e8d8bef9SDimitry Andric   } else if (LMUL == RISCVVLMUL::LMUL_4) {
85e8d8bef9SDimitry Andric     static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
86e8d8bef9SDimitry Andric                   "Unexpected subreg numbering");
87e8d8bef9SDimitry Andric     return RISCV::sub_vrm4_0 + Index;
88e8d8bef9SDimitry Andric   }
89e8d8bef9SDimitry Andric   llvm_unreachable("Invalid vector type.");
90e8d8bef9SDimitry Andric }
91e8d8bef9SDimitry Andric 
92e8d8bef9SDimitry Andric static SDValue createTupleImpl(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs,
93e8d8bef9SDimitry Andric                                unsigned RegClassID, unsigned SubReg0) {
94e8d8bef9SDimitry Andric   assert(Regs.size() >= 2 && Regs.size() <= 8);
95e8d8bef9SDimitry Andric 
96e8d8bef9SDimitry Andric   SDLoc DL(Regs[0]);
97e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Ops;
98e8d8bef9SDimitry Andric 
99e8d8bef9SDimitry Andric   Ops.push_back(CurDAG.getTargetConstant(RegClassID, DL, MVT::i32));
100e8d8bef9SDimitry Andric 
101e8d8bef9SDimitry Andric   for (unsigned I = 0; I < Regs.size(); ++I) {
102e8d8bef9SDimitry Andric     Ops.push_back(Regs[I]);
103e8d8bef9SDimitry Andric     Ops.push_back(CurDAG.getTargetConstant(SubReg0 + I, DL, MVT::i32));
104e8d8bef9SDimitry Andric   }
105e8d8bef9SDimitry Andric   SDNode *N =
106e8d8bef9SDimitry Andric       CurDAG.getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops);
107e8d8bef9SDimitry Andric   return SDValue(N, 0);
108e8d8bef9SDimitry Andric }
109e8d8bef9SDimitry Andric 
110e8d8bef9SDimitry Andric static SDValue createM1Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs,
111e8d8bef9SDimitry Andric                              unsigned NF) {
112e8d8bef9SDimitry Andric   static const unsigned RegClassIDs[] = {
113e8d8bef9SDimitry Andric       RISCV::VRN2M1RegClassID, RISCV::VRN3M1RegClassID, RISCV::VRN4M1RegClassID,
114e8d8bef9SDimitry Andric       RISCV::VRN5M1RegClassID, RISCV::VRN6M1RegClassID, RISCV::VRN7M1RegClassID,
115e8d8bef9SDimitry Andric       RISCV::VRN8M1RegClassID};
116e8d8bef9SDimitry Andric 
117e8d8bef9SDimitry Andric   return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm1_0);
118e8d8bef9SDimitry Andric }
119e8d8bef9SDimitry Andric 
120e8d8bef9SDimitry Andric static SDValue createM2Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs,
121e8d8bef9SDimitry Andric                              unsigned NF) {
122e8d8bef9SDimitry Andric   static const unsigned RegClassIDs[] = {RISCV::VRN2M2RegClassID,
123e8d8bef9SDimitry Andric                                          RISCV::VRN3M2RegClassID,
124e8d8bef9SDimitry Andric                                          RISCV::VRN4M2RegClassID};
125e8d8bef9SDimitry Andric 
126e8d8bef9SDimitry Andric   return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm2_0);
127e8d8bef9SDimitry Andric }
128e8d8bef9SDimitry Andric 
129e8d8bef9SDimitry Andric static SDValue createM4Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs,
130e8d8bef9SDimitry Andric                              unsigned NF) {
131e8d8bef9SDimitry Andric   return createTupleImpl(CurDAG, Regs, RISCV::VRN2M4RegClassID,
132e8d8bef9SDimitry Andric                          RISCV::sub_vrm4_0);
133e8d8bef9SDimitry Andric }
134e8d8bef9SDimitry Andric 
135e8d8bef9SDimitry Andric static SDValue createTuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs,
136e8d8bef9SDimitry Andric                            unsigned NF, RISCVVLMUL LMUL) {
137e8d8bef9SDimitry Andric   switch (LMUL) {
138e8d8bef9SDimitry Andric   default:
139e8d8bef9SDimitry Andric     llvm_unreachable("Invalid LMUL.");
140e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_F8:
141e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_F4:
142e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_F2:
143e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_1:
144e8d8bef9SDimitry Andric     return createM1Tuple(CurDAG, Regs, NF);
145e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_2:
146e8d8bef9SDimitry Andric     return createM2Tuple(CurDAG, Regs, NF);
147e8d8bef9SDimitry Andric   case RISCVVLMUL::LMUL_4:
148e8d8bef9SDimitry Andric     return createM4Tuple(CurDAG, Regs, NF);
149e8d8bef9SDimitry Andric   }
150e8d8bef9SDimitry Andric }
151e8d8bef9SDimitry Andric 
152e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLSEG(SDNode *Node, unsigned IntNo,
153e8d8bef9SDimitry Andric                                     bool IsStrided) {
154e8d8bef9SDimitry Andric   SDLoc DL(Node);
155e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 1;
156e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
157e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
158e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
159e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
160e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
161e8d8bef9SDimitry Andric   SmallVector<SDValue, 5> Operands;
162e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(2)); // Base pointer.
163e8d8bef9SDimitry Andric   if (IsStrided) {
164e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3)); // Stride.
165e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(4)); // VL.
166e8d8bef9SDimitry Andric   } else {
167e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3)); // VL.
168e8d8bef9SDimitry Andric   }
169e8d8bef9SDimitry Andric   Operands.push_back(SEW);
170e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); // Chain.
171e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
172e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
173e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
174e8d8bef9SDimitry Andric   SDNode *Load =
175e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
176e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
177e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
178e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
179e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
180e8d8bef9SDimitry Andric                                                VT, SuperReg));
181e8d8bef9SDimitry Andric 
182e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));
183e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
184e8d8bef9SDimitry Andric }
185e8d8bef9SDimitry Andric 
186e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLSEGMask(SDNode *Node, unsigned IntNo,
187e8d8bef9SDimitry Andric                                         bool IsStrided) {
188e8d8bef9SDimitry Andric   SDLoc DL(Node);
189e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 1;
190e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
191e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
192e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
193e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
194e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
195e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
196e8d8bef9SDimitry Andric   SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL);
197e8d8bef9SDimitry Andric   SmallVector<SDValue, 7> Operands;
198e8d8bef9SDimitry Andric   Operands.push_back(MaskedOff);
199e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(NF + 2)); // Base pointer.
200e8d8bef9SDimitry Andric   if (IsStrided) {
201e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(NF + 3)); // Stride.
202e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(NF + 4)); // Mask.
203e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(NF + 5)); // VL.
204e8d8bef9SDimitry Andric   } else {
205e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(NF + 3)); // Mask.
206e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(NF + 4)); // VL.
207e8d8bef9SDimitry Andric   }
208e8d8bef9SDimitry Andric   Operands.push_back(SEW);
209e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); /// Chain.
210e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
211e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
212e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
213e8d8bef9SDimitry Andric   SDNode *Load =
214e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
215e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
216e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
217e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
218e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
219e8d8bef9SDimitry Andric                                                VT, SuperReg));
220e8d8bef9SDimitry Andric 
221e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));
222e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
223e8d8bef9SDimitry Andric }
224e8d8bef9SDimitry Andric 
225e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLSEGFF(SDNode *Node) {
226e8d8bef9SDimitry Andric   SDLoc DL(Node);
227e8d8bef9SDimitry Andric   unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
228e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 2; // Do not count Chain and Glue.
229e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
230e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
231e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
232e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
233e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
234e8d8bef9SDimitry Andric   SmallVector<SDValue, 5> Operands;
235e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(2)); // Base pointer.
236e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(3)); // VL.
237e8d8bef9SDimitry Andric   Operands.push_back(SEW);
238e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); // Chain.
239e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
240e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
241e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
242e8d8bef9SDimitry Andric   SDNode *Load = CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other,
243e8d8bef9SDimitry Andric                                         MVT::Glue, Operands);
244e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
245e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
246e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
247e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
248e8d8bef9SDimitry Andric                                                VT, SuperReg));
249e8d8bef9SDimitry Andric 
250e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));     // Chain.
251e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF + 1), SDValue(Load, 2)); // Glue.
252e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
253e8d8bef9SDimitry Andric }
254e8d8bef9SDimitry Andric 
255e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLSEGFFMask(SDNode *Node) {
256e8d8bef9SDimitry Andric   SDLoc DL(Node);
257e8d8bef9SDimitry Andric   unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
258e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 2; // Do not count Chain and Glue.
259e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
260e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
261e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
262e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
263e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
264e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
265e8d8bef9SDimitry Andric   SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL);
266e8d8bef9SDimitry Andric   SmallVector<SDValue, 7> Operands;
267e8d8bef9SDimitry Andric   Operands.push_back(MaskedOff);
268e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(NF + 2)); // Base pointer.
269e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(NF + 3)); // Mask.
270e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(NF + 4)); // VL.
271e8d8bef9SDimitry Andric   Operands.push_back(SEW);
272e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); /// Chain.
273e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
274e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
275e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
276e8d8bef9SDimitry Andric   SDNode *Load = CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other,
277e8d8bef9SDimitry Andric                                         MVT::Glue, Operands);
278e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
279e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
280e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
281e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
282e8d8bef9SDimitry Andric                                                VT, SuperReg));
283e8d8bef9SDimitry Andric 
284e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));     // Chain.
285e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF + 1), SDValue(Load, 2)); // Glue.
286e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
287e8d8bef9SDimitry Andric }
288e8d8bef9SDimitry Andric 
289e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLXSEG(SDNode *Node, unsigned IntNo) {
290e8d8bef9SDimitry Andric   SDLoc DL(Node);
291e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 1;
292e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
293e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
294e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
295e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
296e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
297e8d8bef9SDimitry Andric   SDValue Operands[] = {
298e8d8bef9SDimitry Andric       Node->getOperand(2),     // Base pointer.
299e8d8bef9SDimitry Andric       Node->getOperand(3),     // Index.
300e8d8bef9SDimitry Andric       Node->getOperand(4),     // VL.
301e8d8bef9SDimitry Andric       SEW, Node->getOperand(0) // Chain.
302e8d8bef9SDimitry Andric   };
303e8d8bef9SDimitry Andric 
304e8d8bef9SDimitry Andric   EVT IndexVT = Node->getOperand(3)->getValueType(0);
305e8d8bef9SDimitry Andric   RISCVVLMUL IndexLMUL = getLMUL(IndexVT);
306e8d8bef9SDimitry Andric   unsigned IndexScalarSize = IndexVT.getScalarSizeInBits();
307e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
308e8d8bef9SDimitry Andric       IntNo, IndexScalarSize, static_cast<unsigned>(LMUL),
309e8d8bef9SDimitry Andric       static_cast<unsigned>(IndexLMUL));
310e8d8bef9SDimitry Andric   SDNode *Load =
311e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
312e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
313e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
314e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
315e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
316e8d8bef9SDimitry Andric                                                VT, SuperReg));
317e8d8bef9SDimitry Andric 
318e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));
319e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
320e8d8bef9SDimitry Andric }
321e8d8bef9SDimitry Andric 
322e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVLXSEGMask(SDNode *Node, unsigned IntNo) {
323e8d8bef9SDimitry Andric   SDLoc DL(Node);
324e8d8bef9SDimitry Andric   unsigned NF = Node->getNumValues() - 1;
325e8d8bef9SDimitry Andric   EVT VT = Node->getValueType(0);
326e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
327e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
328e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
329e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
330e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
331e8d8bef9SDimitry Andric   SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL);
332e8d8bef9SDimitry Andric   SDValue Operands[] = {
333e8d8bef9SDimitry Andric       MaskedOff,
334e8d8bef9SDimitry Andric       Node->getOperand(NF + 2), // Base pointer.
335e8d8bef9SDimitry Andric       Node->getOperand(NF + 3), // Index.
336e8d8bef9SDimitry Andric       Node->getOperand(NF + 4), // Mask.
337e8d8bef9SDimitry Andric       Node->getOperand(NF + 5), // VL.
338e8d8bef9SDimitry Andric       SEW,
339e8d8bef9SDimitry Andric       Node->getOperand(0) // Chain.
340e8d8bef9SDimitry Andric   };
341e8d8bef9SDimitry Andric 
342e8d8bef9SDimitry Andric   EVT IndexVT = Node->getOperand(NF + 3)->getValueType(0);
343e8d8bef9SDimitry Andric   RISCVVLMUL IndexLMUL = getLMUL(IndexVT);
344e8d8bef9SDimitry Andric   unsigned IndexScalarSize = IndexVT.getScalarSizeInBits();
345e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
346e8d8bef9SDimitry Andric       IntNo, IndexScalarSize, static_cast<unsigned>(LMUL),
347e8d8bef9SDimitry Andric       static_cast<unsigned>(IndexLMUL));
348e8d8bef9SDimitry Andric   SDNode *Load =
349e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
350e8d8bef9SDimitry Andric   SDValue SuperReg = SDValue(Load, 0);
351e8d8bef9SDimitry Andric   for (unsigned I = 0; I < NF; ++I)
352e8d8bef9SDimitry Andric     ReplaceUses(SDValue(Node, I),
353e8d8bef9SDimitry Andric                 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL,
354e8d8bef9SDimitry Andric                                                VT, SuperReg));
355e8d8bef9SDimitry Andric 
356e8d8bef9SDimitry Andric   ReplaceUses(SDValue(Node, NF), SDValue(Load, 1));
357e8d8bef9SDimitry Andric   CurDAG->RemoveDeadNode(Node);
358e8d8bef9SDimitry Andric }
359e8d8bef9SDimitry Andric 
360e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVSSEG(SDNode *Node, unsigned IntNo,
361e8d8bef9SDimitry Andric                                     bool IsStrided) {
362e8d8bef9SDimitry Andric   SDLoc DL(Node);
363e8d8bef9SDimitry Andric   unsigned NF = Node->getNumOperands() - 4;
364e8d8bef9SDimitry Andric   if (IsStrided)
365e8d8bef9SDimitry Andric     NF--;
366e8d8bef9SDimitry Andric   EVT VT = Node->getOperand(2)->getValueType(0);
367e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
368e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
369e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
370e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
371e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
372e8d8bef9SDimitry Andric   SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL);
373e8d8bef9SDimitry Andric   SmallVector<SDValue, 6> Operands;
374e8d8bef9SDimitry Andric   Operands.push_back(StoreVal);
375e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(2 + NF)); // Base pointer.
376e8d8bef9SDimitry Andric   if (IsStrided) {
377e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3 + NF)); // Stride.
378e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(4 + NF)); // VL.
379e8d8bef9SDimitry Andric   } else {
380e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3 + NF)); // VL.
381e8d8bef9SDimitry Andric   }
382e8d8bef9SDimitry Andric   Operands.push_back(SEW);
383e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); // Chain.
384e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
385e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
386e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
387e8d8bef9SDimitry Andric   SDNode *Store =
388e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
389e8d8bef9SDimitry Andric   ReplaceNode(Node, Store);
390e8d8bef9SDimitry Andric }
391e8d8bef9SDimitry Andric 
392e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVSSEGMask(SDNode *Node, unsigned IntNo,
393e8d8bef9SDimitry Andric                                         bool IsStrided) {
394e8d8bef9SDimitry Andric   SDLoc DL(Node);
395e8d8bef9SDimitry Andric   unsigned NF = Node->getNumOperands() - 5;
396e8d8bef9SDimitry Andric   if (IsStrided)
397e8d8bef9SDimitry Andric     NF--;
398e8d8bef9SDimitry Andric   EVT VT = Node->getOperand(2)->getValueType(0);
399e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
400e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
401e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
402e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
403e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
404e8d8bef9SDimitry Andric   SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL);
405e8d8bef9SDimitry Andric   SmallVector<SDValue, 7> Operands;
406e8d8bef9SDimitry Andric   Operands.push_back(StoreVal);
407e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(2 + NF)); // Base pointer.
408e8d8bef9SDimitry Andric   if (IsStrided) {
409e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3 + NF)); // Stride.
410e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(4 + NF)); // Mask.
411e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(5 + NF)); // VL.
412e8d8bef9SDimitry Andric   } else {
413e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(3 + NF)); // Mask.
414e8d8bef9SDimitry Andric     Operands.push_back(Node->getOperand(4 + NF)); // VL.
415e8d8bef9SDimitry Andric   }
416e8d8bef9SDimitry Andric   Operands.push_back(SEW);
417e8d8bef9SDimitry Andric   Operands.push_back(Node->getOperand(0)); // Chain.
418e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
419e8d8bef9SDimitry Andric       IntNo, ScalarSize, static_cast<unsigned>(LMUL),
420e8d8bef9SDimitry Andric       static_cast<unsigned>(RISCVVLMUL::LMUL_1));
421e8d8bef9SDimitry Andric   SDNode *Store =
422e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
423e8d8bef9SDimitry Andric   ReplaceNode(Node, Store);
424e8d8bef9SDimitry Andric }
425e8d8bef9SDimitry Andric 
426e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVSXSEG(SDNode *Node, unsigned IntNo) {
427e8d8bef9SDimitry Andric   SDLoc DL(Node);
428e8d8bef9SDimitry Andric   unsigned NF = Node->getNumOperands() - 5;
429e8d8bef9SDimitry Andric   EVT VT = Node->getOperand(2)->getValueType(0);
430e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
431e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
432e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
433e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
434e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
435e8d8bef9SDimitry Andric   SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL);
436e8d8bef9SDimitry Andric   SDValue Operands[] = {
437e8d8bef9SDimitry Andric       StoreVal,
438e8d8bef9SDimitry Andric       Node->getOperand(2 + NF), // Base pointer.
439e8d8bef9SDimitry Andric       Node->getOperand(3 + NF), // Index.
440e8d8bef9SDimitry Andric       Node->getOperand(4 + NF), // VL.
441e8d8bef9SDimitry Andric       SEW,
442e8d8bef9SDimitry Andric       Node->getOperand(0) // Chain.
443e8d8bef9SDimitry Andric   };
444e8d8bef9SDimitry Andric 
445e8d8bef9SDimitry Andric   EVT IndexVT = Node->getOperand(3 + NF)->getValueType(0);
446e8d8bef9SDimitry Andric   RISCVVLMUL IndexLMUL = getLMUL(IndexVT);
447e8d8bef9SDimitry Andric   unsigned IndexScalarSize = IndexVT.getScalarSizeInBits();
448e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
449e8d8bef9SDimitry Andric       IntNo, IndexScalarSize, static_cast<unsigned>(LMUL),
450e8d8bef9SDimitry Andric       static_cast<unsigned>(IndexLMUL));
451e8d8bef9SDimitry Andric   SDNode *Store =
452e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
453e8d8bef9SDimitry Andric   ReplaceNode(Node, Store);
454e8d8bef9SDimitry Andric }
455e8d8bef9SDimitry Andric 
456e8d8bef9SDimitry Andric void RISCVDAGToDAGISel::selectVSXSEGMask(SDNode *Node, unsigned IntNo) {
457e8d8bef9SDimitry Andric   SDLoc DL(Node);
458e8d8bef9SDimitry Andric   unsigned NF = Node->getNumOperands() - 6;
459e8d8bef9SDimitry Andric   EVT VT = Node->getOperand(2)->getValueType(0);
460e8d8bef9SDimitry Andric   unsigned ScalarSize = VT.getScalarSizeInBits();
461e8d8bef9SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
462e8d8bef9SDimitry Andric   RISCVVLMUL LMUL = getLMUL(VT);
463e8d8bef9SDimitry Andric   SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT);
464e8d8bef9SDimitry Andric   SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF);
465e8d8bef9SDimitry Andric   SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL);
466e8d8bef9SDimitry Andric   SDValue Operands[] = {
467e8d8bef9SDimitry Andric       StoreVal,
468e8d8bef9SDimitry Andric       Node->getOperand(2 + NF), // Base pointer.
469e8d8bef9SDimitry Andric       Node->getOperand(3 + NF), // Index.
470e8d8bef9SDimitry Andric       Node->getOperand(4 + NF), // Mask.
471e8d8bef9SDimitry Andric       Node->getOperand(5 + NF), // VL.
472e8d8bef9SDimitry Andric       SEW,
473e8d8bef9SDimitry Andric       Node->getOperand(0) // Chain.
474e8d8bef9SDimitry Andric   };
475e8d8bef9SDimitry Andric 
476e8d8bef9SDimitry Andric   EVT IndexVT = Node->getOperand(3 + NF)->getValueType(0);
477e8d8bef9SDimitry Andric   RISCVVLMUL IndexLMUL = getLMUL(IndexVT);
478e8d8bef9SDimitry Andric   unsigned IndexScalarSize = IndexVT.getScalarSizeInBits();
479e8d8bef9SDimitry Andric   const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo(
480e8d8bef9SDimitry Andric       IntNo, IndexScalarSize, static_cast<unsigned>(LMUL),
481e8d8bef9SDimitry Andric       static_cast<unsigned>(IndexLMUL));
482e8d8bef9SDimitry Andric   SDNode *Store =
483e8d8bef9SDimitry Andric       CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
484e8d8bef9SDimitry Andric   ReplaceNode(Node, Store);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric void RISCVDAGToDAGISel::Select(SDNode *Node) {
4880b57cec5SDimitry Andric   // If we have a custom node, we have already selected.
4890b57cec5SDimitry Andric   if (Node->isMachineOpcode()) {
4900b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
4910b57cec5SDimitry Andric     Node->setNodeId(-1);
4920b57cec5SDimitry Andric     return;
4930b57cec5SDimitry Andric   }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   // Instruction Selection not handled by the auto-generated tablegen selection
4960b57cec5SDimitry Andric   // should be handled here.
4970b57cec5SDimitry Andric   unsigned Opcode = Node->getOpcode();
4980b57cec5SDimitry Andric   MVT XLenVT = Subtarget->getXLenVT();
4990b57cec5SDimitry Andric   SDLoc DL(Node);
5000b57cec5SDimitry Andric   EVT VT = Node->getValueType(0);
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   switch (Opcode) {
5035ffd83dbSDimitry Andric   case ISD::ADD: {
5045ffd83dbSDimitry Andric     // Optimize (add r, imm) to (addi (addi r, imm0) imm1) if applicable. The
5055ffd83dbSDimitry Andric     // immediate must be in specific ranges and have a single use.
5065ffd83dbSDimitry Andric     if (auto *ConstOp = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
5075ffd83dbSDimitry Andric       if (!(ConstOp->hasOneUse()))
5085ffd83dbSDimitry Andric         break;
5095ffd83dbSDimitry Andric       // The imm must be in range [-4096,-2049] or [2048,4094].
5105ffd83dbSDimitry Andric       int64_t Imm = ConstOp->getSExtValue();
5115ffd83dbSDimitry Andric       if (!(-4096 <= Imm && Imm <= -2049) && !(2048 <= Imm && Imm <= 4094))
5125ffd83dbSDimitry Andric         break;
5135ffd83dbSDimitry Andric       // Break the imm to imm0+imm1.
5145ffd83dbSDimitry Andric       EVT VT = Node->getValueType(0);
5155ffd83dbSDimitry Andric       const SDValue ImmOp0 = CurDAG->getTargetConstant(Imm - Imm / 2, DL, VT);
5165ffd83dbSDimitry Andric       const SDValue ImmOp1 = CurDAG->getTargetConstant(Imm / 2, DL, VT);
5175ffd83dbSDimitry Andric       auto *NodeAddi0 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT,
5185ffd83dbSDimitry Andric                                                Node->getOperand(0), ImmOp0);
5195ffd83dbSDimitry Andric       auto *NodeAddi1 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT,
5205ffd83dbSDimitry Andric                                                SDValue(NodeAddi0, 0), ImmOp1);
5215ffd83dbSDimitry Andric       ReplaceNode(Node, NodeAddi1);
5225ffd83dbSDimitry Andric       return;
5235ffd83dbSDimitry Andric     }
5245ffd83dbSDimitry Andric     break;
5255ffd83dbSDimitry Andric   }
5260b57cec5SDimitry Andric   case ISD::Constant: {
5270b57cec5SDimitry Andric     auto ConstNode = cast<ConstantSDNode>(Node);
5280b57cec5SDimitry Andric     if (VT == XLenVT && ConstNode->isNullValue()) {
529e8d8bef9SDimitry Andric       SDValue New =
530e8d8bef9SDimitry Andric           CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, XLenVT);
5310b57cec5SDimitry Andric       ReplaceNode(Node, New.getNode());
5320b57cec5SDimitry Andric       return;
5330b57cec5SDimitry Andric     }
5340b57cec5SDimitry Andric     int64_t Imm = ConstNode->getSExtValue();
5350b57cec5SDimitry Andric     if (XLenVT == MVT::i64) {
536e8d8bef9SDimitry Andric       ReplaceNode(Node, selectImm(CurDAG, DL, Imm, XLenVT));
5370b57cec5SDimitry Andric       return;
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric     break;
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric   case ISD::FrameIndex: {
5420b57cec5SDimitry Andric     SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT);
5430b57cec5SDimitry Andric     int FI = cast<FrameIndexSDNode>(Node)->getIndex();
5440b57cec5SDimitry Andric     SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
5450b57cec5SDimitry Andric     ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm));
5460b57cec5SDimitry Andric     return;
5470b57cec5SDimitry Andric   }
548e8d8bef9SDimitry Andric   case ISD::INTRINSIC_W_CHAIN: {
549e8d8bef9SDimitry Andric     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
550e8d8bef9SDimitry Andric     switch (IntNo) {
551e8d8bef9SDimitry Andric       // By default we do not custom select any intrinsic.
552e8d8bef9SDimitry Andric     default:
5530b57cec5SDimitry Andric       break;
5540b57cec5SDimitry Andric 
555e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsetvli: {
556e8d8bef9SDimitry Andric       if (!Subtarget->hasStdExtV())
557e8d8bef9SDimitry Andric         break;
558e8d8bef9SDimitry Andric 
559e8d8bef9SDimitry Andric       assert(Node->getNumOperands() == 5);
560e8d8bef9SDimitry Andric 
561e8d8bef9SDimitry Andric       RISCVVSEW VSEW =
562e8d8bef9SDimitry Andric           static_cast<RISCVVSEW>(Node->getConstantOperandVal(3) & 0x7);
563e8d8bef9SDimitry Andric       RISCVVLMUL VLMul =
564e8d8bef9SDimitry Andric           static_cast<RISCVVLMUL>(Node->getConstantOperandVal(4) & 0x7);
565e8d8bef9SDimitry Andric 
566e8d8bef9SDimitry Andric       unsigned VTypeI = RISCVVType::encodeVTYPE(
567e8d8bef9SDimitry Andric           VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
568e8d8bef9SDimitry Andric       SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
569e8d8bef9SDimitry Andric 
570e8d8bef9SDimitry Andric       SDValue VLOperand = Node->getOperand(2);
571e8d8bef9SDimitry Andric       if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) {
572*d409305fSDimitry Andric         uint64_t AVL = C->getZExtValue();
573*d409305fSDimitry Andric         if (isUInt<5>(AVL)) {
574*d409305fSDimitry Andric           SDValue VLImm = CurDAG->getTargetConstant(AVL, DL, XLenVT);
575*d409305fSDimitry Andric           ReplaceNode(Node,
576*d409305fSDimitry Andric                       CurDAG->getMachineNode(RISCV::PseudoVSETIVLI, DL, XLenVT,
577*d409305fSDimitry Andric                                              MVT::Other, VLImm, VTypeIOp,
578*d409305fSDimitry Andric                                              /* Chain */ Node->getOperand(0)));
579*d409305fSDimitry Andric           return;
580e8d8bef9SDimitry Andric         }
581e8d8bef9SDimitry Andric       }
582e8d8bef9SDimitry Andric 
583e8d8bef9SDimitry Andric       ReplaceNode(Node,
584e8d8bef9SDimitry Andric                   CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
585e8d8bef9SDimitry Andric                                          MVT::Other, VLOperand, VTypeIOp,
586e8d8bef9SDimitry Andric                                          /* Chain */ Node->getOperand(0)));
587e8d8bef9SDimitry Andric       return;
588e8d8bef9SDimitry Andric     }
589e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsetvlimax: {
590e8d8bef9SDimitry Andric       if (!Subtarget->hasStdExtV())
591e8d8bef9SDimitry Andric         break;
592e8d8bef9SDimitry Andric 
593e8d8bef9SDimitry Andric       assert(Node->getNumOperands() == 4);
594e8d8bef9SDimitry Andric 
595e8d8bef9SDimitry Andric       RISCVVSEW VSEW =
596e8d8bef9SDimitry Andric           static_cast<RISCVVSEW>(Node->getConstantOperandVal(2) & 0x7);
597e8d8bef9SDimitry Andric       RISCVVLMUL VLMul =
598e8d8bef9SDimitry Andric           static_cast<RISCVVLMUL>(Node->getConstantOperandVal(3) & 0x7);
599e8d8bef9SDimitry Andric 
600e8d8bef9SDimitry Andric       unsigned VTypeI = RISCVVType::encodeVTYPE(
601e8d8bef9SDimitry Andric           VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
602e8d8bef9SDimitry Andric       SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
603e8d8bef9SDimitry Andric 
604e8d8bef9SDimitry Andric       SDValue VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT);
605e8d8bef9SDimitry Andric       ReplaceNode(Node,
606e8d8bef9SDimitry Andric                   CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
607e8d8bef9SDimitry Andric                                          MVT::Other, VLOperand, VTypeIOp,
608e8d8bef9SDimitry Andric                                          /* Chain */ Node->getOperand(0)));
609e8d8bef9SDimitry Andric       return;
610e8d8bef9SDimitry Andric     }
611e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg2:
612e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg3:
613e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg4:
614e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg5:
615e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg6:
616e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg7:
617e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg8: {
618e8d8bef9SDimitry Andric       selectVLSEG(Node, IntNo, /*IsStrided=*/false);
619e8d8bef9SDimitry Andric       return;
620e8d8bef9SDimitry Andric     }
621e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg2_mask:
622e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg3_mask:
623e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg4_mask:
624e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg5_mask:
625e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg6_mask:
626e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg7_mask:
627e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlseg8_mask: {
628e8d8bef9SDimitry Andric       selectVLSEGMask(Node, IntNo, /*IsStrided=*/false);
629e8d8bef9SDimitry Andric       return;
630e8d8bef9SDimitry Andric     }
631e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg2:
632e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg3:
633e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg4:
634e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg5:
635e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg6:
636e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg7:
637e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg8: {
638e8d8bef9SDimitry Andric       selectVLSEG(Node, IntNo, /*IsStrided=*/true);
639e8d8bef9SDimitry Andric       return;
640e8d8bef9SDimitry Andric     }
641e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg2_mask:
642e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg3_mask:
643e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg4_mask:
644e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg5_mask:
645e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg6_mask:
646e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg7_mask:
647e8d8bef9SDimitry Andric     case Intrinsic::riscv_vlsseg8_mask: {
648e8d8bef9SDimitry Andric       selectVLSEGMask(Node, IntNo, /*IsStrided=*/true);
649e8d8bef9SDimitry Andric       return;
650e8d8bef9SDimitry Andric     }
651e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg2:
652e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg3:
653e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg4:
654e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg5:
655e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg6:
656e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg7:
657e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg8:
658e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg2:
659e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg3:
660e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg4:
661e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg5:
662e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg6:
663e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg7:
664e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg8: {
665e8d8bef9SDimitry Andric       selectVLXSEG(Node, IntNo);
666e8d8bef9SDimitry Andric       return;
667e8d8bef9SDimitry Andric     }
668e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg2_mask:
669e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg3_mask:
670e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg4_mask:
671e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg5_mask:
672e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg6_mask:
673e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg7_mask:
674e8d8bef9SDimitry Andric     case Intrinsic::riscv_vloxseg8_mask:
675e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg2_mask:
676e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg3_mask:
677e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg4_mask:
678e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg5_mask:
679e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg6_mask:
680e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg7_mask:
681e8d8bef9SDimitry Andric     case Intrinsic::riscv_vluxseg8_mask: {
682e8d8bef9SDimitry Andric       selectVLXSEGMask(Node, IntNo);
6830b57cec5SDimitry Andric       return;
6840b57cec5SDimitry Andric     }
6850b57cec5SDimitry Andric     }
6860b57cec5SDimitry Andric     break;
6870b57cec5SDimitry Andric   }
688e8d8bef9SDimitry Andric   case ISD::INTRINSIC_VOID: {
689e8d8bef9SDimitry Andric     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
690e8d8bef9SDimitry Andric     switch (IntNo) {
691e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg2:
692e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg3:
693e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg4:
694e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg5:
695e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg6:
696e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg7:
697e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg8: {
698e8d8bef9SDimitry Andric       selectVSSEG(Node, IntNo, /*IsStrided=*/false);
6990b57cec5SDimitry Andric       return;
7000b57cec5SDimitry Andric     }
701e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg2_mask:
702e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg3_mask:
703e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg4_mask:
704e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg5_mask:
705e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg6_mask:
706e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg7_mask:
707e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsseg8_mask: {
708e8d8bef9SDimitry Andric       selectVSSEGMask(Node, IntNo, /*IsStrided=*/false);
709e8d8bef9SDimitry Andric       return;
710e8d8bef9SDimitry Andric     }
711e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg2:
712e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg3:
713e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg4:
714e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg5:
715e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg6:
716e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg7:
717e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg8: {
718e8d8bef9SDimitry Andric       selectVSSEG(Node, IntNo, /*IsStrided=*/true);
719e8d8bef9SDimitry Andric       return;
720e8d8bef9SDimitry Andric     }
721e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg2_mask:
722e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg3_mask:
723e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg4_mask:
724e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg5_mask:
725e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg6_mask:
726e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg7_mask:
727e8d8bef9SDimitry Andric     case Intrinsic::riscv_vssseg8_mask: {
728e8d8bef9SDimitry Andric       selectVSSEGMask(Node, IntNo, /*IsStrided=*/true);
729e8d8bef9SDimitry Andric       return;
730e8d8bef9SDimitry Andric     }
731e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg2:
732e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg3:
733e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg4:
734e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg5:
735e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg6:
736e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg7:
737e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg8:
738e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg2:
739e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg3:
740e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg4:
741e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg5:
742e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg6:
743e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg7:
744e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg8: {
745e8d8bef9SDimitry Andric       selectVSXSEG(Node, IntNo);
746e8d8bef9SDimitry Andric       return;
747e8d8bef9SDimitry Andric     }
748e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg2_mask:
749e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg3_mask:
750e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg4_mask:
751e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg5_mask:
752e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg6_mask:
753e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg7_mask:
754e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsoxseg8_mask:
755e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg2_mask:
756e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg3_mask:
757e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg4_mask:
758e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg5_mask:
759e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg6_mask:
760e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg7_mask:
761e8d8bef9SDimitry Andric     case Intrinsic::riscv_vsuxseg8_mask: {
762e8d8bef9SDimitry Andric       selectVSXSEGMask(Node, IntNo);
763e8d8bef9SDimitry Andric       return;
764e8d8bef9SDimitry Andric     }
765e8d8bef9SDimitry Andric     }
766e8d8bef9SDimitry Andric     break;
767e8d8bef9SDimitry Andric   }
768e8d8bef9SDimitry Andric   case RISCVISD::VLSEGFF: {
769e8d8bef9SDimitry Andric     selectVLSEGFF(Node);
770e8d8bef9SDimitry Andric     return;
771e8d8bef9SDimitry Andric   }
772e8d8bef9SDimitry Andric   case RISCVISD::VLSEGFF_MASK: {
773e8d8bef9SDimitry Andric     selectVLSEGFFMask(Node);
774e8d8bef9SDimitry Andric     return;
775e8d8bef9SDimitry Andric   }
776e8d8bef9SDimitry Andric   }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   // Select the default instruction.
7790b57cec5SDimitry Andric   SelectCode(Node);
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand(
7830b57cec5SDimitry Andric     const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
7840b57cec5SDimitry Andric   switch (ConstraintID) {
7850b57cec5SDimitry Andric   case InlineAsm::Constraint_m:
7860b57cec5SDimitry Andric     // We just support simple memory operands that have a single address
7870b57cec5SDimitry Andric     // operand and need no special handling.
7880b57cec5SDimitry Andric     OutOps.push_back(Op);
7890b57cec5SDimitry Andric     return false;
7900b57cec5SDimitry Andric   case InlineAsm::Constraint_A:
7910b57cec5SDimitry Andric     OutOps.push_back(Op);
7920b57cec5SDimitry Andric     return false;
7930b57cec5SDimitry Andric   default:
7940b57cec5SDimitry Andric     break;
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   return true;
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) {
8010b57cec5SDimitry Andric   if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
8020b57cec5SDimitry Andric     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
8030b57cec5SDimitry Andric     return true;
8040b57cec5SDimitry Andric   }
8050b57cec5SDimitry Andric   return false;
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric 
808e8d8bef9SDimitry Andric // Match (srl (and val, mask), imm) where the result would be a
809e8d8bef9SDimitry Andric // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result
810e8d8bef9SDimitry Andric // is equivalent to this (SimplifyDemandedBits may have removed lower bits
811e8d8bef9SDimitry Andric // from the mask that aren't necessary due to the right-shifting).
812e8d8bef9SDimitry Andric bool RISCVDAGToDAGISel::MatchSRLIW(SDNode *N) const {
813e8d8bef9SDimitry Andric   assert(N->getOpcode() == ISD::SRL);
814e8d8bef9SDimitry Andric   assert(N->getOperand(0).getOpcode() == ISD::AND);
815e8d8bef9SDimitry Andric   assert(isa<ConstantSDNode>(N->getOperand(1)));
816e8d8bef9SDimitry Andric   assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1)));
817e8d8bef9SDimitry Andric 
818e8d8bef9SDimitry Andric   // The IsRV64 predicate is checked after PatFrag predicates so we can get
819e8d8bef9SDimitry Andric   // here even on RV32.
820e8d8bef9SDimitry Andric   if (!Subtarget->is64Bit())
821e8d8bef9SDimitry Andric     return false;
822e8d8bef9SDimitry Andric 
823e8d8bef9SDimitry Andric   SDValue And = N->getOperand(0);
824e8d8bef9SDimitry Andric   uint64_t ShAmt = N->getConstantOperandVal(1);
825e8d8bef9SDimitry Andric   uint64_t Mask = And.getConstantOperandVal(1);
826e8d8bef9SDimitry Andric   return (Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff;
827e8d8bef9SDimitry Andric }
828e8d8bef9SDimitry Andric 
829979e22ffSDimitry Andric // Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
830979e22ffSDimitry Andric // on RV64).
831979e22ffSDimitry Andric // SLLIUW is the same as SLLI except for the fact that it clears the bits
832979e22ffSDimitry Andric // XLEN-1:32 of the input RS1 before shifting.
833e8d8bef9SDimitry Andric // A PatFrag has already checked that it has the right structure:
834979e22ffSDimitry Andric //
835979e22ffSDimitry Andric //  (AND (SHL RS1, VC2), VC1)
836979e22ffSDimitry Andric //
837979e22ffSDimitry Andric // We check that VC2, the shamt is less than 32, otherwise the pattern is
838979e22ffSDimitry Andric // exactly the same as SLLI and we give priority to that.
839e8d8bef9SDimitry Andric // Eventually we check that VC1, the mask used to clear the upper 32 bits
840979e22ffSDimitry Andric // of RS1, is correct:
841979e22ffSDimitry Andric //
842979e22ffSDimitry Andric //  VC1 == (0xFFFFFFFF << VC2)
843e8d8bef9SDimitry Andric //
844e8d8bef9SDimitry Andric bool RISCVDAGToDAGISel::MatchSLLIUW(SDNode *N) const {
845e8d8bef9SDimitry Andric   assert(N->getOpcode() == ISD::AND);
846e8d8bef9SDimitry Andric   assert(N->getOperand(0).getOpcode() == ISD::SHL);
847e8d8bef9SDimitry Andric   assert(isa<ConstantSDNode>(N->getOperand(1)));
848e8d8bef9SDimitry Andric   assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1)));
849979e22ffSDimitry Andric 
850e8d8bef9SDimitry Andric   // The IsRV64 predicate is checked after PatFrag predicates so we can get
851e8d8bef9SDimitry Andric   // here even on RV32.
852e8d8bef9SDimitry Andric   if (!Subtarget->is64Bit())
853e8d8bef9SDimitry Andric     return false;
854e8d8bef9SDimitry Andric 
855e8d8bef9SDimitry Andric   SDValue Shl = N->getOperand(0);
856e8d8bef9SDimitry Andric   uint64_t VC1 = N->getConstantOperandVal(1);
857979e22ffSDimitry Andric   uint64_t VC2 = Shl.getConstantOperandVal(1);
858e8d8bef9SDimitry Andric 
859e8d8bef9SDimitry Andric   // Immediate range should be enforced by uimm5 predicate.
860e8d8bef9SDimitry Andric   assert(VC2 < 32 && "Unexpected immediate");
861e8d8bef9SDimitry Andric   return (VC1 >> VC2) == UINT64_C(0xFFFFFFFF);
862e8d8bef9SDimitry Andric }
863e8d8bef9SDimitry Andric 
864*d409305fSDimitry Andric // X0 has special meaning for vsetvl/vsetvli.
865*d409305fSDimitry Andric //  rd | rs1 |   AVL value | Effect on vl
866*d409305fSDimitry Andric //--------------------------------------------------------------
867*d409305fSDimitry Andric // !X0 |  X0 |       VLMAX | Set vl to VLMAX
868*d409305fSDimitry Andric //  X0 |  X0 | Value in vl | Keep current vl, just change vtype.
869*d409305fSDimitry Andric bool RISCVDAGToDAGISel::selectVLOp(SDValue N, SDValue &VL) {
870*d409305fSDimitry Andric   // If the VL value is a constant 0, manually select it to an ADDI with 0
871*d409305fSDimitry Andric   // immediate to prevent the default selection path from matching it to X0.
872*d409305fSDimitry Andric   auto *C = dyn_cast<ConstantSDNode>(N);
873*d409305fSDimitry Andric   if (C && C->isNullValue())
874*d409305fSDimitry Andric     VL = SDValue(selectImm(CurDAG, SDLoc(N), 0, Subtarget->getXLenVT()), 0);
875*d409305fSDimitry Andric   else
876*d409305fSDimitry Andric     VL = N;
877*d409305fSDimitry Andric 
878*d409305fSDimitry Andric   return true;
879*d409305fSDimitry Andric }
880*d409305fSDimitry Andric 
881e8d8bef9SDimitry Andric bool RISCVDAGToDAGISel::selectVSplat(SDValue N, SDValue &SplatVal) {
882e8d8bef9SDimitry Andric   if (N.getOpcode() != ISD::SPLAT_VECTOR &&
883e8d8bef9SDimitry Andric       N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64)
884e8d8bef9SDimitry Andric     return false;
885e8d8bef9SDimitry Andric   SplatVal = N.getOperand(0);
886979e22ffSDimitry Andric   return true;
887979e22ffSDimitry Andric }
888e8d8bef9SDimitry Andric 
889e8d8bef9SDimitry Andric bool RISCVDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &SplatVal) {
890e8d8bef9SDimitry Andric   if ((N.getOpcode() != ISD::SPLAT_VECTOR &&
891e8d8bef9SDimitry Andric        N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) ||
892e8d8bef9SDimitry Andric       !isa<ConstantSDNode>(N.getOperand(0)))
893979e22ffSDimitry Andric     return false;
894e8d8bef9SDimitry Andric 
895e8d8bef9SDimitry Andric   int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue();
896e8d8bef9SDimitry Andric 
897e8d8bef9SDimitry Andric   // Both ISD::SPLAT_VECTOR and RISCVISD::SPLAT_VECTOR_I64 share semantics when
898e8d8bef9SDimitry Andric   // the operand type is wider than the resulting vector element type: an
899e8d8bef9SDimitry Andric   // implicit truncation first takes place. Therefore, perform a manual
900e8d8bef9SDimitry Andric   // truncation/sign-extension in order to ignore any truncated bits and catch
901e8d8bef9SDimitry Andric   // any zero-extended immediate.
902e8d8bef9SDimitry Andric   // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first
903e8d8bef9SDimitry Andric   // sign-extending to (XLenVT -1).
904e8d8bef9SDimitry Andric   auto XLenVT = Subtarget->getXLenVT();
905e8d8bef9SDimitry Andric   assert(XLenVT == N.getOperand(0).getSimpleValueType() &&
906e8d8bef9SDimitry Andric          "Unexpected splat operand type");
907e8d8bef9SDimitry Andric   auto EltVT = N.getValueType().getVectorElementType();
908e8d8bef9SDimitry Andric   if (EltVT.bitsLT(XLenVT)) {
909e8d8bef9SDimitry Andric     SplatImm = SignExtend64(SplatImm, EltVT.getSizeInBits());
910979e22ffSDimitry Andric   }
911979e22ffSDimitry Andric 
912e8d8bef9SDimitry Andric   if (!isInt<5>(SplatImm))
913e8d8bef9SDimitry Andric     return false;
914979e22ffSDimitry Andric 
915e8d8bef9SDimitry Andric   SplatVal = CurDAG->getTargetConstant(SplatImm, SDLoc(N), XLenVT);
916979e22ffSDimitry Andric   return true;
917979e22ffSDimitry Andric }
918e8d8bef9SDimitry Andric 
919e8d8bef9SDimitry Andric bool RISCVDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &SplatVal) {
920e8d8bef9SDimitry Andric   if ((N.getOpcode() != ISD::SPLAT_VECTOR &&
921e8d8bef9SDimitry Andric        N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) ||
922e8d8bef9SDimitry Andric       !isa<ConstantSDNode>(N.getOperand(0)))
923979e22ffSDimitry Andric     return false;
924979e22ffSDimitry Andric 
925e8d8bef9SDimitry Andric   int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue();
926979e22ffSDimitry Andric 
927e8d8bef9SDimitry Andric   if (!isUInt<5>(SplatImm))
928e8d8bef9SDimitry Andric     return false;
929e8d8bef9SDimitry Andric 
930e8d8bef9SDimitry Andric   SplatVal =
931e8d8bef9SDimitry Andric       CurDAG->getTargetConstant(SplatImm, SDLoc(N), Subtarget->getXLenVT());
932e8d8bef9SDimitry Andric 
933979e22ffSDimitry Andric   return true;
934979e22ffSDimitry Andric }
935979e22ffSDimitry Andric 
9360b57cec5SDimitry Andric // Merge an ADDI into the offset of a load/store instruction where possible.
9375ffd83dbSDimitry Andric // (load (addi base, off1), off2) -> (load base, off1+off2)
9385ffd83dbSDimitry Andric // (store val, (addi base, off1), off2) -> (store val, base, off1+off2)
9395ffd83dbSDimitry Andric // This is possible when off1+off2 fits a 12-bit immediate.
9400b57cec5SDimitry Andric void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() {
9410b57cec5SDimitry Andric   SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode());
9420b57cec5SDimitry Andric   ++Position;
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric   while (Position != CurDAG->allnodes_begin()) {
9450b57cec5SDimitry Andric     SDNode *N = &*--Position;
9460b57cec5SDimitry Andric     // Skip dead nodes and any non-machine opcodes.
9470b57cec5SDimitry Andric     if (N->use_empty() || !N->isMachineOpcode())
9480b57cec5SDimitry Andric       continue;
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric     int OffsetOpIdx;
9510b57cec5SDimitry Andric     int BaseOpIdx;
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric     // Only attempt this optimisation for I-type loads and S-type stores.
9540b57cec5SDimitry Andric     switch (N->getMachineOpcode()) {
9550b57cec5SDimitry Andric     default:
9560b57cec5SDimitry Andric       continue;
9570b57cec5SDimitry Andric     case RISCV::LB:
9580b57cec5SDimitry Andric     case RISCV::LH:
9590b57cec5SDimitry Andric     case RISCV::LW:
9600b57cec5SDimitry Andric     case RISCV::LBU:
9610b57cec5SDimitry Andric     case RISCV::LHU:
9620b57cec5SDimitry Andric     case RISCV::LWU:
9630b57cec5SDimitry Andric     case RISCV::LD:
964e8d8bef9SDimitry Andric     case RISCV::FLH:
9650b57cec5SDimitry Andric     case RISCV::FLW:
9660b57cec5SDimitry Andric     case RISCV::FLD:
9670b57cec5SDimitry Andric       BaseOpIdx = 0;
9680b57cec5SDimitry Andric       OffsetOpIdx = 1;
9690b57cec5SDimitry Andric       break;
9700b57cec5SDimitry Andric     case RISCV::SB:
9710b57cec5SDimitry Andric     case RISCV::SH:
9720b57cec5SDimitry Andric     case RISCV::SW:
9730b57cec5SDimitry Andric     case RISCV::SD:
974e8d8bef9SDimitry Andric     case RISCV::FSH:
9750b57cec5SDimitry Andric     case RISCV::FSW:
9760b57cec5SDimitry Andric     case RISCV::FSD:
9770b57cec5SDimitry Andric       BaseOpIdx = 1;
9780b57cec5SDimitry Andric       OffsetOpIdx = 2;
9790b57cec5SDimitry Andric       break;
9800b57cec5SDimitry Andric     }
9810b57cec5SDimitry Andric 
9825ffd83dbSDimitry Andric     if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx)))
9830b57cec5SDimitry Andric       continue;
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric     SDValue Base = N->getOperand(BaseOpIdx);
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric     // If the base is an ADDI, we can merge it in to the load/store.
9880b57cec5SDimitry Andric     if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI)
9890b57cec5SDimitry Andric       continue;
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric     SDValue ImmOperand = Base.getOperand(1);
9925ffd83dbSDimitry Andric     uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx);
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric     if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) {
9955ffd83dbSDimitry Andric       int64_t Offset1 = Const->getSExtValue();
9965ffd83dbSDimitry Andric       int64_t CombinedOffset = Offset1 + Offset2;
9975ffd83dbSDimitry Andric       if (!isInt<12>(CombinedOffset))
9985ffd83dbSDimitry Andric         continue;
9995ffd83dbSDimitry Andric       ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand),
10005ffd83dbSDimitry Andric                                              ImmOperand.getValueType());
10010b57cec5SDimitry Andric     } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) {
10025ffd83dbSDimitry Andric       // If the off1 in (addi base, off1) is a global variable's address (its
10035ffd83dbSDimitry Andric       // low part, really), then we can rely on the alignment of that variable
10045ffd83dbSDimitry Andric       // to provide a margin of safety before off1 can overflow the 12 bits.
10055ffd83dbSDimitry Andric       // Check if off2 falls within that margin; if so off1+off2 can't overflow.
10065ffd83dbSDimitry Andric       const DataLayout &DL = CurDAG->getDataLayout();
10075ffd83dbSDimitry Andric       Align Alignment = GA->getGlobal()->getPointerAlignment(DL);
10085ffd83dbSDimitry Andric       if (Offset2 != 0 && Alignment <= Offset2)
10095ffd83dbSDimitry Andric         continue;
10105ffd83dbSDimitry Andric       int64_t Offset1 = GA->getOffset();
10115ffd83dbSDimitry Andric       int64_t CombinedOffset = Offset1 + Offset2;
10120b57cec5SDimitry Andric       ImmOperand = CurDAG->getTargetGlobalAddress(
10130b57cec5SDimitry Andric           GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(),
10145ffd83dbSDimitry Andric           CombinedOffset, GA->getTargetFlags());
10155ffd83dbSDimitry Andric     } else if (auto CP = dyn_cast<ConstantPoolSDNode>(ImmOperand)) {
10165ffd83dbSDimitry Andric       // Ditto.
10175ffd83dbSDimitry Andric       Align Alignment = CP->getAlign();
10185ffd83dbSDimitry Andric       if (Offset2 != 0 && Alignment <= Offset2)
10195ffd83dbSDimitry Andric         continue;
10205ffd83dbSDimitry Andric       int64_t Offset1 = CP->getOffset();
10215ffd83dbSDimitry Andric       int64_t CombinedOffset = Offset1 + Offset2;
10225ffd83dbSDimitry Andric       ImmOperand = CurDAG->getTargetConstantPool(
10235ffd83dbSDimitry Andric           CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(),
10245ffd83dbSDimitry Andric           CombinedOffset, CP->getTargetFlags());
10250b57cec5SDimitry Andric     } else {
10260b57cec5SDimitry Andric       continue;
10270b57cec5SDimitry Andric     }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase:    ");
10300b57cec5SDimitry Andric     LLVM_DEBUG(Base->dump(CurDAG));
10310b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\nN: ");
10320b57cec5SDimitry Andric     LLVM_DEBUG(N->dump(CurDAG));
10330b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric     // Modify the offset operand of the load/store.
10360b57cec5SDimitry Andric     if (BaseOpIdx == 0) // Load
10370b57cec5SDimitry Andric       CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
10380b57cec5SDimitry Andric                                  N->getOperand(2));
10390b57cec5SDimitry Andric     else // Store
10400b57cec5SDimitry Andric       CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
10410b57cec5SDimitry Andric                                  ImmOperand, N->getOperand(3));
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric     // The add-immediate may now be dead, in which case remove it.
10440b57cec5SDimitry Andric     if (Base.getNode()->use_empty())
10450b57cec5SDimitry Andric       CurDAG->RemoveDeadNode(Base.getNode());
10460b57cec5SDimitry Andric   }
10470b57cec5SDimitry Andric }
10480b57cec5SDimitry Andric 
10490b57cec5SDimitry Andric // This pass converts a legalized DAG into a RISCV-specific DAG, ready
10500b57cec5SDimitry Andric // for instruction scheduling.
10510b57cec5SDimitry Andric FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {
10520b57cec5SDimitry Andric   return new RISCVDAGToDAGISel(TM);
10530b57cec5SDimitry Andric }
1054