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 MachineInstr *RootDef = MRI->getVRegDef(RootReg);
361
362 if (RootDef->getOpcode() == TargetOpcode::G_SEXT_INREG &&
363 RootDef->getOperand(2).getImm() == Bits) {
364 return {
365 {[=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); }}};
366 }
367
368 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
369 if ((Size - VT->computeNumSignBits(RootReg)) < Bits)
370 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
371
372 return std::nullopt;
373}
374
375InstructionSelector::ComplexRendererFns
376RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
377 unsigned Bits) const {
378 if (!Root.isReg())
379 return std::nullopt;
380 Register RootReg = Root.getReg();
381
382 Register RegX;
383 uint64_t Mask = maskTrailingOnes<uint64_t>(Bits);
384 if (mi_match(RootReg, *MRI, m_GAnd(m_Reg(RegX), m_SpecificICst(Mask)))) {
385 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
386 }
387
388 if (mi_match(RootReg, *MRI, m_GZExt(m_Reg(RegX))) &&
389 MRI->getType(RegX).getScalarSizeInBits() == Bits)
390 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
391
392 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
393 if (VT->maskedValueIsZero(RootReg, APInt::getBitsSetFrom(Size, Bits)))
394 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
395
396 return std::nullopt;
397}
398
399InstructionSelector::ComplexRendererFns
400RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
401 unsigned ShAmt) const {
402 using namespace llvm::MIPatternMatch;
403
404 if (!Root.isReg())
405 return std::nullopt;
406 Register RootReg = Root.getReg();
407
408 const unsigned XLen = STI.getXLen();
409 APInt Mask, C2;
410 Register RegY;
411 std::optional<bool> LeftShift;
412 // (and (shl y, c2), mask)
413 if (mi_match(RootReg, *MRI,
414 m_GAnd(m_GShl(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
415 LeftShift = true;
416 // (and (lshr y, c2), mask)
417 else if (mi_match(RootReg, *MRI,
418 m_GAnd(m_GLShr(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
419 LeftShift = false;
420
421 if (LeftShift.has_value()) {
422 if (*LeftShift)
424 else
426
427 if (Mask.isShiftedMask()) {
428 unsigned Leading = XLen - Mask.getActiveBits();
429 unsigned Trailing = Mask.countr_zero();
430 // Given (and (shl y, c2), mask) in which mask has no leading zeros and
431 // c3 trailing zeros. We can use an SRLI by c3 - c2 followed by a SHXADD.
432 if (*LeftShift && Leading == 0 && C2.ult(Trailing) && Trailing == ShAmt) {
433 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
434 return {{[=](MachineInstrBuilder &MIB) {
435 MachineIRBuilder(*MIB.getInstr())
436 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
437 .addImm(Trailing - C2.getZExtValue());
438 MIB.addReg(DstReg);
439 }}};
440 }
441
442 // Given (and (lshr y, c2), mask) in which mask has c2 leading zeros and
443 // c3 trailing zeros. We can use an SRLI by c2 + c3 followed by a SHXADD.
444 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
445 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
446 return {{[=](MachineInstrBuilder &MIB) {
447 MachineIRBuilder(*MIB.getInstr())
448 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
449 .addImm(Leading + Trailing);
450 MIB.addReg(DstReg);
451 }}};
452 }
453 }
454 }
455
456 LeftShift.reset();
457
458 // (shl (and y, mask), c2)
459 if (mi_match(RootReg, *MRI,
460 m_GShl(m_OneNonDBGUse(m_GAnd(m_Reg(RegY), m_ICst(Mask))),
461 m_ICst(C2))))
462 LeftShift = true;
463 // (lshr (and y, mask), c2)
464 else if (mi_match(RootReg, *MRI,
466 m_ICst(C2))))
467 LeftShift = false;
468
469 if (LeftShift.has_value() && Mask.isShiftedMask()) {
470 unsigned Leading = XLen - Mask.getActiveBits();
471 unsigned Trailing = Mask.countr_zero();
472
473 // Given (shl (and y, mask), c2) in which mask has 32 leading zeros and
474 // c3 trailing zeros. If c1 + c3 == ShAmt, we can emit SRLIW + SHXADD.
475 bool Cond = *LeftShift && Leading == 32 && Trailing > 0 &&
476 (Trailing + C2.getZExtValue()) == ShAmt;
477 if (!Cond)
478 // Given (lshr (and y, mask), c2) in which mask has 32 leading zeros and
479 // c3 trailing zeros. If c3 - c1 == ShAmt, we can emit SRLIW + SHXADD.
480 Cond = !*LeftShift && Leading == 32 && C2.ult(Trailing) &&
481 (Trailing - C2.getZExtValue()) == ShAmt;
482
483 if (Cond) {
484 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
485 return {{[=](MachineInstrBuilder &MIB) {
486 MachineIRBuilder(*MIB.getInstr())
487 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
488 .addImm(Trailing);
489 MIB.addReg(DstReg);
490 }}};
491 }
492 }
493
494 return std::nullopt;
495}
496
497InstructionSelector::ComplexRendererFns
498RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
499 unsigned ShAmt) const {
500 using namespace llvm::MIPatternMatch;
501
502 if (!Root.isReg())
503 return std::nullopt;
504 Register RootReg = Root.getReg();
505
506 // Given (and (shl x, c2), mask) in which mask is a shifted mask with
507 // 32 - ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
508 // c2 - ShAmt followed by SHXADD_UW with ShAmt for x amount.
509 APInt Mask, C2;
510 Register RegX;
511 if (mi_match(
512 RootReg, *MRI,
514 m_ICst(Mask))))) {
516
517 if (Mask.isShiftedMask()) {
518 unsigned Leading = Mask.countl_zero();
519 unsigned Trailing = Mask.countr_zero();
520 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
521 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
522 return {{[=](MachineInstrBuilder &MIB) {
523 MachineIRBuilder(*MIB.getInstr())
524 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
525 .addImm(C2.getZExtValue() - ShAmt);
526 MIB.addReg(DstReg);
527 }}};
528 }
529 }
530 }
531
532 return std::nullopt;
533}
534
535InstructionSelector::ComplexRendererFns
536RISCVInstructionSelector::renderVLOp(MachineOperand &Root) const {
537 assert(Root.isReg() && "Expected operand to be a Register");
538 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
539
540 if (RootDef->getOpcode() == TargetOpcode::G_CONSTANT) {
541 auto C = RootDef->getOperand(1).getCImm();
542 if (C->getValue().isAllOnes())
543 // If the operand is a G_CONSTANT with value of all ones it is larger than
544 // VLMAX. We convert it to an immediate with value VLMaxSentinel. This is
545 // recognized specially by the vsetvli insertion pass.
546 return {{[=](MachineInstrBuilder &MIB) {
547 MIB.addImm(RISCV::VLMaxSentinel);
548 }}};
549
550 if (isUInt<5>(C->getZExtValue())) {
551 uint64_t ZExtC = C->getZExtValue();
552 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
553 }
554 }
555 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); }}};
556}
557
558InstructionSelector::ComplexRendererFns
559RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
560 if (!Root.isReg())
561 return std::nullopt;
562
563 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
564 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
565 return {{
566 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
567 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
568 }};
569 }
570
571 if (isBaseWithConstantOffset(Root, *MRI)) {
572 MachineOperand &LHS = RootDef->getOperand(1);
573 MachineOperand &RHS = RootDef->getOperand(2);
574 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
575 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
576
577 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
578 if (isInt<12>(RHSC)) {
579 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
580 return {{
581 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
582 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
583 }};
584
585 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
586 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
587 }
588 }
589
590 // TODO: Need to get the immediate from a G_PTR_ADD. Should this be done in
591 // the combiner?
592 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
593 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
594}
595
596/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
597/// CC Must be an ICMP Predicate.
598static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
599 switch (CC) {
600 default:
601 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
602 case CmpInst::Predicate::ICMP_EQ:
603 return RISCVCC::COND_EQ;
604 case CmpInst::Predicate::ICMP_NE:
605 return RISCVCC::COND_NE;
606 case CmpInst::Predicate::ICMP_ULT:
607 return RISCVCC::COND_LTU;
608 case CmpInst::Predicate::ICMP_SLT:
609 return RISCVCC::COND_LT;
610 case CmpInst::Predicate::ICMP_UGE:
611 return RISCVCC::COND_GEU;
612 case CmpInst::Predicate::ICMP_SGE:
613 return RISCVCC::COND_GE;
614 }
615}
616
619 MachineRegisterInfo &MRI) {
620 // Try to fold an ICmp. If that fails, use a NE compare with X0.
622 if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
623 LHS = CondReg;
624 RHS = RISCV::X0;
625 CC = RISCVCC::COND_NE;
626 return;
627 }
628
629 // We found an ICmp, do some canonicalization.
630
631 // Adjust comparisons to use comparison with 0 if possible.
632 if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
633 switch (Pred) {
635 // Convert X > -1 to X >= 0
636 if (*Constant == -1) {
637 CC = RISCVCC::COND_GE;
638 RHS = RISCV::X0;
639 return;
640 }
641 break;
643 // Convert X < 1 to 0 >= X
644 if (*Constant == 1) {
645 CC = RISCVCC::COND_GE;
646 RHS = LHS;
647 LHS = RISCV::X0;
648 return;
649 }
650 break;
651 default:
652 break;
653 }
654 }
655
656 switch (Pred) {
657 default:
658 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
665 // These CCs are supported directly by RISC-V branches.
666 break;
671 // These CCs are not supported directly by RISC-V branches, but changing the
672 // direction of the CC and swapping LHS and RHS are.
673 Pred = CmpInst::getSwappedPredicate(Pred);
674 std::swap(LHS, RHS);
675 break;
676 }
677
678 CC = getRISCVCCFromICmp(Pred);
679}
680
681/// Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation
682/// \p GenericOpc, appropriate for the GPR register bank and of memory access
683/// size \p OpSize.
684static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
685 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
686 switch (OpSize) {
687 default:
688 llvm_unreachable("Unexpected memory size");
689 case 8:
690 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
691 case 16:
692 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
693 case 32:
694 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
695 case 64:
696 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
697 }
698}
699
700/// Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation
701/// \p GenericOpc, appropriate for the GPR register bank and of memory access
702/// size \p OpSize. \returns \p GenericOpc if the combination is unsupported.
703static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
704 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
705 switch (OpSize) {
706 case 8:
707 // Prefer unsigned due to no c.lb in Zcb.
708 return IsStore ? RISCV::SB : RISCV::LBU;
709 case 16:
710 return IsStore ? RISCV::SH : RISCV::LH;
711 case 32:
712 return IsStore ? RISCV::SW : RISCV::LW;
713 case 64:
714 return IsStore ? RISCV::SD : RISCV::LD;
715 }
716
717 return GenericOpc;
718}
719
720void RISCVInstructionSelector::addVectorLoadStoreOperands(
721 MachineInstr &I, SmallVectorImpl<Register> &SrcOps, unsigned &CurOp,
722 bool IsMasked, bool IsStridedOrIndexed, LLT *IndexVT) const {
723 // Base Pointer
724 auto PtrReg = I.getOperand(CurOp++).getReg();
725 SrcOps.push_back(PtrReg);
726
727 // Stride or Index
728 if (IsStridedOrIndexed) {
729 auto StrideReg = I.getOperand(CurOp++).getReg();
730 SrcOps.push_back(StrideReg);
731 if (IndexVT)
732 *IndexVT = MRI->getType(StrideReg);
733 }
734
735 // Mask
736 if (IsMasked) {
737 auto MaskReg = I.getOperand(CurOp++).getReg();
738 SrcOps.push_back(MaskReg);
739 }
740}
741
742bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
743 MachineInstr &I) const {
744 // Find the intrinsic ID.
745 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
746 // Select the instruction.
747 switch (IntrinID) {
748 default:
749 return false;
750 case Intrinsic::riscv_vlm:
751 case Intrinsic::riscv_vle:
752 case Intrinsic::riscv_vle_mask:
753 case Intrinsic::riscv_vlse:
754 case Intrinsic::riscv_vlse_mask: {
755 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
756 IntrinID == Intrinsic::riscv_vlse_mask;
757 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
758 IntrinID == Intrinsic::riscv_vlse_mask;
759 LLT VT = MRI->getType(I.getOperand(0).getReg());
760 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
761
762 // Result vector
763 const Register DstReg = I.getOperand(0).getReg();
764
765 // Sources
766 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
767 unsigned CurOp = 2;
768 SmallVector<Register, 4> SrcOps; // Source registers.
769
770 // Passthru
771 if (HasPassthruOperand) {
772 auto PassthruReg = I.getOperand(CurOp++).getReg();
773 SrcOps.push_back(PassthruReg);
774 } else {
775 SrcOps.push_back(Register(RISCV::NoRegister));
776 }
777
778 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
779
781 const RISCV::VLEPseudo *P =
782 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
783 static_cast<unsigned>(LMUL));
784
785 MachineInstrBuilder PseudoMI =
786 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
787 for (Register Reg : SrcOps)
788 PseudoMI.addReg(Reg);
789
790 // Select VL
791 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
792 for (auto &RenderFn : *VLOpFn)
793 RenderFn(PseudoMI);
794
795 // SEW
796 PseudoMI.addImm(Log2SEW);
797
798 // Policy
799 uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
800 if (IsMasked)
801 Policy = I.getOperand(CurOp++).getImm();
802 PseudoMI.addImm(Policy);
803
804 // Memref
805 PseudoMI.cloneMemRefs(I);
806
807 I.eraseFromParent();
808 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
809 return true;
810 }
811 case Intrinsic::riscv_vloxei:
812 case Intrinsic::riscv_vloxei_mask:
813 case Intrinsic::riscv_vluxei:
814 case Intrinsic::riscv_vluxei_mask: {
815 bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
816 IntrinID == Intrinsic::riscv_vluxei_mask;
817 bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
818 IntrinID == Intrinsic::riscv_vloxei_mask;
819 LLT VT = MRI->getType(I.getOperand(0).getReg());
820 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
821
822 // Result vector
823 const Register DstReg = I.getOperand(0).getReg();
824
825 // Sources
826 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
827 unsigned CurOp = 2;
828 SmallVector<Register, 4> SrcOps; // Source registers.
829
830 // Passthru
831 if (HasPassthruOperand) {
832 auto PassthruReg = I.getOperand(CurOp++).getReg();
833 SrcOps.push_back(PassthruReg);
834 } else {
835 // Use NoRegister if there is no specified passthru.
836 SrcOps.push_back(Register());
837 }
838 LLT IndexVT;
839 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
840
842 RISCVVType::VLMUL IndexLMUL =
844 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
845 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
846 reportFatalUsageError("The V extension does not support EEW=64 for index "
847 "values when XLEN=32");
848 }
849 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
850 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
851 static_cast<unsigned>(IndexLMUL));
852
853 MachineInstrBuilder PseudoMI =
854 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
855 for (Register Reg : SrcOps)
856 PseudoMI.addReg(Reg);
857
858 // Select VL
859 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
860 for (auto &RenderFn : *VLOpFn)
861 RenderFn(PseudoMI);
862
863 // SEW
864 PseudoMI.addImm(Log2SEW);
865
866 // Policy
867 uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
868 if (IsMasked)
869 Policy = I.getOperand(CurOp++).getImm();
870 PseudoMI.addImm(Policy);
871
872 // Memref
873 PseudoMI.cloneMemRefs(I);
874
875 I.eraseFromParent();
876 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
877 return true;
878 }
879 case Intrinsic::riscv_vsm:
880 case Intrinsic::riscv_vse:
881 case Intrinsic::riscv_vse_mask:
882 case Intrinsic::riscv_vsse:
883 case Intrinsic::riscv_vsse_mask: {
884 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
885 IntrinID == Intrinsic::riscv_vsse_mask;
886 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
887 IntrinID == Intrinsic::riscv_vsse_mask;
888 LLT VT = MRI->getType(I.getOperand(1).getReg());
889 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
890
891 // Sources
892 unsigned CurOp = 1;
893 SmallVector<Register, 4> SrcOps; // Source registers.
894
895 // Store value
896 auto PassthruReg = I.getOperand(CurOp++).getReg();
897 SrcOps.push_back(PassthruReg);
898
899 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
900
902 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
903 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
904
905 MachineInstrBuilder PseudoMI =
906 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
907 for (Register Reg : SrcOps)
908 PseudoMI.addReg(Reg);
909
910 // Select VL
911 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
912 for (auto &RenderFn : *VLOpFn)
913 RenderFn(PseudoMI);
914
915 // SEW
916 PseudoMI.addImm(Log2SEW);
917
918 // Memref
919 PseudoMI.cloneMemRefs(I);
920
921 I.eraseFromParent();
922 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
923 return true;
924 }
925 case Intrinsic::riscv_vsoxei:
926 case Intrinsic::riscv_vsoxei_mask:
927 case Intrinsic::riscv_vsuxei:
928 case Intrinsic::riscv_vsuxei_mask: {
929 bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
930 IntrinID == Intrinsic::riscv_vsuxei_mask;
931 bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
932 IntrinID == Intrinsic::riscv_vsoxei_mask;
933 LLT VT = MRI->getType(I.getOperand(1).getReg());
934 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
935
936 // Sources
937 unsigned CurOp = 1;
938 SmallVector<Register, 4> SrcOps; // Source registers.
939
940 // Store value
941 auto PassthruReg = I.getOperand(CurOp++).getReg();
942 SrcOps.push_back(PassthruReg);
943
944 LLT IndexVT;
945 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
946
948 RISCVVType::VLMUL IndexLMUL =
950 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
951 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
952 reportFatalUsageError("The V extension does not support EEW=64 for index "
953 "values when XLEN=32");
954 }
955 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
956 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
957 static_cast<unsigned>(IndexLMUL));
958
959 MachineInstrBuilder PseudoMI =
960 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
961 for (Register Reg : SrcOps)
962 PseudoMI.addReg(Reg);
963
964 // Select VL
965 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
966 for (auto &RenderFn : *VLOpFn)
967 RenderFn(PseudoMI);
968
969 // SEW
970 PseudoMI.addImm(Log2SEW);
971
972 // Memref
973 PseudoMI.cloneMemRefs(I);
974
975 I.eraseFromParent();
976 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
977 return true;
978 }
979 }
980}
981
982bool RISCVInstructionSelector::selectIntrinsic(MachineInstr &I) const {
983 // Find the intrinsic ID.
984 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
985 // Select the instruction.
986 switch (IntrinID) {
987 default:
988 return false;
989 case Intrinsic::riscv_vsetvli:
990 case Intrinsic::riscv_vsetvlimax: {
991
992 bool VLMax = IntrinID == Intrinsic::riscv_vsetvlimax;
993
994 unsigned Offset = VLMax ? 2 : 3;
995 unsigned SEW = RISCVVType::decodeVSEW(I.getOperand(Offset).getImm() & 0x7);
996 RISCVVType::VLMUL VLMul =
997 static_cast<RISCVVType::VLMUL>(I.getOperand(Offset + 1).getImm() & 0x7);
998
999 unsigned VTypeI = RISCVVType::encodeVTYPE(VLMul, SEW, /*TailAgnostic*/ true,
1000 /*MaskAgnostic*/ true);
1001
1002 Register DstReg = I.getOperand(0).getReg();
1003
1004 Register VLOperand;
1005 unsigned Opcode = RISCV::PseudoVSETVLI;
1006
1007 // Check if AVL is a constant that equals VLMAX.
1008 if (!VLMax) {
1009 Register AVLReg = I.getOperand(2).getReg();
1010 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1011 uint64_t AVL = AVLConst->Value.getZExtValue();
1012 if (auto VLEN = Subtarget->getRealVLen()) {
1013 if (*VLEN / RISCVVType::getSEWLMULRatio(SEW, VLMul) == AVL)
1014 VLMax = true;
1015 }
1016 }
1017
1018 MachineInstr *AVLDef = MRI->getVRegDef(AVLReg);
1019 if (AVLDef && AVLDef->getOpcode() == TargetOpcode::G_CONSTANT) {
1020 const auto *C = AVLDef->getOperand(1).getCImm();
1021 if (C->getValue().isAllOnes())
1022 VLMax = true;
1023 }
1024 }
1025
1026 if (VLMax) {
1027 VLOperand = Register(RISCV::X0);
1028 Opcode = RISCV::PseudoVSETVLIX0;
1029 } else {
1030 Register AVLReg = I.getOperand(2).getReg();
1031 VLOperand = AVLReg;
1032
1033 // Check if AVL is a small constant that can use PseudoVSETIVLI.
1034 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1035 uint64_t AVL = AVLConst->Value.getZExtValue();
1036 if (isUInt<5>(AVL)) {
1037 MachineInstr *PseudoMI =
1038 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1039 TII.get(RISCV::PseudoVSETIVLI), DstReg)
1040 .addImm(AVL)
1041 .addImm(VTypeI);
1042 I.eraseFromParent();
1043 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1044 return true;
1045 }
1046 }
1047 }
1048
1049 MachineInstr *PseudoMI =
1050 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
1051 .addReg(VLOperand)
1052 .addImm(VTypeI);
1053 I.eraseFromParent();
1054 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1055 return true;
1056 }
1057 }
1058}
1059
1060bool RISCVInstructionSelector::selectExtractSubvector(MachineInstr &MI) const {
1061 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR);
1062
1063 Register DstReg = MI.getOperand(0).getReg();
1064 Register SrcReg = MI.getOperand(1).getReg();
1065
1066 LLT DstTy = MRI->getType(DstReg);
1067 LLT SrcTy = MRI->getType(SrcReg);
1068
1069 unsigned Idx = static_cast<unsigned>(MI.getOperand(2).getImm());
1070
1071 MVT DstMVT = getMVTForLLT(DstTy);
1072 MVT SrcMVT = getMVTForLLT(SrcTy);
1073
1074 unsigned SubRegIdx;
1075 std::tie(SubRegIdx, Idx) =
1077 SrcMVT, DstMVT, Idx, &TRI);
1078
1079 if (Idx != 0)
1080 return false;
1081
1082 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(DstMVT);
1083 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1084 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1085 return false;
1086
1087 unsigned SrcRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(SrcMVT);
1088 const TargetRegisterClass *SrcRC = TRI.getRegClass(SrcRegClassID);
1089 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
1090 return false;
1091
1092 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1093 DstReg)
1094 .addReg(SrcReg, {}, SubRegIdx);
1095
1096 MI.eraseFromParent();
1097 return true;
1098}
1099
1100bool RISCVInstructionSelector::selectInsertSubVector(MachineInstr &MI) const {
1101 assert(MI.getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR);
1102
1103 Register DstReg = MI.getOperand(0).getReg();
1104 Register VecReg = MI.getOperand(1).getReg();
1105 Register SubVecReg = MI.getOperand(2).getReg();
1106
1107 LLT VecTy = MRI->getType(VecReg);
1108 LLT SubVecTy = MRI->getType(SubVecReg);
1109
1110 MVT VecMVT = getMVTForLLT(VecTy);
1111 MVT SubVecMVT = getMVTForLLT(SubVecTy);
1112
1113 unsigned Idx = static_cast<unsigned>(MI.getOperand(3).getImm());
1114
1115 unsigned SubRegIdx;
1116 std::tie(SubRegIdx, Idx) =
1118 VecMVT, SubVecMVT, Idx, &TRI);
1119
1120 // If the Idx hasn't been completely eliminated then this is a subvector
1121 // insert which doesn't naturally align to a vector register. These must
1122 // be handled using instructions to manipulate the vector registers.
1123 if (Idx != 0)
1124 return false;
1125
1126 // Constrain dst
1127 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(VecMVT);
1128 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1129 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1130 return false;
1131
1132 // If we haven't set a SubRegIdx, then we must be going between
1133 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy.
1134 if (SubRegIdx == RISCV::NoSubRegister) {
1136 DstRegClassID &&
1137 "Unexpected subvector insert");
1138 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1139 DstReg)
1140 .addReg(SubVecReg);
1141 MI.eraseFromParent();
1142 return true;
1143 }
1144
1145 // Use INSERT_SUBREG to insert the subvector into the vector at the
1146 // appropriate subregister index.
1147 MachineInstr *Ins = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1148 TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1149 .addReg(VecReg)
1150 .addReg(SubVecReg)
1151 .addImm(SubRegIdx);
1152
1153 MI.eraseFromParent();
1155 return true;
1156}
1157
1158bool RISCVInstructionSelector::select(MachineInstr &MI) {
1159 preISelLower(MI);
1160 const unsigned Opc = MI.getOpcode();
1161
1162 if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
1163 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
1164 const Register DefReg = MI.getOperand(0).getReg();
1165 const LLT DefTy = MRI->getType(DefReg);
1166
1167 const RegClassOrRegBank &RegClassOrBank =
1168 MRI->getRegClassOrRegBank(DefReg);
1169
1170 const TargetRegisterClass *DefRC =
1172 if (!DefRC) {
1173 if (!DefTy.isValid()) {
1174 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
1175 return false;
1176 }
1177
1178 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
1179 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB, STI.is64Bit());
1180 if (!DefRC) {
1181 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
1182 return false;
1183 }
1184 }
1185
1186 MI.setDesc(TII.get(TargetOpcode::PHI));
1187 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
1188 }
1189
1190 // Certain non-generic instructions also need some special handling.
1191 if (MI.isCopy())
1192 return selectCopy(MI);
1193
1194 return true;
1195 }
1196
1197 if (selectImpl(MI, *CoverageInfo))
1198 return true;
1199
1200 switch (Opc) {
1201 case TargetOpcode::G_ANYEXT:
1202 case TargetOpcode::G_PTRTOINT:
1203 case TargetOpcode::G_INTTOPTR:
1204 case TargetOpcode::G_TRUNC:
1205 case TargetOpcode::G_FREEZE:
1206 return selectCopy(MI);
1207 case TargetOpcode::G_CONSTANT: {
1208 Register DstReg = MI.getOperand(0).getReg();
1209 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1210
1211 if (!materializeImm(DstReg, Imm, MI))
1212 return false;
1213
1214 MI.eraseFromParent();
1215 return true;
1216 }
1217 case TargetOpcode::G_ZEXT:
1218 case TargetOpcode::G_SEXT: {
1219 bool IsSigned = Opc != TargetOpcode::G_ZEXT;
1220 Register DstReg = MI.getOperand(0).getReg();
1221 Register SrcReg = MI.getOperand(1).getReg();
1222 LLT SrcTy = MRI->getType(SrcReg);
1223 unsigned SrcSize = SrcTy.getSizeInBits();
1224
1225 if (SrcTy.isVector())
1226 return false; // Should be handled by imported patterns.
1227
1228 assert((*RBI.getRegBank(DstReg, *MRI, TRI)).getID() ==
1229 RISCV::GPRBRegBankID &&
1230 "Unexpected ext regbank");
1231
1232 // Use addiw SrcReg, 0 (sext.w) for i32.
1233 if (IsSigned && SrcSize == 32) {
1234 MI.setDesc(TII.get(RISCV::ADDIW));
1235 MI.addOperand(MachineOperand::CreateImm(0));
1237 return true;
1238 }
1239
1240 // Use add.uw SrcReg, X0 (zext.w) for i32 with Zba.
1241 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
1242 MI.setDesc(TII.get(RISCV::ADD_UW));
1243 MI.addOperand(MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false));
1245 return true;
1246 }
1247
1248 // Use sext.h/zext.h for i16 with Zbb.
1249 if (SrcSize == 16 &&
1250 (STI.hasStdExtZbb() || (!IsSigned && STI.hasStdExtZbkb()))) {
1251 MI.setDesc(TII.get(IsSigned ? RISCV::SEXT_H
1252 : STI.isRV64() ? RISCV::ZEXT_H_RV64
1253 : RISCV::ZEXT_H_RV32));
1255 return true;
1256 }
1257
1258 // Fall back to shift pair.
1259 Register ShiftLeftReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1260 MachineInstr *ShiftLeft = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1261 TII.get(RISCV::SLLI), ShiftLeftReg)
1262 .addReg(SrcReg)
1263 .addImm(STI.getXLen() - SrcSize);
1264 constrainSelectedInstRegOperands(*ShiftLeft, TII, TRI, RBI);
1265 MachineInstr *ShiftRight =
1266 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1267 TII.get(IsSigned ? RISCV::SRAI : RISCV::SRLI), DstReg)
1268 .addReg(ShiftLeftReg)
1269 .addImm(STI.getXLen() - SrcSize);
1270 constrainSelectedInstRegOperands(*ShiftRight, TII, TRI, RBI);
1271 MI.eraseFromParent();
1272 return true;
1273 }
1274 case TargetOpcode::G_FCONSTANT: {
1275 // TODO: Use constant pool for complex constants.
1276 Register DstReg = MI.getOperand(0).getReg();
1277 const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
1278 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1279 if (Size == 16 || Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
1280 Register GPRReg;
1281 if (FPimm.isPosZero()) {
1282 GPRReg = RISCV::X0;
1283 } else {
1284 GPRReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1285 APInt Imm = FPimm.bitcastToAPInt();
1286 if (!materializeImm(GPRReg, Imm.getSExtValue(), MI))
1287 return false;
1288 }
1289
1290 unsigned Opcode = Size == 64 ? RISCV::FMV_D_X
1291 : Size == 32 ? RISCV::FMV_W_X
1292 : RISCV::FMV_H_X;
1293 MachineInstr *FMV = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1294 TII.get(Opcode), DstReg)
1295 .addReg(GPRReg);
1297 } else {
1298 // s64 on rv32
1299 assert(Size == 64 && !Subtarget->is64Bit() &&
1300 "Unexpected size or subtarget");
1301
1302 if (FPimm.isPosZero()) {
1303 // Optimize +0.0 to use fcvt.d.w
1304 MachineInstr *FCVT = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1305 TII.get(RISCV::FCVT_D_W), DstReg)
1306 .addReg(RISCV::X0)
1309
1310 MI.eraseFromParent();
1311 return true;
1312 }
1313
1314 // Split into two pieces and build through the stack.
1315 Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1316 Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1317 APInt Imm = FPimm.bitcastToAPInt();
1318 if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
1319 MI))
1320 return false;
1321 if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MI))
1322 return false;
1323 MachineInstr *PairF64 =
1324 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1325 TII.get(RISCV::BuildPairF64Pseudo), DstReg)
1326 .addReg(GPRRegLow)
1327 .addReg(GPRRegHigh);
1328 constrainSelectedInstRegOperands(*PairF64, TII, TRI, RBI);
1329 }
1330
1331 MI.eraseFromParent();
1332 return true;
1333 }
1334 case TargetOpcode::G_GLOBAL_VALUE: {
1335 auto *GV = MI.getOperand(1).getGlobal();
1336 if (GV->isThreadLocal()) {
1337 // TODO: implement this case.
1338 return false;
1339 }
1340
1341 return selectAddr(MI, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1342 }
1343 case TargetOpcode::G_JUMP_TABLE:
1344 case TargetOpcode::G_CONSTANT_POOL:
1345 return selectAddr(MI);
1346 case TargetOpcode::G_BRCOND: {
1347 Register LHS, RHS;
1349 getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
1350
1351 MachineInstr *Bcc = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1352 TII.get(RISCVCC::getBrCond(CC)))
1353 .addReg(LHS)
1354 .addReg(RHS)
1355 .addMBB(MI.getOperand(1).getMBB());
1356 MI.eraseFromParent();
1358 return true;
1359 }
1360 case TargetOpcode::G_BRINDIRECT:
1361 MI.setDesc(TII.get(RISCV::PseudoBRIND));
1362 MI.addOperand(MachineOperand::CreateImm(0));
1364 return true;
1365 case TargetOpcode::G_SELECT:
1366 return selectSelect(MI);
1367 case TargetOpcode::G_FCMP:
1368 return selectFPCompare(MI);
1369 case TargetOpcode::G_FENCE: {
1370 AtomicOrdering FenceOrdering =
1371 static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
1372 SyncScope::ID FenceSSID =
1373 static_cast<SyncScope::ID>(MI.getOperand(1).getImm());
1374 emitFence(FenceOrdering, FenceSSID, MI);
1375 MI.eraseFromParent();
1376 return true;
1377 }
1378 case TargetOpcode::G_IMPLICIT_DEF:
1379 return selectImplicitDef(MI);
1380 case TargetOpcode::G_UNMERGE_VALUES:
1381 return selectUnmergeValues(MI);
1382 case TargetOpcode::G_LOAD:
1383 case TargetOpcode::G_STORE: {
1384 GLoadStore &LdSt = cast<GLoadStore>(MI);
1385 const Register ValReg = LdSt.getReg(0);
1386 const Register PtrReg = LdSt.getPointerReg();
1387 LLT PtrTy = MRI->getType(PtrReg);
1388
1389 const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
1390 if (RB.getID() != RISCV::GPRBRegBankID)
1391 return false;
1392
1393#ifndef NDEBUG
1394 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, *MRI, TRI);
1395 // Check that the pointer register is valid.
1396 assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
1397 "Load/Store pointer operand isn't a GPR");
1398 assert(PtrTy.isPointer() && "Load/Store pointer operand isn't a pointer");
1399#endif
1400
1401 // Can only handle AddressSpace 0.
1402 if (PtrTy.getAddressSpace() != 0)
1403 return false;
1404
1405 unsigned MemSize = LdSt.getMemSizeInBits().getValue();
1406 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
1407
1408 if (isStrongerThanMonotonic(Order)) {
1409 MI.setDesc(TII.get(selectZalasrLoadStoreOp(Opc, MemSize)));
1411 return true;
1412 }
1413
1414 const unsigned NewOpc = selectRegImmLoadStoreOp(MI.getOpcode(), MemSize);
1415 if (NewOpc == MI.getOpcode())
1416 return false;
1417
1418 // Check if we can fold anything into the addressing mode.
1419 auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
1420 if (!AddrModeFns)
1421 return false;
1422
1423 // Folded something. Create a new instruction and return it.
1424 MachineInstrBuilder NewInst =
1425 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(NewOpc));
1426 NewInst.setMIFlags(MI.getFlags());
1427 if (isa<GStore>(MI))
1428 NewInst.addUse(ValReg);
1429 else
1430 NewInst.addDef(ValReg);
1431 NewInst.cloneMemRefs(MI);
1432 for (auto &Fn : *AddrModeFns)
1433 Fn(NewInst);
1434 MI.eraseFromParent();
1435
1436 constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
1437 return true;
1438 }
1439 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1440 return selectIntrinsicWithSideEffects(MI);
1441 case TargetOpcode::G_INTRINSIC:
1442 return selectIntrinsic(MI);
1443 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1444 return selectExtractSubvector(MI);
1445 case TargetOpcode::G_INSERT_SUBVECTOR:
1446 return selectInsertSubVector(MI);
1447 default:
1448 return false;
1449 }
1450}
1451
1452bool RISCVInstructionSelector::selectUnmergeValues(MachineInstr &MI) const {
1453 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1454
1455 if (!Subtarget->hasStdExtZfa())
1456 return false;
1457
1458 // Split F64 Src into two s32 parts
1459 if (MI.getNumOperands() != 3)
1460 return false;
1461 Register Src = MI.getOperand(2).getReg();
1462 Register Lo = MI.getOperand(0).getReg();
1463 Register Hi = MI.getOperand(1).getReg();
1464 if (!isRegInFprb(Src) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
1465 return false;
1466
1467 MachineInstr *ExtractLo = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1468 TII.get(RISCV::FMV_X_W_FPR64), Lo)
1469 .addReg(Src);
1470 constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI);
1471
1472 MachineInstr *ExtractHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1473 TII.get(RISCV::FMVH_X_D), Hi)
1474 .addReg(Src);
1475 constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI);
1476
1477 MI.eraseFromParent();
1478 return true;
1479}
1480
1481bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &Op) {
1482 Register PtrReg = Op.getReg();
1483 assert(MRI->getType(PtrReg).isPointer() && "Operand is not a pointer!");
1484
1485 const LLT sXLen = LLT::scalar(STI.getXLen());
1486 MachineInstr &ParentMI = *Op.getParent();
1487 Register IntReg = MRI->createGenericVirtualRegister(sXLen);
1488 MRI->setRegBank(IntReg, RBI.getRegBank(RISCV::GPRBRegBankID));
1489 MachineInstr *PtrToInt =
1490 BuildMI(*ParentMI.getParent(), ParentMI, ParentMI.getDebugLoc(),
1491 TII.get(TargetOpcode::G_PTRTOINT), IntReg)
1492 .addReg(PtrReg);
1493 Op.setReg(IntReg);
1494 return select(*PtrToInt);
1495}
1496
1497void RISCVInstructionSelector::preISelLower(MachineInstr &MI) {
1498 switch (MI.getOpcode()) {
1499 case TargetOpcode::G_PTR_ADD: {
1500 Register DstReg = MI.getOperand(0).getReg();
1501 const LLT sXLen = LLT::scalar(STI.getXLen());
1502
1503 replacePtrWithInt(MI.getOperand(1));
1504 MI.setDesc(TII.get(TargetOpcode::G_ADD));
1505 MRI->setType(DstReg, sXLen);
1506 break;
1507 }
1508 case TargetOpcode::G_PTRMASK: {
1509 Register DstReg = MI.getOperand(0).getReg();
1510 const LLT sXLen = LLT::scalar(STI.getXLen());
1511 replacePtrWithInt(MI.getOperand(1));
1512 MI.setDesc(TII.get(TargetOpcode::G_AND));
1513 MRI->setType(DstReg, sXLen);
1514 break;
1515 }
1516 }
1517}
1518
1519void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1520 const MachineInstr &MI,
1521 int OpIdx) const {
1522 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1523 "Expected G_CONSTANT");
1524 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1525 MIB.addImm(-CstVal);
1526}
1527
1528void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1529 const MachineInstr &MI,
1530 int OpIdx) const {
1531 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1532 "Expected G_CONSTANT");
1533 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1534 MIB.addImm(STI.getXLen() - CstVal);
1535}
1536
1537void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1538 const MachineInstr &MI,
1539 int OpIdx) const {
1540 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1541 "Expected G_CONSTANT");
1542 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1543 MIB.addImm(32 - CstVal);
1544}
1545
1546void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1547 const MachineInstr &MI,
1548 int OpIdx) const {
1549 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1550 "Expected G_CONSTANT");
1551 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1552 MIB.addImm(CstVal + 1);
1553}
1554
1555void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1556 const MachineInstr &MI,
1557 int OpIdx) const {
1558 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1559 "Expected G_CONSTANT");
1560 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1562}
1563
1564void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1565 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
1566 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1567 "Expected G_CONSTANT");
1568 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1569 MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
1570}
1571
1572void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1573 const MachineInstr &MI,
1574 int OpIdx) const {
1575 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1576 "Expected G_CONSTANT");
1577 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1578 int64_t Adj = Imm < 0 ? -2048 : 2047;
1579 MIB.addImm(Imm - Adj);
1580}
1581
1582void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1583 const MachineInstr &MI,
1584 int OpIdx) const {
1585 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1586 "Expected G_CONSTANT");
1587 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1588 MIB.addImm(Imm);
1589}
1590
1591bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
1592 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
1593}
1594
1595bool RISCVInstructionSelector::isRegInFprb(Register Reg) const {
1596 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID;
1597}
1598
1599bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
1600 MachineOperand Dst = MI.getOperand(0);
1601 Register DstReg = MI.getOperand(0).getReg();
1602
1603 if (DstReg.isPhysical())
1604 return true;
1605
1606 const TargetRegisterClass *DstRC =
1607 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
1608
1609 assert(DstRC &&
1610 "Register class not available for LLT, register bank combination");
1611
1612 // No need to constrain SrcReg. It will get constrained when
1613 // we hit another of its uses or its defs.
1614 // Copies do not have constraints.
1615 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1616 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1617 << " operand\n");
1618 return false;
1619 }
1620
1621 MI.setDesc(TII.get(RISCV::COPY));
1622 return true;
1623}
1624
1625bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI) const {
1626 assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1627
1628 const Register DstReg = MI.getOperand(0).getReg();
1629 const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
1630 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI), STI.is64Bit());
1631
1632 assert(DstRC &&
1633 "Register class not available for LLT, register bank combination");
1634
1635 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1636 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1637 << " operand\n");
1638 }
1639 MI.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1640 return true;
1641}
1642
1643bool RISCVInstructionSelector::materializeImm(Register DstReg, int64_t Imm,
1644 MachineInstr &MI) const {
1645 MachineBasicBlock &MBB = *MI.getParent();
1646 DebugLoc DL = MI.getDebugLoc();
1647
1648 if (Imm == 0) {
1649 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::COPY), DstReg).addReg(RISCV::X0);
1650 RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, *MRI);
1651 return true;
1652 }
1653
1655 unsigned NumInsts = Seq.size();
1656 Register SrcReg = RISCV::X0;
1657
1658 for (unsigned i = 0; i < NumInsts; i++) {
1659 Register TmpReg = i < NumInsts - 1
1660 ? MRI->createVirtualRegister(&RISCV::GPRRegClass)
1661 : DstReg;
1662 const RISCVMatInt::Inst &I = Seq[i];
1663 MachineInstr *Result;
1664
1665 switch (I.getOpndKind()) {
1666 case RISCVMatInt::Imm:
1667 // clang-format off
1668 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1669 .addImm(I.getImm());
1670 // clang-format on
1671 break;
1672 case RISCVMatInt::RegX0:
1673 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1674 .addReg(SrcReg)
1675 .addReg(RISCV::X0);
1676 break;
1678 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1679 .addReg(SrcReg)
1680 .addReg(SrcReg);
1681 break;
1683 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1684 .addReg(SrcReg)
1685 .addImm(I.getImm());
1686 break;
1687 }
1688
1690
1691 SrcReg = TmpReg;
1692 }
1693
1694 return true;
1695}
1696
1697bool RISCVInstructionSelector::selectAddr(MachineInstr &MI, bool IsLocal,
1698 bool IsExternWeak) const {
1699 assert((MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1700 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1701 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1702 "Unexpected opcode");
1703
1704 const MachineOperand &DispMO = MI.getOperand(1);
1705
1706 Register DefReg = MI.getOperand(0).getReg();
1707 const LLT DefTy = MRI->getType(DefReg);
1708
1709 // When HWASAN is used and tagging of global variables is enabled
1710 // they should be accessed via the GOT, since the tagged address of a global
1711 // is incompatible with existing code models. This also applies to non-pic
1712 // mode.
1713 if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
1714 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1715 // Use PC-relative addressing to access the symbol. This generates the
1716 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
1717 // %pcrel_lo(auipc)).
1718 MI.setDesc(TII.get(RISCV::PseudoLLA));
1720 return true;
1721 }
1722
1723 // Use PC-relative addressing to access the GOT for this symbol, then
1724 // load the address from the GOT. This generates the pattern (PseudoLGA
1725 // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
1726 // %pcrel_lo(auipc))).
1727 MachineFunction &MF = *MI.getParent()->getParent();
1728 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1732 DefTy, Align(DefTy.getSizeInBits() / 8));
1733
1734 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1735 TII.get(RISCV::PseudoLGA), DefReg)
1736 .addDisp(DispMO, 0)
1737 .addMemOperand(MemOp);
1738
1740
1741 MI.eraseFromParent();
1742 return true;
1743 }
1744
1745 switch (TM.getCodeModel()) {
1746 default: {
1748 "Unsupported code model for lowering", MI);
1749 return false;
1750 }
1751 case CodeModel::Small: {
1752 // Must lie within a single 2 GiB address range and must lie between
1753 // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
1754 // (lui %hi(sym)) %lo(sym)).
1755 Register AddrHiDest = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1756 MachineInstr *AddrHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1757 TII.get(RISCV::LUI), AddrHiDest)
1758 .addDisp(DispMO, 0, RISCVII::MO_HI);
1759
1761
1762 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1763 TII.get(RISCV::ADDI), DefReg)
1764 .addReg(AddrHiDest)
1765 .addDisp(DispMO, 0, RISCVII::MO_LO);
1766
1768
1769 MI.eraseFromParent();
1770 return true;
1771 }
1772 case CodeModel::Medium:
1773 // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
1774 // relocation needs to reference a label that points to the auipc
1775 // instruction itself, not the global. This cannot be done inside the
1776 // instruction selector.
1777 if (IsExternWeak) {
1778 // An extern weak symbol may be undefined, i.e. have value 0, which may
1779 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
1780 // symbol. This generates the pattern (PseudoLGA sym), which expands to
1781 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
1782 MachineFunction &MF = *MI.getParent()->getParent();
1783 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1787 DefTy, Align(DefTy.getSizeInBits() / 8));
1788
1789 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1790 TII.get(RISCV::PseudoLGA), DefReg)
1791 .addDisp(DispMO, 0)
1792 .addMemOperand(MemOp);
1793
1795
1796 MI.eraseFromParent();
1797 return true;
1798 }
1799
1800 // Generate a sequence for accessing addresses within any 2GiB range
1801 // within the address space. This generates the pattern (PseudoLLA sym),
1802 // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
1803 MI.setDesc(TII.get(RISCV::PseudoLLA));
1805 return true;
1806 }
1807
1808 return false;
1809}
1810
1811bool RISCVInstructionSelector::selectSelect(MachineInstr &MI) const {
1812 auto &SelectMI = cast<GSelect>(MI);
1813
1814 Register LHS, RHS;
1816 getOperandsForBranch(SelectMI.getCondReg(), CC, LHS, RHS, *MRI);
1817
1818 Register DstReg = SelectMI.getReg(0);
1819
1820 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1821 if (RBI.getRegBank(DstReg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
1822 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1823 Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1824 : RISCV::Select_FPR64_Using_CC_GPR;
1825 }
1826
1827 MachineInstr *Result =
1828 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(Opc))
1829 .addDef(DstReg)
1830 .addReg(LHS)
1831 .addReg(RHS)
1832 .addImm(CC)
1833 .addReg(SelectMI.getTrueReg())
1834 .addReg(SelectMI.getFalseReg());
1835 MI.eraseFromParent();
1837 return true;
1838}
1839
1840// Convert an FCMP predicate to one of the supported F or D instructions.
1841static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
1842 assert((Size == 16 || Size == 32 || Size == 64) && "Unsupported size");
1843 switch (Pred) {
1844 default:
1845 llvm_unreachable("Unsupported predicate");
1846 case CmpInst::FCMP_OLT:
1847 return Size == 16 ? RISCV::FLT_H : Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1848 case CmpInst::FCMP_OLE:
1849 return Size == 16 ? RISCV::FLE_H : Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1850 case CmpInst::FCMP_OEQ:
1851 return Size == 16 ? RISCV::FEQ_H : Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1852 }
1853}
1854
1855// Try legalizing an FCMP by swapping or inverting the predicate to one that
1856// is supported.
1858 CmpInst::Predicate &Pred, bool &NeedInvert) {
1859 auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
1860 return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
1861 Pred == CmpInst::FCMP_OEQ;
1862 };
1863
1864 assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
1865
1867 if (isLegalFCmpPredicate(InvPred)) {
1868 Pred = InvPred;
1869 std::swap(LHS, RHS);
1870 return true;
1871 }
1872
1873 InvPred = CmpInst::getInversePredicate(Pred);
1874 NeedInvert = true;
1875 if (isLegalFCmpPredicate(InvPred)) {
1876 Pred = InvPred;
1877 return true;
1878 }
1879 InvPred = CmpInst::getSwappedPredicate(InvPred);
1880 if (isLegalFCmpPredicate(InvPred)) {
1881 Pred = InvPred;
1882 std::swap(LHS, RHS);
1883 return true;
1884 }
1885
1886 return false;
1887}
1888
1889// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
1890// the result in DstReg.
1891// FIXME: Maybe we should expand this earlier.
1892bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI) const {
1893 auto &CmpMI = cast<GFCmp>(MI);
1894 CmpInst::Predicate Pred = CmpMI.getCond();
1895
1896 Register DstReg = CmpMI.getReg(0);
1897 Register LHS = CmpMI.getLHSReg();
1898 Register RHS = CmpMI.getRHSReg();
1899
1900 unsigned Size = MRI->getType(LHS).getSizeInBits();
1901 assert((Size == 16 || Size == 32 || Size == 64) && "Unexpected size");
1902
1903 Register TmpReg = DstReg;
1904
1905 bool NeedInvert = false;
1906 // First try swapping operands or inverting.
1907 if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
1908 if (NeedInvert)
1909 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1910 MachineInstr *Cmp = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1911 TII.get(getFCmpOpcode(Pred, Size)), TmpReg)
1912 .addReg(LHS)
1913 .addReg(RHS);
1915 } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
1916 // fcmp one LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
1917 NeedInvert = Pred == CmpInst::FCMP_UEQ;
1918 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1919 MachineInstr *Cmp1 =
1920 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1921 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp1Reg)
1922 .addReg(LHS)
1923 .addReg(RHS);
1925 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1926 MachineInstr *Cmp2 =
1927 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1928 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp2Reg)
1929 .addReg(RHS)
1930 .addReg(LHS);
1932 if (NeedInvert)
1933 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1934 MachineInstr *Or = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1935 TII.get(RISCV::OR), TmpReg)
1936 .addReg(Cmp1Reg)
1937 .addReg(Cmp2Reg);
1939 } else if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
1940 // fcmp ord LHS, RHS => (AND (FEQ LHS, LHS), (FEQ RHS, RHS))
1941 // If LHS and RHS are the same, a single FEQ suffices.
1942 NeedInvert = Pred == CmpInst::FCMP_UNO;
1943 if (NeedInvert)
1944 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1945 if (LHS == RHS) {
1946 MachineInstr *Cmp =
1947 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1948 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), TmpReg)
1949 .addReg(LHS)
1950 .addReg(LHS);
1952 } else {
1953 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1954 MachineInstr *Cmp1 =
1955 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1956 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp1Reg)
1957 .addReg(LHS)
1958 .addReg(LHS);
1960 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1961 MachineInstr *Cmp2 =
1962 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1963 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp2Reg)
1964 .addReg(RHS)
1965 .addReg(RHS);
1967 MachineInstr *And = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1968 TII.get(RISCV::AND), TmpReg)
1969 .addReg(Cmp1Reg)
1970 .addReg(Cmp2Reg);
1972 }
1973 } else
1974 llvm_unreachable("Unhandled predicate");
1975
1976 // Emit an XORI to invert the result if needed.
1977 if (NeedInvert) {
1978 MachineInstr *Xor = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1979 TII.get(RISCV::XORI), DstReg)
1980 .addReg(TmpReg)
1981 .addImm(1);
1983 }
1984
1985 MI.eraseFromParent();
1986 return true;
1987}
1988
1989void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
1990 SyncScope::ID FenceSSID,
1991 MachineInstr &MI) const {
1992 MachineBasicBlock &MBB = *MI.getParent();
1993 DebugLoc DL = MI.getDebugLoc();
1994
1995 if (STI.hasStdExtZtso()) {
1996 // The only fence that needs an instruction is a sequentially-consistent
1997 // cross-thread fence.
1998 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1999 FenceSSID == SyncScope::System) {
2000 // fence rw, rw
2001 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE))
2004 return;
2005 }
2006
2007 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
2008 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2009 return;
2010 }
2011
2012 // singlethread fences only synchronize with signal handlers on the same
2013 // thread and thus only need to preserve instruction order, not actually
2014 // enforce memory ordering.
2015 if (FenceSSID == SyncScope::SingleThread) {
2016 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2017 return;
2018 }
2019
2020 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
2021 // Manual: Volume I.
2022 unsigned Pred, Succ;
2023 switch (FenceOrdering) {
2024 default:
2025 llvm_unreachable("Unexpected ordering");
2026 case AtomicOrdering::AcquireRelease:
2027 // fence acq_rel -> fence.tso
2028 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE_TSO));
2029 return;
2030 case AtomicOrdering::Acquire:
2031 // fence acquire -> fence r, rw
2032 Pred = RISCVFenceField::R;
2034 break;
2035 case AtomicOrdering::Release:
2036 // fence release -> fence rw, w
2038 Succ = RISCVFenceField::W;
2039 break;
2040 case AtomicOrdering::SequentiallyConsistent:
2041 // fence seq_cst -> fence rw, rw
2044 break;
2045 }
2046 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE)).addImm(Pred).addImm(Succ);
2047}
2048
2049namespace llvm {
2050InstructionSelector *
2052 const RISCVSubtarget &Subtarget,
2053 const RISCVRegisterBankInfo &RBI) {
2054 return new RISCVInstructionSelector(TM, Subtarget, RBI);
2055}
2056} // 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!")
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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
MachineInstr unsigned OpIdx
#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:1457
bool isPosZero() const
Definition APFloat.h:1576
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1120
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
Definition APInt.h:287
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
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
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 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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
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)
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)
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.