LLVM 24.0.0git
RISCVInstructionSelector.cpp
Go to the documentation of this file.
1//===-- RISCVInstructionSelector.cpp -----------------------------*- C++ -*-==//
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/// \file
9/// This file implements the targeting of the InstructionSelector class for
10/// RISC-V.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
16#include "RISCVSubtarget.h"
17#include "RISCVTargetMachine.h"
25#include "llvm/IR/IntrinsicsRISCV.h"
26#include "llvm/Support/Debug.h"
27
28#define DEBUG_TYPE "riscv-isel"
29
30using namespace llvm;
31using namespace MIPatternMatch;
32
33#define GET_GLOBALISEL_PREDICATE_BITSET
34#include "RISCVGenGlobalISel.inc"
35#undef GET_GLOBALISEL_PREDICATE_BITSET
36
37namespace {
38
39class RISCVInstructionSelector : public InstructionSelector {
40public:
41 RISCVInstructionSelector(const RISCVTargetMachine &TM,
42 const RISCVSubtarget &STI,
43 const RISCVRegisterBankInfo &RBI);
44
45 bool select(MachineInstr &MI) override;
46
47 void setupMF(MachineFunction &MF, GISelValueTracking *VT,
48 CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI,
49 BlockFrequencyInfo *BFI) override {
50 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
51 MRI = &MF.getRegInfo();
52 }
53
54 static const char *getName() { return DEBUG_TYPE; }
55
56private:
57 static constexpr unsigned MaxRecursionDepth = 6;
58
59 bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits,
60 const unsigned Depth = 0) const;
61 bool hasAllHUsers(const MachineInstr &MI) const {
62 return hasAllNBitUsers(MI, 16);
63 }
64 bool hasAllWUsers(const MachineInstr &MI) const {
65 return hasAllNBitUsers(MI, 32);
66 }
67
68 bool isRegInGprb(Register Reg) const;
69 bool isRegInFprb(Register Reg) const;
70
71 // tblgen-erated 'select' implementation, used as the initial selector for
72 // the patterns that don't require complex C++.
73 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
74
75 // A lowering phase that runs before any selection attempts.
76 // Returns true if the instruction was modified.
77 void preISelLower(MachineInstr &MI);
78
79 bool replacePtrWithInt(MachineOperand &Op);
80
81 // Custom selection methods
82 bool selectCopy(MachineInstr &MI) const;
83 bool selectImplicitDef(MachineInstr &MI) const;
84 bool materializeImm(Register Reg, int64_t Imm, MachineInstr &MI) const;
85 bool selectAddr(MachineInstr &MI, bool IsLocal = true,
86 bool IsExternWeak = false) const;
87 bool selectSelect(MachineInstr &MI) const;
88 bool selectFPCompare(MachineInstr &MI) const;
89 void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
90 MachineInstr &MI) const;
92 void addVectorLoadStoreOperands(MachineInstr &I,
94 unsigned &CurOp, bool IsMasked,
95 bool IsStridedOrIndexed,
96 LLT *IndexVT = nullptr) const;
97 bool selectIntrinsicWithSideEffects(MachineInstr &I) const;
98 bool selectIntrinsic(MachineInstr &I) const;
99 bool selectExtractSubvector(MachineInstr &MI) const;
100 bool selectInsertSubVector(MachineInstr &I) const;
101 ComplexRendererFns selectShiftMask(MachineOperand &Root,
102 unsigned ShiftWidth) const;
103 ComplexRendererFns selectShiftMaskXLen(MachineOperand &Root) const {
104 return selectShiftMask(Root, STI.getXLen());
105 }
106 ComplexRendererFns selectShiftMask32(MachineOperand &Root) const {
107 return selectShiftMask(Root, 32);
108 }
109 ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
110
111 ComplexRendererFns selectSExtBits(MachineOperand &Root, unsigned Bits) const;
112 template <unsigned Bits>
113 ComplexRendererFns selectSExtBits(MachineOperand &Root) const {
114 return selectSExtBits(Root, Bits);
115 }
116
117 ComplexRendererFns selectZExtBits(MachineOperand &Root, unsigned Bits) const;
118 template <unsigned Bits>
119 ComplexRendererFns selectZExtBits(MachineOperand &Root) const {
120 return selectZExtBits(Root, Bits);
121 }
122
123 ComplexRendererFns selectSHXADDOp(MachineOperand &Root, unsigned ShAmt) const;
124 template <unsigned ShAmt>
125 ComplexRendererFns selectSHXADDOp(MachineOperand &Root) const {
126 return selectSHXADDOp(Root, ShAmt);
127 }
128
129 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root,
130 unsigned ShAmt) const;
131 template <unsigned ShAmt>
132 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root) const {
133 return selectSHXADD_UWOp(Root, ShAmt);
134 }
135
136 ComplexRendererFns renderVLOp(MachineOperand &Root) const;
137
138 // Custom renderers for tablegen
139 void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
140 int OpIdx) const;
141 void renderImmSubFromXLen(MachineInstrBuilder &MIB, const MachineInstr &MI,
142 int OpIdx) const;
143 void renderImmSubFrom32(MachineInstrBuilder &MIB, const MachineInstr &MI,
144 int OpIdx) const;
145 void renderImmPlus1(MachineInstrBuilder &MIB, const MachineInstr &MI,
146 int OpIdx) const;
147
148 void renderTrailingZeros(MachineInstrBuilder &MIB, const MachineInstr &MI,
149 int OpIdx) const;
150 void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
151 const MachineInstr &MI, int OpIdx) const;
152
153 void renderAddiPairImmLarge(MachineInstrBuilder &MIB, const MachineInstr &MI,
154 int OpIdx) const;
155 void renderAddiPairImmSmall(MachineInstrBuilder &MIB, const MachineInstr &MI,
156 int OpIdx) const;
157
158 const RISCVSubtarget &STI;
159 const RISCVInstrInfo &TII;
160 const RISCVRegisterInfo &TRI;
161 const RISCVRegisterBankInfo &RBI;
162 const RISCVTargetMachine &TM;
163
164 MachineRegisterInfo *MRI = nullptr;
165
166 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
167 // uses "STI." in the code generated by TableGen. We need to unify the name of
168 // Subtarget variable.
169 const RISCVSubtarget *Subtarget = &STI;
170
171#define GET_GLOBALISEL_PREDICATES_DECL
172#include "RISCVGenGlobalISel.inc"
173#undef GET_GLOBALISEL_PREDICATES_DECL
174
175#define GET_GLOBALISEL_TEMPORARIES_DECL
176#include "RISCVGenGlobalISel.inc"
177#undef GET_GLOBALISEL_TEMPORARIES_DECL
178};
179
180} // end anonymous namespace
181
182#define GET_GLOBALISEL_IMPL
183#include "RISCVGenGlobalISel.inc"
184#undef GET_GLOBALISEL_IMPL
185
186RISCVInstructionSelector::RISCVInstructionSelector(
187 const RISCVTargetMachine &TM, const RISCVSubtarget &STI,
188 const RISCVRegisterBankInfo &RBI)
189 : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
190 TM(TM),
191
193#include "RISCVGenGlobalISel.inc"
196#include "RISCVGenGlobalISel.inc"
198{
199}
200
201// Mimics optimizations in ISel and RISCVOptWInst Pass
202bool RISCVInstructionSelector::hasAllNBitUsers(const MachineInstr &MI,
203 unsigned Bits,
204 const unsigned Depth) const {
205
206 assert((MI.getOpcode() == TargetOpcode::G_ADD ||
207 MI.getOpcode() == TargetOpcode::G_SUB ||
208 MI.getOpcode() == TargetOpcode::G_MUL ||
209 MI.getOpcode() == TargetOpcode::G_SHL ||
210 MI.getOpcode() == TargetOpcode::G_LSHR ||
211 MI.getOpcode() == TargetOpcode::G_AND ||
212 MI.getOpcode() == TargetOpcode::G_OR ||
213 MI.getOpcode() == TargetOpcode::G_XOR ||
214 MI.getOpcode() == TargetOpcode::G_SEXT_INREG || Depth != 0) &&
215 "Unexpected opcode");
216
217 if (Depth >= RISCVInstructionSelector::MaxRecursionDepth)
218 return false;
219
220 auto DestReg = MI.getOperand(0).getReg();
221 for (auto &UserOp : MRI->use_nodbg_operands(DestReg)) {
222 assert(UserOp.getParent() && "UserOp must have a parent");
223 const MachineInstr &UserMI = *UserOp.getParent();
224 unsigned OpIdx = UserOp.getOperandNo();
225
226 switch (UserMI.getOpcode()) {
227 default:
228 return false;
229 case RISCV::ADDW:
230 case RISCV::ADDIW:
231 case RISCV::SUBW:
232 case RISCV::FCVT_D_W:
233 case RISCV::FCVT_S_W:
234 if (Bits >= 32)
235 break;
236 return false;
237 case RISCV::SLL:
238 case RISCV::SRA:
239 case RISCV::SRL:
240 // Shift amount operands only use log2(Xlen) bits.
241 if (OpIdx == 2 && Bits >= Log2_32(Subtarget->getXLen()))
242 break;
243 return false;
244 case RISCV::SLLI:
245 // SLLI only uses the lower (XLen - ShAmt) bits.
246 if (Bits >= Subtarget->getXLen() - UserMI.getOperand(2).getImm())
247 break;
248 return false;
249 case RISCV::ANDI:
250 if (Bits >= (unsigned)llvm::bit_width<uint64_t>(
251 (uint64_t)UserMI.getOperand(2).getImm()))
252 break;
253 goto RecCheck;
254 case RISCV::AND:
255 case RISCV::OR:
256 case RISCV::XOR:
257 RecCheck:
258 if (hasAllNBitUsers(UserMI, Bits, Depth + 1))
259 break;
260 return false;
261 case RISCV::SRLI: {
262 unsigned ShAmt = UserMI.getOperand(2).getImm();
263 // If we are shifting right by less than Bits, and users don't demand any
264 // bits that were shifted into [Bits-1:0], then we can consider this as an
265 // N-Bit user.
266 if (Bits > ShAmt && hasAllNBitUsers(UserMI, Bits - ShAmt, Depth + 1))
267 break;
268 return false;
269 }
270 }
271 }
272
273 return true;
274}
275
276InstructionSelector::ComplexRendererFns
277RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
278 unsigned ShiftWidth) const {
279 if (!Root.isReg())
280 return std::nullopt;
281
282 using namespace llvm::MIPatternMatch;
283
284 Register ShAmtReg = Root.getReg();
285 // Peek through zext.
286 Register ZExtSrcReg;
287 if (mi_match(ShAmtReg, *MRI, m_GZExt(m_Reg(ZExtSrcReg))))
288 ShAmtReg = ZExtSrcReg;
289
290 APInt AndMask;
291 Register AndSrcReg;
292 // Try to combine the following pattern (applicable to other shift
293 // instructions as well as 32-bit ones):
294 //
295 // %4:gprb(s64) = G_AND %3, %2
296 // %5:gprb(s64) = G_LSHR %1, %4(s64)
297 //
298 // According to RISC-V's ISA manual, SLL, SRL, and SRA ignore other bits than
299 // the lowest log2(XLEN) bits of register rs2. As for the above pattern, if
300 // the lowest log2(XLEN) bits of register rd and rs2 of G_AND are the same,
301 // then it can be eliminated. Given register rs1 or rs2 holding a constant
302 // (the and mask), there are two cases G_AND can be erased:
303 //
304 // 1. the lowest log2(XLEN) bits of the and mask are all set
305 // 2. the bits of the register being masked are already unset (zero set)
306 if (mi_match(ShAmtReg, *MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
307 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
308 if (ShMask.isSubsetOf(AndMask)) {
309 ShAmtReg = AndSrcReg;
310 } else {
311 // SimplifyDemandedBits may have optimized the mask so try restoring any
312 // bits that are known zero.
313 KnownBits Known = VT->getKnownBits(AndSrcReg);
314 if (ShMask.isSubsetOf(AndMask | Known.Zero))
315 ShAmtReg = AndSrcReg;
316 }
317 }
318
319 APInt Imm;
321 if (mi_match(ShAmtReg, *MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
322 if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
323 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
324 // to avoid the ADD.
325 ShAmtReg = Reg;
326 } else if (mi_match(ShAmtReg, *MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
327 if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
328 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
329 // to generate a NEG instead of a SUB of a constant.
330 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
331 unsigned NegOpc = Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
332 return {{[=](MachineInstrBuilder &MIB) {
333 MachineIRBuilder(*MIB.getInstr())
334 .buildInstr(NegOpc, {ShAmtReg}, {Register(RISCV::X0), Reg});
335 MIB.addReg(ShAmtReg);
336 }}};
337 }
338 if (Imm.urem(ShiftWidth) == ShiftWidth - 1) {
339 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
340 // to generate a NOT instead of a SUB of a constant.
341 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
342 return {{[=](MachineInstrBuilder &MIB) {
343 MachineIRBuilder(*MIB.getInstr())
344 .buildInstr(RISCV::XORI, {ShAmtReg}, {Reg})
345 .addImm(-1);
346 MIB.addReg(ShAmtReg);
347 }}};
348 }
349 }
350
351 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
352}
353
354InstructionSelector::ComplexRendererFns
355RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
356 unsigned Bits) const {
357 if (!Root.isReg())
358 return std::nullopt;
359 Register RootReg = Root.getReg();
360
361 Register SrcReg;
362 if (mi_match(RootReg, *MRI,
363 m_GSExtInReg(m_Reg(SrcReg), m_SpecificImm(Bits)))) {
364 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SrcReg); }}};
365 }
366
367 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
368 if ((Size - VT->computeNumSignBits(RootReg)) < Bits)
369 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
370
371 return std::nullopt;
372}
373
374InstructionSelector::ComplexRendererFns
375RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
376 unsigned Bits) const {
377 if (!Root.isReg())
378 return std::nullopt;
379 Register RootReg = Root.getReg();
380
381 Register RegX;
383 if (mi_match(RootReg, *MRI, m_GAnd(m_Reg(RegX), m_SpecificICst(Mask)))) {
384 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
385 }
386
387 if (mi_match(RootReg, *MRI, m_GZExt(m_Reg(RegX))) &&
388 MRI->getType(RegX).getScalarSizeInBits() == Bits)
389 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
390
391 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
392 if (VT->maskedValueIsZero(RootReg, APInt::getBitsSetFrom(Size, Bits)))
393 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
394
395 return std::nullopt;
396}
397
398InstructionSelector::ComplexRendererFns
399RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
400 unsigned ShAmt) const {
401 using namespace llvm::MIPatternMatch;
402
403 if (!Root.isReg())
404 return std::nullopt;
405 Register RootReg = Root.getReg();
406
407 const unsigned XLen = STI.getXLen();
408 APInt Mask, C2;
409 Register RegY;
410 std::optional<bool> LeftShift;
411 // (and (shl y, c2), mask)
412 if (mi_match(RootReg, *MRI,
413 m_GAnd(m_GShl(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
414 LeftShift = true;
415 // (and (lshr y, c2), mask)
416 else if (mi_match(RootReg, *MRI,
417 m_GAnd(m_GLShr(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
418 LeftShift = false;
419
420 if (LeftShift.has_value()) {
421 if (*LeftShift)
423 else
425
426 if (Mask.isShiftedMask()) {
427 unsigned Leading = XLen - Mask.getActiveBits();
428 unsigned Trailing = Mask.countr_zero();
429 // Given (and (shl y, c2), mask) in which mask has no leading zeros and
430 // c3 trailing zeros. We can use an SRLI by c3 - c2 followed by a SHXADD.
431 if (*LeftShift && Leading == 0 && C2.ult(Trailing) && Trailing == ShAmt) {
432 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
433 return {{[=](MachineInstrBuilder &MIB) {
434 MachineIRBuilder(*MIB.getInstr())
435 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
436 .addImm(Trailing - C2.getZExtValue());
437 MIB.addReg(DstReg);
438 }}};
439 }
440
441 // Given (and (lshr y, c2), mask) in which mask has c2 leading zeros and
442 // c3 trailing zeros. We can use an SRLI by c2 + c3 followed by a SHXADD.
443 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
444 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
445 return {{[=](MachineInstrBuilder &MIB) {
446 MachineIRBuilder(*MIB.getInstr())
447 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
448 .addImm(Leading + Trailing);
449 MIB.addReg(DstReg);
450 }}};
451 }
452 }
453 }
454
455 LeftShift.reset();
456
457 // (shl (and y, mask), c2)
458 if (mi_match(RootReg, *MRI,
459 m_GShl(m_OneNonDBGUse(m_GAnd(m_Reg(RegY), m_ICst(Mask))),
460 m_ICst(C2))))
461 LeftShift = true;
462 // (lshr (and y, mask), c2)
463 else if (mi_match(RootReg, *MRI,
465 m_ICst(C2))))
466 LeftShift = false;
467
468 if (LeftShift.has_value() && Mask.isShiftedMask()) {
469 unsigned Leading = XLen - Mask.getActiveBits();
470 unsigned Trailing = Mask.countr_zero();
471
472 // Given (shl (and y, mask), c2) in which mask has 32 leading zeros and
473 // c3 trailing zeros. If c1 + c3 == ShAmt, we can emit SRLIW + SHXADD.
474 bool Cond = *LeftShift && Leading == 32 && Trailing > 0 &&
475 (Trailing + C2.getZExtValue()) == ShAmt;
476 if (!Cond)
477 // Given (lshr (and y, mask), c2) in which mask has 32 leading zeros and
478 // c3 trailing zeros. If c3 - c1 == ShAmt, we can emit SRLIW + SHXADD.
479 Cond = !*LeftShift && Leading == 32 && C2.ult(Trailing) &&
480 (Trailing - C2.getZExtValue()) == ShAmt;
481
482 if (Cond) {
483 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
484 return {{[=](MachineInstrBuilder &MIB) {
485 MachineIRBuilder(*MIB.getInstr())
486 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
487 .addImm(Trailing);
488 MIB.addReg(DstReg);
489 }}};
490 }
491 }
492
493 return std::nullopt;
494}
495
496InstructionSelector::ComplexRendererFns
497RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
498 unsigned ShAmt) const {
499 using namespace llvm::MIPatternMatch;
500
501 if (!Root.isReg())
502 return std::nullopt;
503 Register RootReg = Root.getReg();
504
505 // Given (and (shl x, c2), mask) in which mask is a shifted mask with
506 // 32 - ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
507 // c2 - ShAmt followed by SHXADD_UW with ShAmt for x amount.
508 APInt Mask, C2;
509 Register RegX;
510 if (mi_match(
511 RootReg, *MRI,
513 m_ICst(Mask))))) {
515
516 if (Mask.isShiftedMask()) {
517 unsigned Leading = Mask.countl_zero();
518 unsigned Trailing = Mask.countr_zero();
519 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
520 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
521 return {{[=](MachineInstrBuilder &MIB) {
522 MachineIRBuilder(*MIB.getInstr())
523 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
524 .addImm(C2.getZExtValue() - ShAmt);
525 MIB.addReg(DstReg);
526 }}};
527 }
528 }
529 }
530
531 return std::nullopt;
532}
533
534InstructionSelector::ComplexRendererFns
535RISCVInstructionSelector::renderVLOp(MachineOperand &Root) const {
536 assert(Root.isReg() && "Expected operand to be a Register");
537 std::optional<ValueAndVReg> C;
538 if (mi_match(Root.getReg(), *MRI, m_GCst(C))) {
539 if (C->Value.isAllOnes())
540 // If the operand is a G_CONSTANT with value of all ones it is larger than
541 // VLMAX. We convert it to an immediate with value VLMaxSentinel. This is
542 // recognized specially by the vsetvli insertion pass.
543 return {{[=](MachineInstrBuilder &MIB) {
544 MIB.addImm(RISCV::VLMaxSentinel);
545 }}};
546
547 if (isUInt<5>(C->Value.getZExtValue())) {
548 uint64_t ZExtC = C->Value.getZExtValue();
549 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
550 }
551 }
552 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); }}};
553}
554
555InstructionSelector::ComplexRendererFns
556RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
557 if (!Root.isReg())
558 return std::nullopt;
559
560 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
561 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
562 return {{
563 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
564 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
565 }};
566 }
567
568 if (isBaseWithConstantOffset(Root, *MRI)) {
569 MachineOperand &LHS = RootDef->getOperand(1);
570 MachineOperand &RHS = RootDef->getOperand(2);
571 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
572 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
573
574 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
575 if (isInt<12>(RHSC)) {
576 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
577 return {{
578 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
579 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
580 }};
581
582 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
583 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
584 }
585 }
586
587 // TODO: Need to get the immediate from a G_PTR_ADD. Should this be done in
588 // the combiner?
589 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
590 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
591}
592
593/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
594/// CC Must be an ICMP Predicate.
595static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
596 switch (CC) {
597 default:
598 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
599 case CmpInst::Predicate::ICMP_EQ:
600 return RISCVCC::COND_EQ;
601 case CmpInst::Predicate::ICMP_NE:
602 return RISCVCC::COND_NE;
603 case CmpInst::Predicate::ICMP_ULT:
604 return RISCVCC::COND_LTU;
605 case CmpInst::Predicate::ICMP_SLT:
606 return RISCVCC::COND_LT;
607 case CmpInst::Predicate::ICMP_UGE:
608 return RISCVCC::COND_GEU;
609 case CmpInst::Predicate::ICMP_SGE:
610 return RISCVCC::COND_GE;
611 }
612}
613
616 MachineRegisterInfo &MRI) {
617 // Try to fold an ICmp. If that fails, use a NE compare with X0.
619 if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
620 LHS = CondReg;
621 RHS = RISCV::X0;
622 CC = RISCVCC::COND_NE;
623 return;
624 }
625
626 // We found an ICmp, do some canonicalization.
627
628 // Adjust comparisons to use comparison with 0 if possible.
629 if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
630 switch (Pred) {
632 // Convert X > -1 to X >= 0
633 if (*Constant == -1) {
634 CC = RISCVCC::COND_GE;
635 RHS = RISCV::X0;
636 return;
637 }
638 break;
640 // Convert X < 1 to 0 >= X
641 if (*Constant == 1) {
642 CC = RISCVCC::COND_GE;
643 RHS = LHS;
644 LHS = RISCV::X0;
645 return;
646 }
647 break;
648 default:
649 break;
650 }
651 }
652
653 switch (Pred) {
654 default:
655 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
662 // These CCs are supported directly by RISC-V branches.
663 break;
668 // These CCs are not supported directly by RISC-V branches, but changing the
669 // direction of the CC and swapping LHS and RHS are.
670 Pred = CmpInst::getSwappedPredicate(Pred);
671 std::swap(LHS, RHS);
672 break;
673 }
674
675 CC = getRISCVCCFromICmp(Pred);
676}
677
678/// Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation
679/// \p GenericOpc, appropriate for the GPR register bank and of memory access
680/// size \p OpSize.
681static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
682 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
683 switch (OpSize) {
684 default:
685 llvm_unreachable("Unexpected memory size");
686 case 8:
687 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
688 case 16:
689 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
690 case 32:
691 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
692 case 64:
693 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
694 }
695}
696
697/// Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation
698/// \p GenericOpc, appropriate for the GPR register bank and of memory access
699/// size \p OpSize. \returns \p GenericOpc if the combination is unsupported.
700static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
701 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
702 switch (OpSize) {
703 case 8:
704 // Prefer unsigned due to no c.lb in Zcb.
705 return IsStore ? RISCV::SB : RISCV::LBU;
706 case 16:
707 return IsStore ? RISCV::SH : RISCV::LH;
708 case 32:
709 return IsStore ? RISCV::SW : RISCV::LW;
710 case 64:
711 return IsStore ? RISCV::SD : RISCV::LD;
712 }
713
714 return GenericOpc;
715}
716
717void RISCVInstructionSelector::addVectorLoadStoreOperands(
718 MachineInstr &I, SmallVectorImpl<Register> &SrcOps, unsigned &CurOp,
719 bool IsMasked, bool IsStridedOrIndexed, LLT *IndexVT) const {
720 // Base Pointer
721 auto PtrReg = I.getOperand(CurOp++).getReg();
722 SrcOps.push_back(PtrReg);
723
724 // Stride or Index
725 if (IsStridedOrIndexed) {
726 auto StrideReg = I.getOperand(CurOp++).getReg();
727 SrcOps.push_back(StrideReg);
728 if (IndexVT)
729 *IndexVT = MRI->getType(StrideReg);
730 }
731
732 // Mask
733 if (IsMasked) {
734 auto MaskReg = I.getOperand(CurOp++).getReg();
735 SrcOps.push_back(MaskReg);
736 }
737}
738
739bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
740 MachineInstr &I) const {
741 // Find the intrinsic ID.
742 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
743 // Select the instruction.
744 switch (IntrinID) {
745 default:
746 return false;
747 case Intrinsic::riscv_vlm:
748 case Intrinsic::riscv_vle:
749 case Intrinsic::riscv_vle_mask:
750 case Intrinsic::riscv_vlse:
751 case Intrinsic::riscv_vlse_mask: {
752 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
753 IntrinID == Intrinsic::riscv_vlse_mask;
754 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
755 IntrinID == Intrinsic::riscv_vlse_mask;
756 LLT VT = MRI->getType(I.getOperand(0).getReg());
757 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
758
759 // Result vector
760 const Register DstReg = I.getOperand(0).getReg();
761
762 // Sources
763 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
764 unsigned CurOp = 2;
765 SmallVector<Register, 4> SrcOps; // Source registers.
766
767 // Passthru
768 if (HasPassthruOperand) {
769 auto PassthruReg = I.getOperand(CurOp++).getReg();
770 SrcOps.push_back(PassthruReg);
771 } else {
772 SrcOps.push_back(Register(RISCV::NoRegister));
773 }
774
775 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
776
778 const RISCV::VLEPseudo *P =
779 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
780 static_cast<unsigned>(LMUL));
781
782 MachineInstrBuilder PseudoMI =
783 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
784 for (Register Reg : SrcOps)
785 PseudoMI.addReg(Reg);
786
787 // Select VL
788 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
789 for (auto &RenderFn : *VLOpFn)
790 RenderFn(PseudoMI);
791
792 // SEW
793 PseudoMI.addImm(Log2SEW);
794
795 // Policy
797 if (IsMasked)
798 Policy = I.getOperand(CurOp++).getImm();
799 PseudoMI.addImm(Policy);
800
801 // Memref
802 PseudoMI.cloneMemRefs(I);
803
804 I.eraseFromParent();
805 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
806 return true;
807 }
808 case Intrinsic::riscv_vloxei:
809 case Intrinsic::riscv_vloxei_mask:
810 case Intrinsic::riscv_vluxei:
811 case Intrinsic::riscv_vluxei_mask: {
812 bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
813 IntrinID == Intrinsic::riscv_vluxei_mask;
814 bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
815 IntrinID == Intrinsic::riscv_vloxei_mask;
816 LLT VT = MRI->getType(I.getOperand(0).getReg());
817 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
818
819 // Result vector
820 const Register DstReg = I.getOperand(0).getReg();
821
822 // Sources
823 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
824 unsigned CurOp = 2;
825 SmallVector<Register, 4> SrcOps; // Source registers.
826
827 // Passthru
828 if (HasPassthruOperand) {
829 auto PassthruReg = I.getOperand(CurOp++).getReg();
830 SrcOps.push_back(PassthruReg);
831 } else {
832 // Use NoRegister if there is no specified passthru.
833 SrcOps.push_back(Register());
834 }
835 LLT IndexVT;
836 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
837
839 RISCVVType::VLMUL IndexLMUL =
841 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
842 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
843 reportFatalUsageError("The V extension does not support EEW=64 for index "
844 "values when XLEN=32");
845 }
846 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
847 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
848 static_cast<unsigned>(IndexLMUL));
849
850 MachineInstrBuilder PseudoMI =
851 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
852 for (Register Reg : SrcOps)
853 PseudoMI.addReg(Reg);
854
855 // Select VL
856 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
857 for (auto &RenderFn : *VLOpFn)
858 RenderFn(PseudoMI);
859
860 // SEW
861 PseudoMI.addImm(Log2SEW);
862
863 // Policy
865 if (IsMasked)
866 Policy = I.getOperand(CurOp++).getImm();
867 PseudoMI.addImm(Policy);
868
869 // Memref
870 PseudoMI.cloneMemRefs(I);
871
872 I.eraseFromParent();
873 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
874 return true;
875 }
876 case Intrinsic::riscv_vsm:
877 case Intrinsic::riscv_vse:
878 case Intrinsic::riscv_vse_mask:
879 case Intrinsic::riscv_vsse:
880 case Intrinsic::riscv_vsse_mask: {
881 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
882 IntrinID == Intrinsic::riscv_vsse_mask;
883 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
884 IntrinID == Intrinsic::riscv_vsse_mask;
885 LLT VT = MRI->getType(I.getOperand(1).getReg());
886 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
887
888 // Sources
889 unsigned CurOp = 1;
890 SmallVector<Register, 4> SrcOps; // Source registers.
891
892 // Store value
893 auto PassthruReg = I.getOperand(CurOp++).getReg();
894 SrcOps.push_back(PassthruReg);
895
896 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
897
899 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
900 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
901
902 MachineInstrBuilder PseudoMI =
903 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
904 for (Register Reg : SrcOps)
905 PseudoMI.addReg(Reg);
906
907 // Select VL
908 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
909 for (auto &RenderFn : *VLOpFn)
910 RenderFn(PseudoMI);
911
912 // SEW
913 PseudoMI.addImm(Log2SEW);
914
915 // Memref
916 PseudoMI.cloneMemRefs(I);
917
918 I.eraseFromParent();
919 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
920 return true;
921 }
922 case Intrinsic::riscv_vsoxei:
923 case Intrinsic::riscv_vsoxei_mask:
924 case Intrinsic::riscv_vsuxei:
925 case Intrinsic::riscv_vsuxei_mask: {
926 bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
927 IntrinID == Intrinsic::riscv_vsuxei_mask;
928 bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
929 IntrinID == Intrinsic::riscv_vsoxei_mask;
930 LLT VT = MRI->getType(I.getOperand(1).getReg());
931 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
932
933 // Sources
934 unsigned CurOp = 1;
935 SmallVector<Register, 4> SrcOps; // Source registers.
936
937 // Store value
938 auto PassthruReg = I.getOperand(CurOp++).getReg();
939 SrcOps.push_back(PassthruReg);
940
941 LLT IndexVT;
942 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
943
945 RISCVVType::VLMUL IndexLMUL =
947 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
948 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
949 reportFatalUsageError("The V extension does not support EEW=64 for index "
950 "values when XLEN=32");
951 }
952 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
953 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
954 static_cast<unsigned>(IndexLMUL));
955
956 MachineInstrBuilder PseudoMI =
957 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
958 for (Register Reg : SrcOps)
959 PseudoMI.addReg(Reg);
960
961 // Select VL
962 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
963 for (auto &RenderFn : *VLOpFn)
964 RenderFn(PseudoMI);
965
966 // SEW
967 PseudoMI.addImm(Log2SEW);
968
969 // Memref
970 PseudoMI.cloneMemRefs(I);
971
972 I.eraseFromParent();
973 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
974 return true;
975 }
976 }
977}
978
979bool RISCVInstructionSelector::selectIntrinsic(MachineInstr &I) const {
980 // Find the intrinsic ID.
981 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
982 // Select the instruction.
983 switch (IntrinID) {
984 default:
985 return false;
986 case Intrinsic::riscv_vsetvli:
987 case Intrinsic::riscv_vsetvlimax: {
988
989 bool VLMax = IntrinID == Intrinsic::riscv_vsetvlimax;
990
991 unsigned Offset = VLMax ? 2 : 3;
992 unsigned SEW = RISCVVType::decodeVSEW(I.getOperand(Offset).getImm() & 0x7);
993 RISCVVType::VLMUL VLMul =
994 static_cast<RISCVVType::VLMUL>(I.getOperand(Offset + 1).getImm() & 0x7);
995
996 unsigned VTypeI = RISCVVType::encodeVTYPE(VLMul, SEW, /*TailAgnostic*/ true,
997 /*MaskAgnostic*/ true);
998
999 Register DstReg = I.getOperand(0).getReg();
1000
1001 Register VLOperand;
1002 unsigned Opcode = RISCV::PseudoVSETVLI;
1003
1004 // Check if AVL is a constant that equals VLMAX.
1005 if (!VLMax) {
1006 Register AVLReg = I.getOperand(2).getReg();
1007 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1008 uint64_t AVL = AVLConst->Value.getZExtValue();
1009 if (auto VLEN = Subtarget->getRealVLen()) {
1010 if (*VLEN / RISCVVType::getSEWLMULRatio(SEW, VLMul) == AVL)
1011 VLMax = true;
1012 }
1013 }
1014
1015 if (mi_match(AVLReg, *MRI, m_AllOnes()))
1016 VLMax = true;
1017 }
1018
1019 if (VLMax) {
1020 VLOperand = Register(RISCV::X0);
1021 Opcode = RISCV::PseudoVSETVLIX0;
1022 } else {
1023 Register AVLReg = I.getOperand(2).getReg();
1024 VLOperand = AVLReg;
1025
1026 // Check if AVL is a small constant that can use PseudoVSETIVLI.
1027 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1028 uint64_t AVL = AVLConst->Value.getZExtValue();
1029 if (isUInt<5>(AVL)) {
1030 MachineInstr *PseudoMI =
1031 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1032 TII.get(RISCV::PseudoVSETIVLI), DstReg)
1033 .addImm(AVL)
1034 .addImm(VTypeI);
1035 I.eraseFromParent();
1036 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1037 return true;
1038 }
1039 }
1040 }
1041
1042 MachineInstr *PseudoMI =
1043 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
1044 .addReg(VLOperand)
1045 .addImm(VTypeI);
1046 I.eraseFromParent();
1047 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1048 return true;
1049 }
1050 }
1051}
1052
1053bool RISCVInstructionSelector::selectExtractSubvector(MachineInstr &MI) const {
1054 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR);
1055
1056 Register DstReg = MI.getOperand(0).getReg();
1057 Register SrcReg = MI.getOperand(1).getReg();
1058
1059 LLT DstTy = MRI->getType(DstReg);
1060 LLT SrcTy = MRI->getType(SrcReg);
1061
1062 unsigned Idx = static_cast<unsigned>(MI.getOperand(2).getImm());
1063
1064 MVT DstMVT = getMVTForLLT(DstTy);
1065 MVT SrcMVT = getMVTForLLT(SrcTy);
1066
1067 unsigned SubRegIdx;
1068 std::tie(SubRegIdx, Idx) =
1070 SrcMVT, DstMVT, Idx, &TRI);
1071
1072 if (Idx != 0)
1073 return false;
1074
1075 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(DstMVT);
1076 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1077 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1078 return false;
1079
1080 unsigned SrcRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(SrcMVT);
1081 const TargetRegisterClass *SrcRC = TRI.getRegClass(SrcRegClassID);
1082 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
1083 return false;
1084
1085 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1086 DstReg)
1087 .addReg(SrcReg, {}, SubRegIdx);
1088
1089 MI.eraseFromParent();
1090 return true;
1091}
1092
1093bool RISCVInstructionSelector::selectInsertSubVector(MachineInstr &MI) const {
1094 assert(MI.getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR);
1095
1096 Register DstReg = MI.getOperand(0).getReg();
1097 Register VecReg = MI.getOperand(1).getReg();
1098 Register SubVecReg = MI.getOperand(2).getReg();
1099
1100 LLT VecTy = MRI->getType(VecReg);
1101 LLT SubVecTy = MRI->getType(SubVecReg);
1102
1103 MVT VecMVT = getMVTForLLT(VecTy);
1104 MVT SubVecMVT = getMVTForLLT(SubVecTy);
1105
1106 unsigned Idx = static_cast<unsigned>(MI.getOperand(3).getImm());
1107
1108 unsigned SubRegIdx;
1109 std::tie(SubRegIdx, Idx) =
1111 VecMVT, SubVecMVT, Idx, &TRI);
1112
1113 // If the Idx hasn't been completely eliminated then this is a subvector
1114 // insert which doesn't naturally align to a vector register. These must
1115 // be handled using instructions to manipulate the vector registers.
1116 if (Idx != 0)
1117 return false;
1118
1119 // Constrain dst
1120 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(VecMVT);
1121 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1122 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1123 return false;
1124
1125 // If we haven't set a SubRegIdx, then we must be going between
1126 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy.
1127 if (SubRegIdx == RISCV::NoSubRegister) {
1129 DstRegClassID &&
1130 "Unexpected subvector insert");
1131 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1132 DstReg)
1133 .addReg(SubVecReg);
1134 MI.eraseFromParent();
1135 return true;
1136 }
1137
1138 // Use INSERT_SUBREG to insert the subvector into the vector at the
1139 // appropriate subregister index.
1140 MachineInstr *Ins = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1141 TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1142 .addReg(VecReg)
1143 .addReg(SubVecReg)
1144 .addImm(SubRegIdx);
1145
1146 MI.eraseFromParent();
1148 return true;
1149}
1150
1151bool RISCVInstructionSelector::select(MachineInstr &MI) {
1152 preISelLower(MI);
1153 const unsigned Opc = MI.getOpcode();
1154
1155 if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
1156 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
1157 const Register DefReg = MI.getOperand(0).getReg();
1158 const LLT DefTy = MRI->getType(DefReg);
1159
1160 const RegClassOrRegBank &RegClassOrBank =
1161 MRI->getRegClassOrRegBank(DefReg);
1162
1163 const TargetRegisterClass *DefRC =
1165 if (!DefRC) {
1166 if (!DefTy.isValid()) {
1167 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
1168 return false;
1169 }
1170
1171 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
1172 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB, STI.is64Bit());
1173 if (!DefRC) {
1174 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
1175 return false;
1176 }
1177 }
1178
1179 MI.setDesc(TII.get(TargetOpcode::PHI));
1180 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
1181 }
1182
1183 // Certain non-generic instructions also need some special handling.
1184 if (MI.isCopy())
1185 return selectCopy(MI);
1186
1187 return true;
1188 }
1189
1190 if (selectImpl(MI, *CoverageInfo))
1191 return true;
1192
1193 switch (Opc) {
1194 case TargetOpcode::G_ANYEXT:
1195 case TargetOpcode::G_PTRTOINT:
1196 case TargetOpcode::G_INTTOPTR:
1197 case TargetOpcode::G_TRUNC:
1198 case TargetOpcode::G_FREEZE:
1199 return selectCopy(MI);
1200 case TargetOpcode::G_CONSTANT: {
1201 Register DstReg = MI.getOperand(0).getReg();
1202 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1203
1204 if (!materializeImm(DstReg, Imm, MI))
1205 return false;
1206
1207 MI.eraseFromParent();
1208 return true;
1209 }
1210 case TargetOpcode::G_ZEXT:
1211 case TargetOpcode::G_SEXT: {
1212 bool IsSigned = Opc != TargetOpcode::G_ZEXT;
1213 Register DstReg = MI.getOperand(0).getReg();
1214 Register SrcReg = MI.getOperand(1).getReg();
1215 LLT SrcTy = MRI->getType(SrcReg);
1216 unsigned SrcSize = SrcTy.getSizeInBits();
1217
1218 if (SrcTy.isVector())
1219 return false; // Should be handled by imported patterns.
1220
1221 assert((*RBI.getRegBank(DstReg, *MRI, TRI)).getID() ==
1222 RISCV::GPRBRegBankID &&
1223 "Unexpected ext regbank");
1224
1225 // Use addiw SrcReg, 0 (sext.w) for i32.
1226 if (IsSigned && SrcSize == 32) {
1227 MI.setDesc(TII.get(RISCV::ADDIW));
1228 MI.addOperand(MachineOperand::CreateImm(0));
1230 return true;
1231 }
1232
1233 // Use add.uw SrcReg, X0 (zext.w) for i32 with Zba.
1234 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
1235 MI.setDesc(TII.get(RISCV::ADD_UW));
1236 MI.addOperand(MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false));
1238 return true;
1239 }
1240
1241 // Use sext.h/zext.h for i16 with Zbb.
1242 if (SrcSize == 16 &&
1243 (STI.hasStdExtZbb() || (!IsSigned && STI.hasStdExtZbkb()))) {
1244 MI.setDesc(TII.get(IsSigned ? RISCV::SEXT_H
1245 : STI.isRV64() ? RISCV::ZEXT_H_RV64
1246 : RISCV::ZEXT_H_RV32));
1248 return true;
1249 }
1250
1251 // Fall back to shift pair.
1252 Register ShiftLeftReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1253 MachineInstr *ShiftLeft = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1254 TII.get(RISCV::SLLI), ShiftLeftReg)
1255 .addReg(SrcReg)
1256 .addImm(STI.getXLen() - SrcSize);
1257 constrainSelectedInstRegOperands(*ShiftLeft, TII, TRI, RBI);
1258 MachineInstr *ShiftRight =
1259 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1260 TII.get(IsSigned ? RISCV::SRAI : RISCV::SRLI), DstReg)
1261 .addReg(ShiftLeftReg)
1262 .addImm(STI.getXLen() - SrcSize);
1263 constrainSelectedInstRegOperands(*ShiftRight, TII, TRI, RBI);
1264 MI.eraseFromParent();
1265 return true;
1266 }
1267 case TargetOpcode::G_FCONSTANT: {
1268 // TODO: Use constant pool for complex constants.
1269 Register DstReg = MI.getOperand(0).getReg();
1270 const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
1271 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1272 if (Size == 16 || Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
1273 Register GPRReg;
1274 if (FPimm.isPosZero()) {
1275 GPRReg = RISCV::X0;
1276 } else {
1277 GPRReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1278 APInt Imm = FPimm.bitcastToAPInt();
1279 if (!materializeImm(GPRReg, Imm.getSExtValue(), MI))
1280 return false;
1281 }
1282
1283 unsigned Opcode = Size == 64 ? RISCV::FMV_D_X
1284 : Size == 32 ? RISCV::FMV_W_X
1285 : RISCV::FMV_H_X;
1286 MachineInstr *FMV = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1287 TII.get(Opcode), DstReg)
1288 .addReg(GPRReg);
1290 } else {
1291 // s64 on rv32
1292 assert(Size == 64 && !Subtarget->is64Bit() &&
1293 "Unexpected size or subtarget");
1294
1295 if (FPimm.isPosZero()) {
1296 // Optimize +0.0 to use fcvt.d.w
1297 MachineInstr *FCVT = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1298 TII.get(RISCV::FCVT_D_W), DstReg)
1299 .addReg(RISCV::X0)
1302
1303 MI.eraseFromParent();
1304 return true;
1305 }
1306
1307 // Split into two pieces and build through the stack.
1308 Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1309 Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1310 APInt Imm = FPimm.bitcastToAPInt();
1311 if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
1312 MI))
1313 return false;
1314 if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MI))
1315 return false;
1316 MachineInstr *PairF64 =
1317 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1318 TII.get(RISCV::BuildPairF64Pseudo), DstReg)
1319 .addReg(GPRRegLow)
1320 .addReg(GPRRegHigh);
1321 constrainSelectedInstRegOperands(*PairF64, TII, TRI, RBI);
1322 }
1323
1324 MI.eraseFromParent();
1325 return true;
1326 }
1327 case TargetOpcode::G_GLOBAL_VALUE: {
1328 auto *GV = MI.getOperand(1).getGlobal();
1329 if (GV->isThreadLocal()) {
1330 // TODO: implement this case.
1331 return false;
1332 }
1333
1334 return selectAddr(MI, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1335 }
1336 case TargetOpcode::G_JUMP_TABLE:
1337 case TargetOpcode::G_CONSTANT_POOL:
1338 return selectAddr(MI);
1339 case TargetOpcode::G_BRCOND: {
1340 Register LHS, RHS;
1342 getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
1343
1344 MachineInstr *Bcc = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1345 TII.get(RISCVCC::getBrCond(CC)))
1346 .addReg(LHS)
1347 .addReg(RHS)
1348 .addMBB(MI.getOperand(1).getMBB());
1349 MI.eraseFromParent();
1351 return true;
1352 }
1353 case TargetOpcode::G_BRINDIRECT:
1354 MI.setDesc(TII.get(RISCV::PseudoBRIND));
1355 MI.addOperand(MachineOperand::CreateImm(0));
1357 return true;
1358 case TargetOpcode::G_SELECT:
1359 return selectSelect(MI);
1360 case TargetOpcode::G_FCMP:
1361 return selectFPCompare(MI);
1362 case TargetOpcode::G_FENCE: {
1363 AtomicOrdering FenceOrdering =
1364 static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
1365 SyncScope::ID FenceSSID =
1366 static_cast<SyncScope::ID>(MI.getOperand(1).getImm());
1367 emitFence(FenceOrdering, FenceSSID, MI);
1368 MI.eraseFromParent();
1369 return true;
1370 }
1371 case TargetOpcode::G_IMPLICIT_DEF:
1372 return selectImplicitDef(MI);
1373 case TargetOpcode::G_UNMERGE_VALUES:
1374 return selectUnmergeValues(MI);
1375 case TargetOpcode::G_LOAD:
1376 case TargetOpcode::G_STORE: {
1377 GLoadStore &LdSt = cast<GLoadStore>(MI);
1378 const Register ValReg = LdSt.getReg(0);
1379 const Register PtrReg = LdSt.getPointerReg();
1380 LLT PtrTy = MRI->getType(PtrReg);
1381
1382 const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
1383 if (RB.getID() != RISCV::GPRBRegBankID)
1384 return false;
1385
1386#ifndef NDEBUG
1387 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, *MRI, TRI);
1388 // Check that the pointer register is valid.
1389 assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
1390 "Load/Store pointer operand isn't a GPR");
1391 assert(PtrTy.isPointer() && "Load/Store pointer operand isn't a pointer");
1392#endif
1393
1394 // Can only handle AddressSpace 0.
1395 if (PtrTy.getAddressSpace() != 0)
1396 return false;
1397
1398 unsigned MemSize = LdSt.getMemSizeInBits().getValue();
1399 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
1400
1401 if (isStrongerThanMonotonic(Order)) {
1402 MI.setDesc(TII.get(selectZalasrLoadStoreOp(Opc, MemSize)));
1404 return true;
1405 }
1406
1407 const unsigned NewOpc = selectRegImmLoadStoreOp(MI.getOpcode(), MemSize);
1408 if (NewOpc == MI.getOpcode())
1409 return false;
1410
1411 // Check if we can fold anything into the addressing mode.
1412 auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
1413 if (!AddrModeFns)
1414 return false;
1415
1416 // Folded something. Create a new instruction and return it.
1417 MachineInstrBuilder NewInst =
1418 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(NewOpc));
1419 NewInst.setMIFlags(MI.getFlags());
1420 if (isa<GStore>(MI))
1421 NewInst.addUse(ValReg);
1422 else
1423 NewInst.addDef(ValReg);
1424 NewInst.cloneMemRefs(MI);
1425 for (auto &Fn : *AddrModeFns)
1426 Fn(NewInst);
1427 MI.eraseFromParent();
1428
1429 constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
1430 return true;
1431 }
1432 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1433 return selectIntrinsicWithSideEffects(MI);
1434 case TargetOpcode::G_INTRINSIC:
1435 return selectIntrinsic(MI);
1436 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1437 return selectExtractSubvector(MI);
1438 case TargetOpcode::G_INSERT_SUBVECTOR:
1439 return selectInsertSubVector(MI);
1440 default:
1441 return false;
1442 }
1443}
1444
1445bool RISCVInstructionSelector::selectUnmergeValues(MachineInstr &MI) const {
1446 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1447
1448 if (!Subtarget->hasStdExtZfa())
1449 return false;
1450
1451 // Split F64 Src into two s32 parts
1452 if (MI.getNumOperands() != 3)
1453 return false;
1454 Register Src = MI.getOperand(2).getReg();
1455 Register Lo = MI.getOperand(0).getReg();
1456 Register Hi = MI.getOperand(1).getReg();
1457 if (!isRegInFprb(Src) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
1458 return false;
1459
1460 MachineInstr *ExtractLo = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1461 TII.get(RISCV::FMV_X_W_FPR64), Lo)
1462 .addReg(Src);
1463 constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI);
1464
1465 MachineInstr *ExtractHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1466 TII.get(RISCV::FMVH_X_D), Hi)
1467 .addReg(Src);
1468 constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI);
1469
1470 MI.eraseFromParent();
1471 return true;
1472}
1473
1474bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &Op) {
1475 Register PtrReg = Op.getReg();
1476 assert(MRI->getType(PtrReg).isPointer() && "Operand is not a pointer!");
1477
1478 const LLT sXLen = LLT::scalar(STI.getXLen());
1479 MachineInstr &ParentMI = *Op.getParent();
1480 Register IntReg = MRI->createGenericVirtualRegister(sXLen);
1481 MRI->setRegBank(IntReg, RBI.getRegBank(RISCV::GPRBRegBankID));
1482 MachineInstr *PtrToInt =
1483 BuildMI(*ParentMI.getParent(), ParentMI, ParentMI.getDebugLoc(),
1484 TII.get(TargetOpcode::G_PTRTOINT), IntReg)
1485 .addReg(PtrReg);
1486 Op.setReg(IntReg);
1487 return select(*PtrToInt);
1488}
1489
1490void RISCVInstructionSelector::preISelLower(MachineInstr &MI) {
1491 switch (MI.getOpcode()) {
1492 case TargetOpcode::G_PTR_ADD: {
1493 Register DstReg = MI.getOperand(0).getReg();
1494 const LLT sXLen = LLT::scalar(STI.getXLen());
1495
1496 replacePtrWithInt(MI.getOperand(1));
1497 MI.setDesc(TII.get(TargetOpcode::G_ADD));
1498 MRI->setType(DstReg, sXLen);
1499 break;
1500 }
1501 case TargetOpcode::G_PTRMASK: {
1502 Register DstReg = MI.getOperand(0).getReg();
1503 const LLT sXLen = LLT::scalar(STI.getXLen());
1504 replacePtrWithInt(MI.getOperand(1));
1505 MI.setDesc(TII.get(TargetOpcode::G_AND));
1506 MRI->setType(DstReg, sXLen);
1507 break;
1508 }
1509 }
1510}
1511
1512void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1513 const MachineInstr &MI,
1514 int OpIdx) const {
1515 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1516 "Expected G_CONSTANT");
1517 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1518 MIB.addImm(-CstVal);
1519}
1520
1521void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1522 const MachineInstr &MI,
1523 int OpIdx) const {
1524 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1525 "Expected G_CONSTANT");
1526 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1527 MIB.addImm(STI.getXLen() - CstVal);
1528}
1529
1530void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1531 const MachineInstr &MI,
1532 int OpIdx) const {
1533 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1534 "Expected G_CONSTANT");
1535 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1536 MIB.addImm(32 - CstVal);
1537}
1538
1539void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1540 const MachineInstr &MI,
1541 int OpIdx) const {
1542 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1543 "Expected G_CONSTANT");
1544 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1545 MIB.addImm(CstVal + 1);
1546}
1547
1548void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1549 const MachineInstr &MI,
1550 int OpIdx) const {
1551 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1552 "Expected G_CONSTANT");
1553 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1555}
1556
1557void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1558 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
1559 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1560 "Expected G_CONSTANT");
1561 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1562 MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
1563}
1564
1565void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1566 const MachineInstr &MI,
1567 int OpIdx) const {
1568 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1569 "Expected G_CONSTANT");
1570 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1571 int64_t Adj = Imm < 0 ? -2048 : 2047;
1572 MIB.addImm(Imm - Adj);
1573}
1574
1575void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1576 const MachineInstr &MI,
1577 int OpIdx) const {
1578 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1579 "Expected G_CONSTANT");
1580 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1581 MIB.addImm(Imm);
1582}
1583
1584bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
1585 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
1586}
1587
1588bool RISCVInstructionSelector::isRegInFprb(Register Reg) const {
1589 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID;
1590}
1591
1592bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
1593 MachineOperand Dst = MI.getOperand(0);
1594 Register DstReg = MI.getOperand(0).getReg();
1595
1596 if (DstReg.isPhysical())
1597 return true;
1598
1599 const TargetRegisterClass *DstRC =
1600 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
1601
1602 assert(DstRC &&
1603 "Register class not available for LLT, register bank combination");
1604
1605 // No need to constrain SrcReg. It will get constrained when
1606 // we hit another of its uses or its defs.
1607 // Copies do not have constraints.
1608 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1609 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1610 << " operand\n");
1611 return false;
1612 }
1613
1614 MI.setDesc(TII.get(RISCV::COPY));
1615 return true;
1616}
1617
1618bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI) const {
1619 assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1620
1621 const Register DstReg = MI.getOperand(0).getReg();
1622 const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
1623 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI), STI.is64Bit());
1624
1625 assert(DstRC &&
1626 "Register class not available for LLT, register bank combination");
1627
1628 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1629 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1630 << " operand\n");
1631 }
1632 MI.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1633 return true;
1634}
1635
1636bool RISCVInstructionSelector::materializeImm(Register DstReg, int64_t Imm,
1637 MachineInstr &MI) const {
1638 MachineBasicBlock &MBB = *MI.getParent();
1639 DebugLoc DL = MI.getDebugLoc();
1640
1641 if (Imm == 0) {
1642 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::COPY), DstReg).addReg(RISCV::X0);
1643 RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, *MRI);
1644 return true;
1645 }
1646
1648 unsigned NumInsts = Seq.size();
1649 Register SrcReg = RISCV::X0;
1650
1651 for (unsigned i = 0; i < NumInsts; i++) {
1652 Register TmpReg = i < NumInsts - 1
1653 ? MRI->createVirtualRegister(&RISCV::GPRRegClass)
1654 : DstReg;
1655 const RISCVMatInt::Inst &I = Seq[i];
1656 MachineInstr *Result;
1657
1658 switch (I.getOpndKind()) {
1659 case RISCVMatInt::Imm:
1660 // clang-format off
1661 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1662 .addImm(I.getImm());
1663 // clang-format on
1664 break;
1665 case RISCVMatInt::RegX0:
1666 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1667 .addReg(SrcReg)
1668 .addReg(RISCV::X0);
1669 break;
1671 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1672 .addReg(SrcReg)
1673 .addReg(SrcReg);
1674 break;
1676 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1677 .addReg(SrcReg)
1678 .addImm(I.getImm());
1679 break;
1680 }
1681
1683
1684 SrcReg = TmpReg;
1685 }
1686
1687 return true;
1688}
1689
1690bool RISCVInstructionSelector::selectAddr(MachineInstr &MI, bool IsLocal,
1691 bool IsExternWeak) const {
1692 assert((MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1693 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1694 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1695 "Unexpected opcode");
1696
1697 const MachineOperand &DispMO = MI.getOperand(1);
1698
1699 Register DefReg = MI.getOperand(0).getReg();
1700 const LLT DefTy = MRI->getType(DefReg);
1701
1702 // When HWASAN is used and tagging of global variables is enabled
1703 // they should be accessed via the GOT, since the tagged address of a global
1704 // is incompatible with existing code models. This also applies to non-pic
1705 // mode.
1706 if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
1707 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1708 // Use PC-relative addressing to access the symbol. This generates the
1709 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
1710 // %pcrel_lo(auipc)).
1711 MI.setDesc(TII.get(RISCV::PseudoLLA));
1713 return true;
1714 }
1715
1716 // Use PC-relative addressing to access the GOT for this symbol, then
1717 // load the address from the GOT. This generates the pattern (PseudoLGA
1718 // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
1719 // %pcrel_lo(auipc))).
1720 MachineFunction &MF = *MI.getParent()->getParent();
1721 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1725 DefTy, Align(DefTy.getSizeInBits() / 8));
1726
1727 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1728 TII.get(RISCV::PseudoLGA), DefReg)
1729 .addDisp(DispMO, 0)
1730 .addMemOperand(MemOp);
1731
1733
1734 MI.eraseFromParent();
1735 return true;
1736 }
1737
1738 switch (TM.getCodeModel()) {
1739 default: {
1741 "Unsupported code model for lowering", MI);
1742 return false;
1743 }
1744 case CodeModel::Small: {
1745 // Must lie within a single 2 GiB address range and must lie between
1746 // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
1747 // (lui %hi(sym)) %lo(sym)).
1748 Register AddrHiDest = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1749 MachineInstr *AddrHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1750 TII.get(RISCV::LUI), AddrHiDest)
1751 .addDisp(DispMO, 0, RISCVII::MO_HI);
1752
1754
1755 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1756 TII.get(RISCV::ADDI), DefReg)
1757 .addReg(AddrHiDest)
1758 .addDisp(DispMO, 0, RISCVII::MO_LO);
1759
1761
1762 MI.eraseFromParent();
1763 return true;
1764 }
1765 case CodeModel::Medium:
1766 // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
1767 // relocation needs to reference a label that points to the auipc
1768 // instruction itself, not the global. This cannot be done inside the
1769 // instruction selector.
1770 if (IsExternWeak) {
1771 // An extern weak symbol may be undefined, i.e. have value 0, which may
1772 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
1773 // symbol. This generates the pattern (PseudoLGA sym), which expands to
1774 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
1775 MachineFunction &MF = *MI.getParent()->getParent();
1776 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1780 DefTy, Align(DefTy.getSizeInBits() / 8));
1781
1782 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1783 TII.get(RISCV::PseudoLGA), DefReg)
1784 .addDisp(DispMO, 0)
1785 .addMemOperand(MemOp);
1786
1788
1789 MI.eraseFromParent();
1790 return true;
1791 }
1792
1793 // Generate a sequence for accessing addresses within any 2GiB range
1794 // within the address space. This generates the pattern (PseudoLLA sym),
1795 // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
1796 MI.setDesc(TII.get(RISCV::PseudoLLA));
1798 return true;
1799 }
1800
1801 return false;
1802}
1803
1804bool RISCVInstructionSelector::selectSelect(MachineInstr &MI) const {
1805 auto &SelectMI = cast<GSelect>(MI);
1806
1807 Register LHS, RHS;
1809 getOperandsForBranch(SelectMI.getCondReg(), CC, LHS, RHS, *MRI);
1810
1811 Register DstReg = SelectMI.getReg(0);
1812
1813 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1814 if (RBI.getRegBank(DstReg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
1815 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1816 Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1817 : RISCV::Select_FPR64_Using_CC_GPR;
1818 }
1819
1820 MachineInstr *Result =
1821 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(Opc))
1822 .addDef(DstReg)
1823 .addReg(LHS)
1824 .addReg(RHS)
1825 .addImm(CC)
1826 .addReg(SelectMI.getTrueReg())
1827 .addReg(SelectMI.getFalseReg());
1828 MI.eraseFromParent();
1830 return true;
1831}
1832
1833// Convert an FCMP predicate to one of the supported F or D instructions.
1834static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
1835 assert((Size == 16 || Size == 32 || Size == 64) && "Unsupported size");
1836 switch (Pred) {
1837 default:
1838 llvm_unreachable("Unsupported predicate");
1839 case CmpInst::FCMP_OLT:
1840 return Size == 16 ? RISCV::FLT_H : Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1841 case CmpInst::FCMP_OLE:
1842 return Size == 16 ? RISCV::FLE_H : Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1843 case CmpInst::FCMP_OEQ:
1844 return Size == 16 ? RISCV::FEQ_H : Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1845 }
1846}
1847
1848// Try legalizing an FCMP by swapping or inverting the predicate to one that
1849// is supported.
1851 CmpInst::Predicate &Pred, bool &NeedInvert) {
1852 auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
1853 return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
1854 Pred == CmpInst::FCMP_OEQ;
1855 };
1856
1857 assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
1858
1860 if (isLegalFCmpPredicate(InvPred)) {
1861 Pred = InvPred;
1862 std::swap(LHS, RHS);
1863 return true;
1864 }
1865
1866 InvPred = CmpInst::getInversePredicate(Pred);
1867 NeedInvert = true;
1868 if (isLegalFCmpPredicate(InvPred)) {
1869 Pred = InvPred;
1870 return true;
1871 }
1872 InvPred = CmpInst::getSwappedPredicate(InvPred);
1873 if (isLegalFCmpPredicate(InvPred)) {
1874 Pred = InvPred;
1875 std::swap(LHS, RHS);
1876 return true;
1877 }
1878
1879 return false;
1880}
1881
1882// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
1883// the result in DstReg.
1884// FIXME: Maybe we should expand this earlier.
1885bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI) const {
1886 auto &CmpMI = cast<GFCmp>(MI);
1887 CmpInst::Predicate Pred = CmpMI.getCond();
1888
1889 Register DstReg = CmpMI.getReg(0);
1890 Register LHS = CmpMI.getLHSReg();
1891 Register RHS = CmpMI.getRHSReg();
1892
1893 unsigned Size = MRI->getType(LHS).getSizeInBits();
1894 assert((Size == 16 || Size == 32 || Size == 64) && "Unexpected size");
1895
1896 Register TmpReg = DstReg;
1897
1898 bool NeedInvert = false;
1899 // First try swapping operands or inverting.
1900 if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
1901 if (NeedInvert)
1902 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1903 MachineInstr *Cmp = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1904 TII.get(getFCmpOpcode(Pred, Size)), TmpReg)
1905 .addReg(LHS)
1906 .addReg(RHS);
1908 } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
1909 // fcmp one LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
1910 NeedInvert = Pred == CmpInst::FCMP_UEQ;
1911 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1912 MachineInstr *Cmp1 =
1913 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1914 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp1Reg)
1915 .addReg(LHS)
1916 .addReg(RHS);
1918 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1919 MachineInstr *Cmp2 =
1920 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1921 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp2Reg)
1922 .addReg(RHS)
1923 .addReg(LHS);
1925 if (NeedInvert)
1926 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1927 MachineInstr *Or = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1928 TII.get(RISCV::OR), TmpReg)
1929 .addReg(Cmp1Reg)
1930 .addReg(Cmp2Reg);
1932 } else if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
1933 // fcmp ord LHS, RHS => (AND (FEQ LHS, LHS), (FEQ RHS, RHS))
1934 // If LHS and RHS are the same, a single FEQ suffices.
1935 NeedInvert = Pred == CmpInst::FCMP_UNO;
1936 if (NeedInvert)
1937 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1938 if (LHS == RHS) {
1939 MachineInstr *Cmp =
1940 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1941 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), TmpReg)
1942 .addReg(LHS)
1943 .addReg(LHS);
1945 } else {
1946 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1947 MachineInstr *Cmp1 =
1948 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1949 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp1Reg)
1950 .addReg(LHS)
1951 .addReg(LHS);
1953 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1954 MachineInstr *Cmp2 =
1955 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1956 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp2Reg)
1957 .addReg(RHS)
1958 .addReg(RHS);
1960 MachineInstr *And = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1961 TII.get(RISCV::AND), TmpReg)
1962 .addReg(Cmp1Reg)
1963 .addReg(Cmp2Reg);
1965 }
1966 } else
1967 llvm_unreachable("Unhandled predicate");
1968
1969 // Emit an XORI to invert the result if needed.
1970 if (NeedInvert) {
1971 MachineInstr *Xor = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1972 TII.get(RISCV::XORI), DstReg)
1973 .addReg(TmpReg)
1974 .addImm(1);
1976 }
1977
1978 MI.eraseFromParent();
1979 return true;
1980}
1981
1982void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
1983 SyncScope::ID FenceSSID,
1984 MachineInstr &MI) const {
1985 MachineBasicBlock &MBB = *MI.getParent();
1986 DebugLoc DL = MI.getDebugLoc();
1987
1988 if (STI.hasStdExtZtso()) {
1989 // The only fence that needs an instruction is a sequentially-consistent
1990 // cross-thread fence.
1991 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1992 FenceSSID == SyncScope::System) {
1993 // fence rw, rw
1994 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE))
1997 return;
1998 }
1999
2000 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
2001 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2002 return;
2003 }
2004
2005 // singlethread fences only synchronize with signal handlers on the same
2006 // thread and thus only need to preserve instruction order, not actually
2007 // enforce memory ordering.
2008 if (FenceSSID == SyncScope::SingleThread) {
2009 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2010 return;
2011 }
2012
2013 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
2014 // Manual: Volume I.
2015 unsigned Pred, Succ;
2016 switch (FenceOrdering) {
2017 default:
2018 llvm_unreachable("Unexpected ordering");
2019 case AtomicOrdering::AcquireRelease:
2020 // fence acq_rel -> fence.tso
2021 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE_TSO));
2022 return;
2023 case AtomicOrdering::Acquire:
2024 // fence acquire -> fence r, rw
2025 Pred = RISCVFenceField::R;
2027 break;
2028 case AtomicOrdering::Release:
2029 // fence release -> fence rw, w
2031 Succ = RISCVFenceField::W;
2032 break;
2033 case AtomicOrdering::SequentiallyConsistent:
2034 // fence seq_cst -> fence rw, rw
2037 break;
2038 }
2039 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE)).addImm(Pred).addImm(Succ);
2040}
2041
2042namespace llvm {
2043InstructionSelector *
2045 const RISCVSubtarget &Subtarget,
2046 const RISCVRegisterBankInfo &RBI) {
2047 return new RISCVInstructionSelector(TM, Subtarget, RBI);
2048}
2049} // end namespace llvm
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static bool hasAllWUsers(const MachineInstr &OrigMI, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI)
static bool hasAllNBitUsers(const MachineInstr &OrigMI, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI, unsigned OrigBits)
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
static StringRef getName(Value *V)
static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize)
Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the G...
static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize)
Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the G...
static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size)
static bool legalizeFCmpPredicate(Register &LHS, Register &RHS, CmpInst::Predicate &Pred, bool &NeedInvert)
static void getOperandsForBranch(Register CondReg, RISCVCC::CondCode &CC, Register &LHS, Register &RHS, MachineRegisterInfo &MRI)
const SmallVectorImpl< MachineOperand > & Cond
This file declares the targeting of the RegisterBankInfo class for RISC-V.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
APInt bitcastToAPInt() const
Definition APFloat.h:1467
bool isPosZero() const
Definition APFloat.h:1586
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1116
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
Definition APInt.h:283
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition Constants.h:174
This is an important base class in LLVM.
Definition Constant.h:43
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSizeInBits() const
Returns the size in bits of the memory access.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr unsigned getAddressSpace() const
TypeSize getValue() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDisp(const MachineOperand &Disp, int64_t off, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setRegBank(Register Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Analysis providing profile information.
This class provides the information for the target register banks.
unsigned getXLen() const
std::optional< unsigned > getRealVLen() const
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
static unsigned getRegClassIDForVecVT(MVT VT)
static RISCVVType::VLMUL getLMUL(MVT VT)
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
bool isPositionIndependent() const
CodeModel::Model getCodeModel() const
Returns the code model.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
operand_type_match m_Pred()
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
SpecificImmMatch m_SpecificImm(int64_t RequestedValue)
Matches an immediate operand equal to RequestedValue.
AllOnesConstantMatch m_AllOnes()
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
SrcImmOp_match< SrcTy, AnyImmMatch, TargetOpcode::G_SEXT_INREG > m_GSExtInReg(const SrcTy &Src)
Matches a G_SEXT_INREG, binding its source and immediate width.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
SmallVector< Inst, 8 > InstSeq
Definition RISCVMatInt.h:43
static unsigned decodeVSEW(unsigned VSEW)
LLVM_ABI unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
static constexpr int64_t VLMaxSentinel
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition LLVMContext.h:55
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Known
Known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:159
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
InstructionSelector * createRISCVInstructionSelector(const RISCVTargetMachine &TM, const RISCVSubtarget &Subtarget, const RISCVRegisterBankInfo &RBI)
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition Utils.cpp:317
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
Definition Utils.cpp:261
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition MathExtras.h:95
@ Or
Bitwise or logical OR of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define MORE()
Definition regcomp.c:246
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.