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(MachineInstr &MI, unsigned OpIdx);
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 // Emit a constant-materialization instruction sequence.
86 bool materializeInstSeq(Register DstReg, const RISCVMatInt::InstSeq &Seq,
87 MachineInstr &MI) const;
88 bool selectAddr(MachineInstr &MI, bool IsLocal = true,
89 bool IsExternWeak = false) const;
90 bool selectSelect(MachineInstr &MI) const;
91 bool selectFPCompare(MachineInstr &MI) const;
92 void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
93 MachineInstr &MI) const;
95 void addVectorLoadStoreOperands(MachineInstr &I,
97 unsigned &CurOp, bool IsMasked,
98 bool IsStridedOrIndexed,
99 LLT *IndexVT = nullptr) const;
100 bool selectIntrinsicWithSideEffects(MachineInstr &I) const;
101 bool selectIntrinsic(MachineInstr &I) const;
102 bool selectExtractSubvector(MachineInstr &MI) const;
103 bool selectInsertSubVector(MachineInstr &I) const;
104 ComplexRendererFns selectShiftMask(MachineOperand &Root,
105 unsigned ShiftWidth) const;
106 ComplexRendererFns selectShiftMaskXLen(MachineOperand &Root) const {
107 return selectShiftMask(Root, STI.getXLen());
108 }
109 ComplexRendererFns selectShiftMask32(MachineOperand &Root) const {
110 return selectShiftMask(Root, 32);
111 }
112 ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
113 ComplexRendererFns selectAddrRegImmLsb00000(MachineOperand &Root) const;
114
115 // Plan for materializing a constant address as (Hi materialization, Lo12
116 // offset). Lo12 is a simm12 that, for prefetch (IsPrefetch), must be
117 // a multiple of 32.
118 struct ConstAddrPlan {
119 enum { X0, LUI, InstSeq } Kind = X0;
120 int64_t Hi20 = 0;
122 int64_t Lo12 = 0;
123 };
124 ComplexRendererFns computeConstAddr(int64_t CVal, bool IsPrefetch,
125 Register OrigBase) const;
126 // Materialize the high part of Plan into a register. If OrigBase is valid,
127 // ADD it to the materialized high part (for G_PTR_ADD + large constant).
128 Register materializeConstBase(MachineInstrBuilder &MIB,
129 const ConstAddrPlan &Plan,
130 Register OrigBase) const;
131
132 ComplexRendererFns selectSExtBits(MachineOperand &Root, unsigned Bits) const;
133 template <unsigned Bits>
134 ComplexRendererFns selectSExtBits(MachineOperand &Root) const {
135 return selectSExtBits(Root, Bits);
136 }
137
138 ComplexRendererFns selectZExtBits(MachineOperand &Root, unsigned Bits) const;
139 template <unsigned Bits>
140 ComplexRendererFns selectZExtBits(MachineOperand &Root) const {
141 return selectZExtBits(Root, Bits);
142 }
143
144 ComplexRendererFns selectSHXADDOp(MachineOperand &Root, unsigned ShAmt) const;
145 template <unsigned ShAmt>
146 ComplexRendererFns selectSHXADDOp(MachineOperand &Root) const {
147 return selectSHXADDOp(Root, ShAmt);
148 }
149
150 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root,
151 unsigned ShAmt) const;
152 template <unsigned ShAmt>
153 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root) const {
154 return selectSHXADD_UWOp(Root, ShAmt);
155 }
156
157 ComplexRendererFns renderVLOp(MachineOperand &Root) const;
158
159 // Custom renderers for tablegen
160 void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
161 int OpIdx) const;
162 void renderImmSubFromXLen(MachineInstrBuilder &MIB, const MachineInstr &MI,
163 int OpIdx) const;
164 void renderImmSubFrom32(MachineInstrBuilder &MIB, const MachineInstr &MI,
165 int OpIdx) const;
166 void renderImmPlus1(MachineInstrBuilder &MIB, const MachineInstr &MI,
167 int OpIdx) const;
168
169 void renderTrailingZeros(MachineInstrBuilder &MIB, const MachineInstr &MI,
170 int OpIdx) const;
171 void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
172 const MachineInstr &MI, int OpIdx) const;
173
174 void renderAddiPairImmLarge(MachineInstrBuilder &MIB, const MachineInstr &MI,
175 int OpIdx) const;
176 void renderAddiPairImmSmall(MachineInstrBuilder &MIB, const MachineInstr &MI,
177 int OpIdx) const;
178
179 const RISCVSubtarget &STI;
180 const RISCVInstrInfo &TII;
181 const RISCVRegisterInfo &TRI;
182 const RISCVRegisterBankInfo &RBI;
183 const RISCVTargetMachine &TM;
184
185 MachineRegisterInfo *MRI = nullptr;
186
187 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
188 // uses "STI." in the code generated by TableGen. We need to unify the name of
189 // Subtarget variable.
190 const RISCVSubtarget *Subtarget = &STI;
191
192#define GET_GLOBALISEL_PREDICATES_DECL
193#include "RISCVGenGlobalISel.inc"
194#undef GET_GLOBALISEL_PREDICATES_DECL
195
196#define GET_GLOBALISEL_TEMPORARIES_DECL
197#include "RISCVGenGlobalISel.inc"
198#undef GET_GLOBALISEL_TEMPORARIES_DECL
199};
200
201} // end anonymous namespace
202
203#define GET_GLOBALISEL_IMPL
204#include "RISCVGenGlobalISel.inc"
205#undef GET_GLOBALISEL_IMPL
206
207RISCVInstructionSelector::RISCVInstructionSelector(
208 const RISCVTargetMachine &TM, const RISCVSubtarget &STI,
209 const RISCVRegisterBankInfo &RBI)
210 : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
211 TM(TM),
212
214#include "RISCVGenGlobalISel.inc"
217#include "RISCVGenGlobalISel.inc"
219{
220}
221
222// Mimics optimizations in ISel and RISCVOptWInst Pass
223bool RISCVInstructionSelector::hasAllNBitUsers(const MachineInstr &MI,
224 unsigned Bits,
225 const unsigned Depth) const {
226
227 assert((MI.getOpcode() == TargetOpcode::G_ADD ||
228 MI.getOpcode() == TargetOpcode::G_SUB ||
229 MI.getOpcode() == TargetOpcode::G_MUL ||
230 MI.getOpcode() == TargetOpcode::G_SHL ||
231 MI.getOpcode() == TargetOpcode::G_LSHR ||
232 MI.getOpcode() == TargetOpcode::G_AND ||
233 MI.getOpcode() == TargetOpcode::G_OR ||
234 MI.getOpcode() == TargetOpcode::G_XOR ||
235 MI.getOpcode() == TargetOpcode::G_SEXT_INREG || Depth != 0) &&
236 "Unexpected opcode");
237
238 if (Depth >= RISCVInstructionSelector::MaxRecursionDepth)
239 return false;
240
241 auto DestReg = MI.getOperand(0).getReg();
242 for (auto &UserOp : MRI->use_nodbg_operands(DestReg)) {
243 assert(UserOp.getParent() && "UserOp must have a parent");
244 const MachineInstr &UserMI = *UserOp.getParent();
245 unsigned OpIdx = UserOp.getOperandNo();
246
247 switch (UserMI.getOpcode()) {
248 default:
249 return false;
250 case RISCV::ADDW:
251 case RISCV::ADDIW:
252 case RISCV::SUBW:
253 case RISCV::FCVT_D_W:
254 case RISCV::FCVT_S_W:
255 if (Bits >= 32)
256 break;
257 return false;
258 case RISCV::SLL:
259 case RISCV::SRA:
260 case RISCV::SRL:
261 // Shift amount operands only use log2(Xlen) bits.
262 if (OpIdx == 2 && Bits >= Log2_32(Subtarget->getXLen()))
263 break;
264 return false;
265 case RISCV::SLLI:
266 // SLLI only uses the lower (XLen - ShAmt) bits.
267 if (Bits >= Subtarget->getXLen() - UserMI.getOperand(2).getImm())
268 break;
269 return false;
270 case RISCV::ANDI:
271 if (Bits >= (unsigned)llvm::bit_width<uint64_t>(
272 (uint64_t)UserMI.getOperand(2).getImm()))
273 break;
274 goto RecCheck;
275 case RISCV::AND:
276 case RISCV::OR:
277 case RISCV::XOR:
278 RecCheck:
279 if (hasAllNBitUsers(UserMI, Bits, Depth + 1))
280 break;
281 return false;
282 case RISCV::SRLI: {
283 unsigned ShAmt = UserMI.getOperand(2).getImm();
284 // If we are shifting right by less than Bits, and users don't demand any
285 // bits that were shifted into [Bits-1:0], then we can consider this as an
286 // N-Bit user.
287 if (Bits > ShAmt && hasAllNBitUsers(UserMI, Bits - ShAmt, Depth + 1))
288 break;
289 return false;
290 }
291 }
292 }
293
294 return true;
295}
296
297InstructionSelector::ComplexRendererFns
298RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
299 unsigned ShiftWidth) const {
300 if (!Root.isReg())
301 return std::nullopt;
302
303 using namespace llvm::MIPatternMatch;
304
305 Register ShAmtReg = Root.getReg();
306 // Peek through zext.
307 Register ZExtSrcReg;
308 if (mi_match(ShAmtReg, *MRI, m_GZExt(m_Reg(ZExtSrcReg))))
309 ShAmtReg = ZExtSrcReg;
310
311 APInt AndMask;
312 Register AndSrcReg;
313 // Try to combine the following pattern (applicable to other shift
314 // instructions as well as 32-bit ones):
315 //
316 // %4:gprb(s64) = G_AND %3, %2
317 // %5:gprb(s64) = G_LSHR %1, %4(s64)
318 //
319 // According to RISC-V's ISA manual, SLL, SRL, and SRA ignore other bits than
320 // the lowest log2(XLEN) bits of register rs2. As for the above pattern, if
321 // the lowest log2(XLEN) bits of register rd and rs2 of G_AND are the same,
322 // then it can be eliminated. Given register rs1 or rs2 holding a constant
323 // (the and mask), there are two cases G_AND can be erased:
324 //
325 // 1. the lowest log2(XLEN) bits of the and mask are all set
326 // 2. the bits of the register being masked are already unset (zero set)
327 if (mi_match(ShAmtReg, *MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
328 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
329 if (ShMask.isSubsetOf(AndMask)) {
330 ShAmtReg = AndSrcReg;
331 } else {
332 // SimplifyDemandedBits may have optimized the mask so try restoring any
333 // bits that are known zero.
334 KnownBits Known = VT->getKnownBits(AndSrcReg);
335 if (ShMask.isSubsetOf(AndMask | Known.Zero))
336 ShAmtReg = AndSrcReg;
337 }
338 }
339
340 APInt Imm;
342 if (mi_match(ShAmtReg, *MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
343 if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
344 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
345 // to avoid the ADD.
346 ShAmtReg = Reg;
347 } else if (mi_match(ShAmtReg, *MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
348 if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
349 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
350 // to generate a NEG instead of a SUB of a constant.
351 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
352 unsigned NegOpc = Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
353 return {{[=](MachineInstrBuilder &MIB) {
354 MachineIRBuilder(*MIB.getInstr())
355 .buildInstr(NegOpc, {ShAmtReg}, {Register(RISCV::X0), Reg});
356 MIB.addReg(ShAmtReg);
357 }}};
358 }
359 if (Imm.urem(ShiftWidth) == ShiftWidth - 1) {
360 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
361 // to generate a NOT instead of a SUB of a constant.
362 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
363 return {{[=](MachineInstrBuilder &MIB) {
364 MachineIRBuilder(*MIB.getInstr())
365 .buildInstr(RISCV::XORI, {ShAmtReg}, {Reg})
366 .addImm(-1);
367 MIB.addReg(ShAmtReg);
368 }}};
369 }
370 }
371
372 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
373}
374
375InstructionSelector::ComplexRendererFns
376RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
377 unsigned Bits) const {
378 if (!Root.isReg())
379 return std::nullopt;
380 Register RootReg = Root.getReg();
381
382 Register SrcReg;
383 if (mi_match(RootReg, *MRI,
384 m_GSExtInReg(m_Reg(SrcReg), m_SpecificImm(Bits)))) {
385 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SrcReg); }}};
386 }
387
388 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
389 if ((Size - VT->computeNumSignBits(RootReg)) < Bits)
390 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
391
392 return std::nullopt;
393}
394
395InstructionSelector::ComplexRendererFns
396RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
397 unsigned Bits) const {
398 if (!Root.isReg())
399 return std::nullopt;
400 Register RootReg = Root.getReg();
401
402 Register RegX;
404 if (mi_match(RootReg, *MRI, m_GAnd(m_Reg(RegX), m_SpecificICst(Mask)))) {
405 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
406 }
407
408 if (mi_match(RootReg, *MRI, m_GZExt(m_Reg(RegX))) &&
409 MRI->getType(RegX).getScalarSizeInBits() == Bits)
410 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
411
412 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
413 if (VT->maskedValueIsZero(RootReg, APInt::getBitsSetFrom(Size, Bits)))
414 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
415
416 return std::nullopt;
417}
418
419InstructionSelector::ComplexRendererFns
420RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
421 unsigned ShAmt) const {
422 using namespace llvm::MIPatternMatch;
423
424 if (!Root.isReg())
425 return std::nullopt;
426 Register RootReg = Root.getReg();
427
428 const unsigned XLen = STI.getXLen();
429 APInt Mask, C2;
430 Register RegY;
431 std::optional<bool> LeftShift;
432 // (and (shl y, c2), mask)
433 if (mi_match(RootReg, *MRI,
434 m_GAnd(m_GShl(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
435 LeftShift = true;
436 // (and (lshr y, c2), mask)
437 else if (mi_match(RootReg, *MRI,
438 m_GAnd(m_GLShr(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
439 LeftShift = false;
440
441 if (LeftShift.has_value()) {
442 if (*LeftShift)
444 else
446
447 if (Mask.isShiftedMask()) {
448 unsigned Leading = XLen - Mask.getActiveBits();
449 unsigned Trailing = Mask.countr_zero();
450 // Given (and (shl y, c2), mask) in which mask has no leading zeros and
451 // c3 trailing zeros. We can use an SRLI by c3 - c2 followed by a SHXADD.
452 if (*LeftShift && Leading == 0 && C2.ult(Trailing) && Trailing == ShAmt) {
453 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
454 return {{[=](MachineInstrBuilder &MIB) {
455 MachineIRBuilder(*MIB.getInstr())
456 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
457 .addImm(Trailing - C2.getZExtValue());
458 MIB.addReg(DstReg);
459 }}};
460 }
461
462 // Given (and (lshr y, c2), mask) in which mask has c2 leading zeros and
463 // c3 trailing zeros. We can use an SRLI by c2 + c3 followed by a SHXADD.
464 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
465 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
466 return {{[=](MachineInstrBuilder &MIB) {
467 MachineIRBuilder(*MIB.getInstr())
468 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
469 .addImm(Leading + Trailing);
470 MIB.addReg(DstReg);
471 }}};
472 }
473 }
474 }
475
476 LeftShift.reset();
477
478 // (shl (and y, mask), c2)
479 if (mi_match(RootReg, *MRI,
480 m_GShl(m_OneNonDBGUse(m_GAnd(m_Reg(RegY), m_ICst(Mask))),
481 m_ICst(C2))))
482 LeftShift = true;
483 // (lshr (and y, mask), c2)
484 else if (mi_match(RootReg, *MRI,
486 m_ICst(C2))))
487 LeftShift = false;
488
489 if (LeftShift.has_value() && Mask.isShiftedMask()) {
490 unsigned Leading = XLen - Mask.getActiveBits();
491 unsigned Trailing = Mask.countr_zero();
492
493 // Given (shl (and y, mask), c2) in which mask has 32 leading zeros and
494 // c3 trailing zeros. If c1 + c3 == ShAmt, we can emit SRLIW + SHXADD.
495 bool Cond = *LeftShift && Leading == 32 && Trailing > 0 &&
496 (Trailing + C2.getZExtValue()) == ShAmt;
497 if (!Cond)
498 // Given (lshr (and y, mask), c2) in which mask has 32 leading zeros and
499 // c3 trailing zeros. If c3 - c1 == ShAmt, we can emit SRLIW + SHXADD.
500 Cond = !*LeftShift && Leading == 32 && C2.ult(Trailing) &&
501 (Trailing - C2.getZExtValue()) == ShAmt;
502
503 if (Cond) {
504 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
505 return {{[=](MachineInstrBuilder &MIB) {
506 MachineIRBuilder(*MIB.getInstr())
507 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
508 .addImm(Trailing);
509 MIB.addReg(DstReg);
510 }}};
511 }
512 }
513
514 return std::nullopt;
515}
516
517InstructionSelector::ComplexRendererFns
518RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
519 unsigned ShAmt) const {
520 using namespace llvm::MIPatternMatch;
521
522 if (!Root.isReg())
523 return std::nullopt;
524 Register RootReg = Root.getReg();
525
526 // Given (and (shl x, c2), mask) in which mask is a shifted mask with
527 // 32 - ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
528 // c2 - ShAmt followed by SHXADD_UW with ShAmt for x amount.
529 APInt Mask, C2;
530 Register RegX;
531 if (mi_match(
532 RootReg, *MRI,
534 m_ICst(Mask))))) {
536
537 if (Mask.isShiftedMask()) {
538 unsigned Leading = Mask.countl_zero();
539 unsigned Trailing = Mask.countr_zero();
540 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
541 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
542 return {{[=](MachineInstrBuilder &MIB) {
543 MachineIRBuilder(*MIB.getInstr())
544 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
545 .addImm(C2.getZExtValue() - ShAmt);
546 MIB.addReg(DstReg);
547 }}};
548 }
549 }
550 }
551
552 return std::nullopt;
553}
554
555InstructionSelector::ComplexRendererFns
556RISCVInstructionSelector::renderVLOp(MachineOperand &Root) const {
557 assert(Root.isReg() && "Expected operand to be a Register");
558 std::optional<ValueAndVReg> C;
559 if (mi_match(Root.getReg(), *MRI, m_GCst(C))) {
560 if (C->Value.isAllOnes())
561 // If the operand is a G_CONSTANT with value of all ones it is larger than
562 // VLMAX. We convert it to an immediate with value VLMaxSentinel. This is
563 // recognized specially by the vsetvli insertion pass.
564 return {{[=](MachineInstrBuilder &MIB) {
565 MIB.addImm(RISCV::VLMaxSentinel);
566 }}};
567
568 if (isUInt<5>(C->Value.getZExtValue())) {
569 uint64_t ZExtC = C->Value.getZExtValue();
570 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
571 }
572 }
573 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); }}};
574}
575
576InstructionSelector::ComplexRendererFns
577RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
578 if (!Root.isReg())
579 return std::nullopt;
580
581 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
582 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
583 return {{
584 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
585 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
586 }};
587 }
588
589 if (isBaseWithConstantOffset(Root, *MRI)) {
590 MachineOperand &LHS = RootDef->getOperand(1);
591 MachineOperand &RHS = RootDef->getOperand(2);
592 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
593 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
594
595 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
596 if (isInt<12>(RHSC)) {
597 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
598 return {{
599 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
600 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
601 }};
602
603 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
604 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
605 }
606 }
607
608 // TODO: Need to get the immediate from a G_PTR_ADD. Should this be done in
609 // the combiner?
610 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
611 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
612}
613
614InstructionSelector::ComplexRendererFns
615RISCVInstructionSelector::selectAddrRegImmLsb00000(MachineOperand &Root) const {
616 if (!Root.isReg())
617 return std::nullopt;
618
619 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
620 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
621 return {{
622 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
623 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
624 }};
625 }
626
627 if (isBaseWithConstantOffset(Root, *MRI)) {
628 MachineOperand &LHS = RootDef->getOperand(1);
629 MachineOperand &RHS = RootDef->getOperand(2);
630 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
631 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
632 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
633
634 if (isInt<12>(RHSC)) {
635 // Not a multiple of 32: can't encode, use the address as-is.
636 if ((RHSC & 0b11111) != 0) {
637 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
638 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
639 }
640 // Fold the offset.
641 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
642 return {{
643 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
644 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
645 }};
646 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
647 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
648 }
649
650 // Large constant: fold a -2048/2016 adjustment to save an instruction.
651 if ((-2049 >= RHSC && RHSC >= -4096) || (4063 >= RHSC && RHSC >= 2017)) {
652 int64_t Adj = RHSC < 0 ? -2048 : 2016;
653 int64_t AdjustedOffset = RHSC - Adj;
654 Register BaseReg = LHS.getReg();
655 return {{[=](MachineInstrBuilder &MIB) {
656 Register Tmp = MRI->createVirtualRegister(&RISCV::GPRRegClass);
657 MachineInstr *Addi =
658 BuildMI(*MIB->getParent(), *MIB.getInstr(),
659 MIB->getDebugLoc(), TII.get(RISCV::ADDI), Tmp)
660 .addReg(BaseReg)
661 .addImm(AdjustedOffset);
663 MIB.addReg(Tmp);
664 },
665 [=](MachineInstrBuilder &MIB) { MIB.addImm(Adj); }}};
666 }
667
668 // Otherwise split the constant into Hi (materialized + added to the base)
669 // and Lo12 (folded offset).
670 if (auto Fns = computeConstAddr(RHSC, /*IsPrefetch=*/true, LHS.getReg()))
671 return Fns;
672 }
673
674 // Bare constant address. IRTranslator emits inttoptr(C) as
675 // G_INTTOPTR(G_CONSTANT); look through the G_INTTOPTR to reach the constant.
676 if (RootDef->getOpcode() == TargetOpcode::G_INTTOPTR) {
677 MachineInstr *SrcDef = MRI->getVRegDef(RootDef->getOperand(1).getReg());
678 if (SrcDef->getOpcode() == TargetOpcode::G_CONSTANT)
679 RootDef = SrcDef;
680 }
681 if (RootDef->getOpcode() == TargetOpcode::G_CONSTANT) {
682 int64_t CVal = RootDef->getOperand(1).getCImm()->getSExtValue();
683 if (auto Fns = computeConstAddr(CVal, /*IsPrefetch=*/true, Register()))
684 return Fns;
685 }
686
687 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
688 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
689}
690
691/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
692/// CC Must be an ICMP Predicate.
693static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
694 switch (CC) {
695 default:
696 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
697 case CmpInst::Predicate::ICMP_EQ:
698 return RISCVCC::COND_EQ;
699 case CmpInst::Predicate::ICMP_NE:
700 return RISCVCC::COND_NE;
701 case CmpInst::Predicate::ICMP_ULT:
702 return RISCVCC::COND_LTU;
703 case CmpInst::Predicate::ICMP_SLT:
704 return RISCVCC::COND_LT;
705 case CmpInst::Predicate::ICMP_UGE:
706 return RISCVCC::COND_GEU;
707 case CmpInst::Predicate::ICMP_SGE:
708 return RISCVCC::COND_GE;
709 }
710}
711
714 MachineRegisterInfo &MRI) {
715 // Try to fold an ICmp. If that fails, use a NE compare with X0.
717 if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
718 LHS = CondReg;
719 RHS = RISCV::X0;
720 CC = RISCVCC::COND_NE;
721 return;
722 }
723
724 // We found an ICmp, do some canonicalization.
725
726 // Adjust comparisons to use comparison with 0 if possible.
727 if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
728 switch (Pred) {
730 // Convert X > -1 to X >= 0
731 if (*Constant == -1) {
732 CC = RISCVCC::COND_GE;
733 RHS = RISCV::X0;
734 return;
735 }
736 break;
738 // Convert X < 1 to 0 >= X
739 if (*Constant == 1) {
740 CC = RISCVCC::COND_GE;
741 RHS = LHS;
742 LHS = RISCV::X0;
743 return;
744 }
745 break;
746 default:
747 break;
748 }
749 }
750
751 switch (Pred) {
752 default:
753 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
760 // These CCs are supported directly by RISC-V branches.
761 break;
766 // These CCs are not supported directly by RISC-V branches, but changing the
767 // direction of the CC and swapping LHS and RHS are.
768 Pred = CmpInst::getSwappedPredicate(Pred);
769 std::swap(LHS, RHS);
770 break;
771 }
772
773 CC = getRISCVCCFromICmp(Pred);
774}
775
776/// Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation
777/// \p GenericOpc, appropriate for the GPR register bank and of memory access
778/// size \p OpSize.
779static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
780 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
781 switch (OpSize) {
782 default:
783 llvm_unreachable("Unexpected memory size");
784 case 8:
785 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
786 case 16:
787 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
788 case 32:
789 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
790 case 64:
791 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
792 }
793}
794
795/// Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation
796/// \p GenericOpc, appropriate for the GPR register bank and of memory access
797/// size \p OpSize. \returns \p GenericOpc if the combination is unsupported.
798static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
799 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
800 switch (OpSize) {
801 case 8:
802 // Prefer unsigned due to no c.lb in Zcb.
803 return IsStore ? RISCV::SB : RISCV::LBU;
804 case 16:
805 return IsStore ? RISCV::SH : RISCV::LH;
806 case 32:
807 return IsStore ? RISCV::SW : RISCV::LW;
808 case 64:
809 return IsStore ? RISCV::SD : RISCV::LD;
810 }
811
812 return GenericOpc;
813}
814
815void RISCVInstructionSelector::addVectorLoadStoreOperands(
816 MachineInstr &I, SmallVectorImpl<Register> &SrcOps, unsigned &CurOp,
817 bool IsMasked, bool IsStridedOrIndexed, LLT *IndexVT) const {
818 // Base Pointer
819 auto PtrReg = I.getOperand(CurOp++).getReg();
820 SrcOps.push_back(PtrReg);
821
822 // Stride or Index
823 if (IsStridedOrIndexed) {
824 auto StrideReg = I.getOperand(CurOp++).getReg();
825 SrcOps.push_back(StrideReg);
826 if (IndexVT)
827 *IndexVT = MRI->getType(StrideReg);
828 }
829
830 // Mask
831 if (IsMasked) {
832 auto MaskReg = I.getOperand(CurOp++).getReg();
833 SrcOps.push_back(MaskReg);
834 }
835}
836
837bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
838 MachineInstr &I) const {
839 // Find the intrinsic ID.
840 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
841 // Select the instruction.
842 switch (IntrinID) {
843 default:
844 return false;
845 case Intrinsic::riscv_vlm:
846 case Intrinsic::riscv_vle:
847 case Intrinsic::riscv_vle_mask:
848 case Intrinsic::riscv_vlse:
849 case Intrinsic::riscv_vlse_mask: {
850 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
851 IntrinID == Intrinsic::riscv_vlse_mask;
852 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
853 IntrinID == Intrinsic::riscv_vlse_mask;
854 LLT VT = MRI->getType(I.getOperand(0).getReg());
855 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
856
857 // Result vector
858 const Register DstReg = I.getOperand(0).getReg();
859
860 // Sources
861 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
862 unsigned CurOp = 2;
863 SmallVector<Register, 4> SrcOps; // Source registers.
864
865 // Passthru
866 if (HasPassthruOperand) {
867 auto PassthruReg = I.getOperand(CurOp++).getReg();
868 SrcOps.push_back(PassthruReg);
869 } else {
870 SrcOps.push_back(Register(RISCV::NoRegister));
871 }
872
873 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
874
876 const RISCV::VLEPseudo *P =
877 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
878 static_cast<unsigned>(LMUL));
879
880 MachineInstrBuilder PseudoMI =
881 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
882 for (Register Reg : SrcOps)
883 PseudoMI.addReg(Reg);
884
885 // Select VL
886 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
887 for (auto &RenderFn : *VLOpFn)
888 RenderFn(PseudoMI);
889
890 // SEW
891 PseudoMI.addImm(Log2SEW);
892
893 // Policy
895 if (IsMasked)
896 Policy = I.getOperand(CurOp++).getImm();
897 PseudoMI.addImm(Policy);
898
899 // Memref
900 PseudoMI.cloneMemRefs(I);
901
902 I.eraseFromParent();
903 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
904 return true;
905 }
906 case Intrinsic::riscv_vloxei:
907 case Intrinsic::riscv_vloxei_mask:
908 case Intrinsic::riscv_vluxei:
909 case Intrinsic::riscv_vluxei_mask: {
910 bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
911 IntrinID == Intrinsic::riscv_vluxei_mask;
912 bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
913 IntrinID == Intrinsic::riscv_vloxei_mask;
914 LLT VT = MRI->getType(I.getOperand(0).getReg());
915 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
916
917 // Result vector
918 const Register DstReg = I.getOperand(0).getReg();
919
920 // Sources
921 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
922 unsigned CurOp = 2;
923 SmallVector<Register, 4> SrcOps; // Source registers.
924
925 // Passthru
926 if (HasPassthruOperand) {
927 auto PassthruReg = I.getOperand(CurOp++).getReg();
928 SrcOps.push_back(PassthruReg);
929 } else {
930 // Use NoRegister if there is no specified passthru.
931 SrcOps.push_back(Register());
932 }
933 LLT IndexVT;
934 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
935
937 RISCVVType::VLMUL IndexLMUL =
939 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
940 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
941 reportFatalUsageError("The V extension does not support EEW=64 for index "
942 "values when XLEN=32");
943 }
944 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
945 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
946 static_cast<unsigned>(IndexLMUL));
947
948 MachineInstrBuilder PseudoMI =
949 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo), DstReg);
950 for (Register Reg : SrcOps)
951 PseudoMI.addReg(Reg);
952
953 // Select VL
954 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
955 for (auto &RenderFn : *VLOpFn)
956 RenderFn(PseudoMI);
957
958 // SEW
959 PseudoMI.addImm(Log2SEW);
960
961 // Policy
963 if (IsMasked)
964 Policy = I.getOperand(CurOp++).getImm();
965 PseudoMI.addImm(Policy);
966
967 // Memref
968 PseudoMI.cloneMemRefs(I);
969
970 I.eraseFromParent();
971 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
972 return true;
973 }
974 case Intrinsic::riscv_vsm:
975 case Intrinsic::riscv_vse:
976 case Intrinsic::riscv_vse_mask:
977 case Intrinsic::riscv_vsse:
978 case Intrinsic::riscv_vsse_mask: {
979 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
980 IntrinID == Intrinsic::riscv_vsse_mask;
981 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
982 IntrinID == Intrinsic::riscv_vsse_mask;
983 LLT VT = MRI->getType(I.getOperand(1).getReg());
984 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
985
986 // Sources
987 unsigned CurOp = 1;
988 SmallVector<Register, 4> SrcOps; // Source registers.
989
990 // Store value
991 auto PassthruReg = I.getOperand(CurOp++).getReg();
992 SrcOps.push_back(PassthruReg);
993
994 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
995
997 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
998 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
999
1000 MachineInstrBuilder PseudoMI =
1001 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
1002 for (Register Reg : SrcOps)
1003 PseudoMI.addReg(Reg);
1004
1005 // Select VL
1006 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
1007 for (auto &RenderFn : *VLOpFn)
1008 RenderFn(PseudoMI);
1009
1010 // SEW
1011 PseudoMI.addImm(Log2SEW);
1012
1013 // Memref
1014 PseudoMI.cloneMemRefs(I);
1015
1016 I.eraseFromParent();
1017 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1018 return true;
1019 }
1020 case Intrinsic::riscv_vsoxei:
1021 case Intrinsic::riscv_vsoxei_mask:
1022 case Intrinsic::riscv_vsuxei:
1023 case Intrinsic::riscv_vsuxei_mask: {
1024 bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
1025 IntrinID == Intrinsic::riscv_vsuxei_mask;
1026 bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
1027 IntrinID == Intrinsic::riscv_vsoxei_mask;
1028 LLT VT = MRI->getType(I.getOperand(1).getReg());
1029 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
1030
1031 // Sources
1032 unsigned CurOp = 1;
1033 SmallVector<Register, 4> SrcOps; // Source registers.
1034
1035 // Store value
1036 auto PassthruReg = I.getOperand(CurOp++).getReg();
1037 SrcOps.push_back(PassthruReg);
1038
1039 LLT IndexVT;
1040 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);
1041
1043 RISCVVType::VLMUL IndexLMUL =
1045 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
1046 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
1047 reportFatalUsageError("The V extension does not support EEW=64 for index "
1048 "values when XLEN=32");
1049 }
1050 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
1051 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
1052 static_cast<unsigned>(IndexLMUL));
1053
1054 MachineInstrBuilder PseudoMI =
1055 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(P->Pseudo));
1056 for (Register Reg : SrcOps)
1057 PseudoMI.addReg(Reg);
1058
1059 // Select VL
1060 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
1061 for (auto &RenderFn : *VLOpFn)
1062 RenderFn(PseudoMI);
1063
1064 // SEW
1065 PseudoMI.addImm(Log2SEW);
1066
1067 // Memref
1068 PseudoMI.cloneMemRefs(I);
1069
1070 I.eraseFromParent();
1071 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1072 return true;
1073 }
1074 }
1075}
1076
1077bool RISCVInstructionSelector::selectIntrinsic(MachineInstr &I) const {
1078 // Find the intrinsic ID.
1079 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
1080 // Select the instruction.
1081 switch (IntrinID) {
1082 default:
1083 return false;
1084 case Intrinsic::riscv_vsetvli:
1085 case Intrinsic::riscv_vsetvlimax: {
1086
1087 bool VLMax = IntrinID == Intrinsic::riscv_vsetvlimax;
1088
1089 unsigned Offset = VLMax ? 2 : 3;
1090 unsigned SEW = RISCVVType::decodeVSEW(I.getOperand(Offset).getImm() & 0x7);
1091 RISCVVType::VLMUL VLMul =
1092 static_cast<RISCVVType::VLMUL>(I.getOperand(Offset + 1).getImm() & 0x7);
1093
1094 unsigned VTypeI = RISCVVType::encodeVTYPE(VLMul, SEW, /*TailAgnostic*/ true,
1095 /*MaskAgnostic*/ true);
1096
1097 Register DstReg = I.getOperand(0).getReg();
1098
1099 Register VLOperand;
1100 unsigned Opcode = RISCV::PseudoVSETVLI;
1101
1102 // Check if AVL is a constant that equals VLMAX.
1103 if (!VLMax) {
1104 Register AVLReg = I.getOperand(2).getReg();
1105 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1106 uint64_t AVL = AVLConst->Value.getZExtValue();
1107 if (auto VLEN = Subtarget->getRealVLen()) {
1108 if (*VLEN / RISCVVType::getSEWLMULRatio(SEW, VLMul) == AVL)
1109 VLMax = true;
1110 }
1111 }
1112
1113 if (mi_match(AVLReg, *MRI, m_AllOnes()))
1114 VLMax = true;
1115 }
1116
1117 if (VLMax) {
1118 VLOperand = Register(RISCV::X0);
1119 Opcode = RISCV::PseudoVSETVLIX0;
1120 } else {
1121 Register AVLReg = I.getOperand(2).getReg();
1122 VLOperand = AVLReg;
1123
1124 // Check if AVL is a small constant that can use PseudoVSETIVLI.
1125 if (auto AVLConst = getIConstantVRegValWithLookThrough(AVLReg, *MRI)) {
1126 uint64_t AVL = AVLConst->Value.getZExtValue();
1127 if (isUInt<5>(AVL)) {
1128 MachineInstr *PseudoMI =
1129 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1130 TII.get(RISCV::PseudoVSETIVLI), DstReg)
1131 .addImm(AVL)
1132 .addImm(VTypeI);
1133 I.eraseFromParent();
1134 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1135 return true;
1136 }
1137 }
1138 }
1139
1140 MachineInstr *PseudoMI =
1141 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
1142 .addReg(VLOperand)
1143 .addImm(VTypeI);
1144 I.eraseFromParent();
1145 constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
1146 return true;
1147 }
1148 }
1149}
1150
1151bool RISCVInstructionSelector::selectExtractSubvector(MachineInstr &MI) const {
1152 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR);
1153
1154 Register DstReg = MI.getOperand(0).getReg();
1155 Register SrcReg = MI.getOperand(1).getReg();
1156
1157 LLT DstTy = MRI->getType(DstReg);
1158 LLT SrcTy = MRI->getType(SrcReg);
1159
1160 unsigned Idx = static_cast<unsigned>(MI.getOperand(2).getImm());
1161
1162 MVT DstMVT = getMVTForLLT(DstTy);
1163 MVT SrcMVT = getMVTForLLT(SrcTy);
1164
1165 unsigned SubRegIdx;
1166 std::tie(SubRegIdx, Idx) =
1168 SrcMVT, DstMVT, Idx, &TRI);
1169
1170 if (Idx != 0)
1171 return false;
1172
1173 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(DstMVT);
1174 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1175 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1176 return false;
1177
1178 unsigned SrcRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(SrcMVT);
1179 const TargetRegisterClass *SrcRC = TRI.getRegClass(SrcRegClassID);
1180 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
1181 return false;
1182
1183 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1184 DstReg)
1185 .addReg(SrcReg, {}, SubRegIdx);
1186
1187 MI.eraseFromParent();
1188 return true;
1189}
1190
1191bool RISCVInstructionSelector::selectInsertSubVector(MachineInstr &MI) const {
1192 assert(MI.getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR);
1193
1194 Register DstReg = MI.getOperand(0).getReg();
1195 Register VecReg = MI.getOperand(1).getReg();
1196 Register SubVecReg = MI.getOperand(2).getReg();
1197
1198 LLT VecTy = MRI->getType(VecReg);
1199 LLT SubVecTy = MRI->getType(SubVecReg);
1200
1201 MVT VecMVT = getMVTForLLT(VecTy);
1202 MVT SubVecMVT = getMVTForLLT(SubVecTy);
1203
1204 unsigned Idx = static_cast<unsigned>(MI.getOperand(3).getImm());
1205
1206 unsigned SubRegIdx;
1207 std::tie(SubRegIdx, Idx) =
1209 VecMVT, SubVecMVT, Idx, &TRI);
1210
1211 // If the Idx hasn't been completely eliminated then this is a subvector
1212 // insert which doesn't naturally align to a vector register. These must
1213 // be handled using instructions to manipulate the vector registers.
1214 if (Idx != 0)
1215 return false;
1216
1217 // Constrain dst
1218 unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(VecMVT);
1219 const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID);
1220 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1221 return false;
1222
1223 // If we haven't set a SubRegIdx, then we must be going between
1224 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy.
1225 if (SubRegIdx == RISCV::NoSubRegister) {
1227 DstRegClassID &&
1228 "Unexpected subvector insert");
1229 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(TargetOpcode::COPY),
1230 DstReg)
1231 .addReg(SubVecReg);
1232 MI.eraseFromParent();
1233 return true;
1234 }
1235
1236 // Use INSERT_SUBREG to insert the subvector into the vector at the
1237 // appropriate subregister index.
1238 MachineInstr *Ins = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1239 TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1240 .addReg(VecReg)
1241 .addReg(SubVecReg)
1242 .addImm(SubRegIdx);
1243
1244 MI.eraseFromParent();
1246 return true;
1247}
1248
1249bool RISCVInstructionSelector::select(MachineInstr &MI) {
1250 preISelLower(MI);
1251 const unsigned Opc = MI.getOpcode();
1252
1253 if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
1254 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
1255 const Register DefReg = MI.getOperand(0).getReg();
1256 const LLT DefTy = MRI->getType(DefReg);
1257
1258 const RegClassOrRegBank &RegClassOrBank =
1259 MRI->getRegClassOrRegBank(DefReg);
1260
1261 const TargetRegisterClass *DefRC =
1263 if (!DefRC) {
1264 if (!DefTy.isValid()) {
1265 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
1266 return false;
1267 }
1268
1269 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
1270 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB, STI.is64Bit());
1271 if (!DefRC) {
1272 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
1273 return false;
1274 }
1275 }
1276
1277 MI.setDesc(TII.get(TargetOpcode::PHI));
1278 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
1279 }
1280
1281 // Certain non-generic instructions also need some special handling.
1282 if (MI.isCopy())
1283 return selectCopy(MI);
1284
1285 return true;
1286 }
1287
1288 if (selectImpl(MI, *CoverageInfo))
1289 return true;
1290
1291 switch (Opc) {
1292 case TargetOpcode::G_ANYEXT:
1293 case TargetOpcode::G_PTRTOINT:
1294 case TargetOpcode::G_INTTOPTR:
1295 case TargetOpcode::G_TRUNC:
1296 case TargetOpcode::G_FREEZE:
1297 return selectCopy(MI);
1298 case TargetOpcode::G_CONSTANT: {
1299 Register DstReg = MI.getOperand(0).getReg();
1300 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1301
1302 if (!materializeImm(DstReg, Imm, MI))
1303 return false;
1304
1305 MI.eraseFromParent();
1306 return true;
1307 }
1308 case TargetOpcode::G_ZEXT:
1309 case TargetOpcode::G_SEXT: {
1310 bool IsSigned = Opc != TargetOpcode::G_ZEXT;
1311 Register DstReg = MI.getOperand(0).getReg();
1312 Register SrcReg = MI.getOperand(1).getReg();
1313 LLT SrcTy = MRI->getType(SrcReg);
1314 unsigned SrcSize = SrcTy.getSizeInBits();
1315
1316 if (SrcTy.isVector())
1317 return false; // Should be handled by imported patterns.
1318
1319 assert((*RBI.getRegBank(DstReg, *MRI, TRI)).getID() ==
1320 RISCV::GPRBRegBankID &&
1321 "Unexpected ext regbank");
1322
1323 // Use addiw SrcReg, 0 (sext.w) for i32.
1324 if (IsSigned && SrcSize == 32) {
1325 MI.setDesc(TII.get(RISCV::ADDIW));
1326 MI.addOperand(MachineOperand::CreateImm(0));
1328 return true;
1329 }
1330
1331 // Use add.uw SrcReg, X0 (zext.w) for i32 with Zba.
1332 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
1333 MI.setDesc(TII.get(RISCV::ADD_UW));
1334 MI.addOperand(MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false));
1336 return true;
1337 }
1338
1339 // Use sext.h/zext.h for i16 with Zbb.
1340 if (SrcSize == 16 &&
1341 (STI.hasStdExtZbb() || (!IsSigned && STI.hasStdExtZbkb()))) {
1342 MI.setDesc(TII.get(IsSigned ? RISCV::SEXT_H
1343 : STI.isRV64() ? RISCV::ZEXT_H_RV64
1344 : RISCV::ZEXT_H_RV32));
1346 return true;
1347 }
1348
1349 // Fall back to shift pair.
1350 Register ShiftLeftReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1351 MachineInstr *ShiftLeft = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1352 TII.get(RISCV::SLLI), ShiftLeftReg)
1353 .addReg(SrcReg)
1354 .addImm(STI.getXLen() - SrcSize);
1355 constrainSelectedInstRegOperands(*ShiftLeft, TII, TRI, RBI);
1356 MachineInstr *ShiftRight =
1357 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1358 TII.get(IsSigned ? RISCV::SRAI : RISCV::SRLI), DstReg)
1359 .addReg(ShiftLeftReg)
1360 .addImm(STI.getXLen() - SrcSize);
1361 constrainSelectedInstRegOperands(*ShiftRight, TII, TRI, RBI);
1362 MI.eraseFromParent();
1363 return true;
1364 }
1365 case TargetOpcode::G_FCONSTANT: {
1366 // TODO: Use constant pool for complex constants.
1367 Register DstReg = MI.getOperand(0).getReg();
1368 const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
1369 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1370 if (Size == 16 || Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
1371 Register GPRReg;
1372 if (FPimm.isPosZero()) {
1373 GPRReg = RISCV::X0;
1374 } else {
1375 GPRReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1376 APInt Imm = FPimm.bitcastToAPInt();
1377 if (!materializeImm(GPRReg, Imm.getSExtValue(), MI))
1378 return false;
1379 }
1380
1381 unsigned Opcode = Size == 64 ? RISCV::FMV_D_X
1382 : Size == 32 ? RISCV::FMV_W_X
1383 : RISCV::FMV_H_X;
1384 MachineInstr *FMV = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1385 TII.get(Opcode), DstReg)
1386 .addReg(GPRReg);
1388 } else {
1389 // s64 on rv32
1390 assert(Size == 64 && !Subtarget->is64Bit() &&
1391 "Unexpected size or subtarget");
1392
1393 if (FPimm.isPosZero()) {
1394 // Optimize +0.0 to use fcvt.d.w
1395 MachineInstr *FCVT = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1396 TII.get(RISCV::FCVT_D_W), DstReg)
1397 .addReg(RISCV::X0)
1400
1401 MI.eraseFromParent();
1402 return true;
1403 }
1404
1405 // Split into two pieces and build through the stack.
1406 Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1407 Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1408 APInt Imm = FPimm.bitcastToAPInt();
1409 if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
1410 MI))
1411 return false;
1412 if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MI))
1413 return false;
1414 MachineInstr *PairF64 =
1415 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1416 TII.get(RISCV::BuildPairF64Pseudo), DstReg)
1417 .addReg(GPRRegLow)
1418 .addReg(GPRRegHigh);
1419 constrainSelectedInstRegOperands(*PairF64, TII, TRI, RBI);
1420 }
1421
1422 MI.eraseFromParent();
1423 return true;
1424 }
1425 case TargetOpcode::G_GLOBAL_VALUE: {
1426 auto *GV = MI.getOperand(1).getGlobal();
1427 if (GV->isThreadLocal()) {
1428 // TODO: implement this case.
1429 return false;
1430 }
1431
1432 return selectAddr(MI, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1433 }
1434 case TargetOpcode::G_JUMP_TABLE:
1435 case TargetOpcode::G_CONSTANT_POOL:
1436 return selectAddr(MI);
1437 case TargetOpcode::G_BRCOND: {
1438 Register LHS, RHS;
1440 getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
1441
1442 MachineInstr *Bcc = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1443 TII.get(RISCVCC::getBrCond(CC)))
1444 .addReg(LHS)
1445 .addReg(RHS)
1446 .addMBB(MI.getOperand(1).getMBB());
1447 MI.eraseFromParent();
1449 return true;
1450 }
1451 case TargetOpcode::G_BRINDIRECT:
1452 MI.setDesc(TII.get(RISCV::PseudoBRIND));
1453 MI.addOperand(MachineOperand::CreateImm(0));
1455 return true;
1456 case TargetOpcode::G_SELECT:
1457 return selectSelect(MI);
1458 case TargetOpcode::G_FCMP:
1459 return selectFPCompare(MI);
1460 case TargetOpcode::G_FENCE: {
1461 AtomicOrdering FenceOrdering =
1462 static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
1463 SyncScope::ID FenceSSID =
1464 static_cast<SyncScope::ID>(MI.getOperand(1).getImm());
1465 emitFence(FenceOrdering, FenceSSID, MI);
1466 MI.eraseFromParent();
1467 return true;
1468 }
1469 case TargetOpcode::G_IMPLICIT_DEF:
1470 return selectImplicitDef(MI);
1471 case TargetOpcode::G_UNMERGE_VALUES:
1472 return selectUnmergeValues(MI);
1473 case TargetOpcode::G_LOAD:
1474 case TargetOpcode::G_STORE: {
1475 GLoadStore &LdSt = cast<GLoadStore>(MI);
1476 const Register ValReg = LdSt.getReg(0);
1477 const Register PtrReg = LdSt.getPointerReg();
1478 LLT PtrTy = MRI->getType(PtrReg);
1479
1480 const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
1481 if (RB.getID() != RISCV::GPRBRegBankID)
1482 return false;
1483
1484#ifndef NDEBUG
1485 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, *MRI, TRI);
1486 // Check that the pointer register is valid.
1487 assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
1488 "Load/Store pointer operand isn't a GPR");
1489 assert(PtrTy.isPointer() && "Load/Store pointer operand isn't a pointer");
1490#endif
1491
1492 // Can only handle AddressSpace 0.
1493 if (PtrTy.getAddressSpace() != 0)
1494 return false;
1495
1496 unsigned MemSize = LdSt.getMemSizeInBits().getValue();
1497 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
1498
1499 if (isStrongerThanMonotonic(Order)) {
1500 MI.setDesc(TII.get(selectZalasrLoadStoreOp(Opc, MemSize)));
1502 return true;
1503 }
1504
1505 const unsigned NewOpc = selectRegImmLoadStoreOp(MI.getOpcode(), MemSize);
1506 if (NewOpc == MI.getOpcode())
1507 return false;
1508
1509 // Check if we can fold anything into the addressing mode.
1510 auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
1511 if (!AddrModeFns)
1512 return false;
1513
1514 // Folded something. Create a new instruction and return it.
1515 MachineInstrBuilder NewInst =
1516 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(NewOpc));
1517 NewInst.setMIFlags(MI.getFlags());
1518 if (isa<GStore>(MI))
1519 NewInst.addUse(ValReg);
1520 else
1521 NewInst.addDef(ValReg);
1522 NewInst.cloneMemRefs(MI);
1523 for (auto &Fn : *AddrModeFns)
1524 Fn(NewInst);
1525 MI.eraseFromParent();
1526
1527 constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
1528 return true;
1529 }
1530 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1531 return selectIntrinsicWithSideEffects(MI);
1532 case TargetOpcode::G_INTRINSIC:
1533 return selectIntrinsic(MI);
1534 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1535 return selectExtractSubvector(MI);
1536 case TargetOpcode::G_INSERT_SUBVECTOR:
1537 return selectInsertSubVector(MI);
1538 default:
1539 return false;
1540 }
1541}
1542
1543bool RISCVInstructionSelector::selectUnmergeValues(MachineInstr &MI) const {
1544 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1545
1546 if (!Subtarget->hasStdExtZfa())
1547 return false;
1548
1549 // Split F64 Src into two s32 parts
1550 if (MI.getNumOperands() != 3)
1551 return false;
1552 Register Src = MI.getOperand(2).getReg();
1553 Register Lo = MI.getOperand(0).getReg();
1554 Register Hi = MI.getOperand(1).getReg();
1555 if (!isRegInFprb(Src) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
1556 return false;
1557
1558 MachineInstr *ExtractLo = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1559 TII.get(RISCV::FMV_X_W_FPR64), Lo)
1560 .addReg(Src);
1561 constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI);
1562
1563 MachineInstr *ExtractHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1564 TII.get(RISCV::FMVH_X_D), Hi)
1565 .addReg(Src);
1566 constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI);
1567
1568 MI.eraseFromParent();
1569 return true;
1570}
1571
1572bool RISCVInstructionSelector::replacePtrWithInt(MachineInstr &MI,
1573 unsigned OpIdx) {
1574 MachineOperand &Op = MI.getOperand(OpIdx);
1575 Register PtrReg = Op.getReg();
1576 assert(MRI->getType(PtrReg).isPointer() && "Operand is not a pointer!");
1577
1578 const LLT sXLen = LLT::scalar(STI.getXLen());
1579 Register IntReg = MRI->createGenericVirtualRegister(sXLen);
1580 MRI->setRegBank(IntReg, RBI.getRegBank(RISCV::GPRBRegBankID));
1581 MachineInstr *PtrToInt = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1582 TII.get(TargetOpcode::G_PTRTOINT), IntReg)
1583 .addReg(PtrReg);
1584 Op.setReg(IntReg);
1585 return select(*PtrToInt);
1586}
1587
1588void RISCVInstructionSelector::preISelLower(MachineInstr &MI) {
1589 switch (MI.getOpcode()) {
1590 case TargetOpcode::G_PTR_ADD: {
1591 Register DstReg = MI.getOperand(0).getReg();
1592 const LLT sXLen = LLT::scalar(STI.getXLen());
1593
1594 replacePtrWithInt(MI, 1);
1595 MI.setDesc(TII.get(TargetOpcode::G_ADD));
1596 MRI->setType(DstReg, sXLen);
1597 break;
1598 }
1599 case TargetOpcode::G_PTRMASK: {
1600 Register DstReg = MI.getOperand(0).getReg();
1601 const LLT sXLen = LLT::scalar(STI.getXLen());
1602 replacePtrWithInt(MI, 1);
1603 MI.setDesc(TII.get(TargetOpcode::G_AND));
1604 MRI->setType(DstReg, sXLen);
1605 break;
1606 }
1607 }
1608}
1609
1610void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1611 const MachineInstr &MI,
1612 int OpIdx) const {
1613 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1614 "Expected G_CONSTANT");
1615 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1616 MIB.addImm(-CstVal);
1617}
1618
1619void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1620 const MachineInstr &MI,
1621 int OpIdx) const {
1622 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1623 "Expected G_CONSTANT");
1624 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1625 MIB.addImm(STI.getXLen() - CstVal);
1626}
1627
1628void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1629 const MachineInstr &MI,
1630 int OpIdx) const {
1631 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1632 "Expected G_CONSTANT");
1633 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1634 MIB.addImm(32 - CstVal);
1635}
1636
1637void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1638 const MachineInstr &MI,
1639 int OpIdx) const {
1640 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1641 "Expected G_CONSTANT");
1642 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1643 MIB.addImm(CstVal + 1);
1644}
1645
1646void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1647 const MachineInstr &MI,
1648 int OpIdx) const {
1649 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1650 "Expected G_CONSTANT");
1651 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1653}
1654
1655void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1656 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
1657 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1658 "Expected G_CONSTANT");
1659 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1660 MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
1661}
1662
1663void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1664 const MachineInstr &MI,
1665 int OpIdx) const {
1666 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1667 "Expected G_CONSTANT");
1668 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1669 int64_t Adj = Imm < 0 ? -2048 : 2047;
1670 MIB.addImm(Imm - Adj);
1671}
1672
1673void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1674 const MachineInstr &MI,
1675 int OpIdx) const {
1676 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1677 "Expected G_CONSTANT");
1678 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1679 MIB.addImm(Imm);
1680}
1681
1682bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
1683 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
1684}
1685
1686bool RISCVInstructionSelector::isRegInFprb(Register Reg) const {
1687 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID;
1688}
1689
1690bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
1691 Register DstReg = MI.getOperand(0).getReg();
1692
1693 if (DstReg.isPhysical())
1694 return true;
1695
1696 const TargetRegisterClass *DstRC =
1697 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
1698
1699 assert(DstRC &&
1700 "Register class not available for LLT, register bank combination");
1701
1702 // No need to constrain SrcReg. It will get constrained when
1703 // we hit another of its uses or its defs.
1704 // Copies do not have constraints.
1705 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1706 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1707 << " operand\n");
1708 return false;
1709 }
1710
1711 MI.setDesc(TII.get(RISCV::COPY));
1712 return true;
1713}
1714
1715bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI) const {
1716 assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1717
1718 const Register DstReg = MI.getOperand(0).getReg();
1719 const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
1720 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI), STI.is64Bit());
1721
1722 assert(DstRC &&
1723 "Register class not available for LLT, register bank combination");
1724
1725 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1726 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1727 << " operand\n");
1728 }
1729 MI.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1730 return true;
1731}
1732
1733bool RISCVInstructionSelector::materializeImm(Register DstReg, int64_t Imm,
1734 MachineInstr &MI) const {
1735 if (Imm == 0) {
1736 MachineBasicBlock &MBB = *MI.getParent();
1737 DebugLoc DL = MI.getDebugLoc();
1738 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::COPY), DstReg).addReg(RISCV::X0);
1739 RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, *MRI);
1740 return true;
1741 }
1742
1744 return materializeInstSeq(DstReg, Seq, MI);
1745}
1746
1747bool RISCVInstructionSelector::materializeInstSeq(
1748 Register DstReg, const RISCVMatInt::InstSeq &Seq, MachineInstr &MI) const {
1749 assert(!Seq.empty() && "materializeInstSeq requires a non-empty sequence");
1750
1751 MachineBasicBlock &MBB = *MI.getParent();
1752 DebugLoc DL = MI.getDebugLoc();
1753 unsigned NumInsts = Seq.size();
1754 Register SrcReg = RISCV::X0;
1755
1756 for (unsigned i = 0; i < NumInsts; i++) {
1757 Register TmpReg = i < NumInsts - 1
1758 ? MRI->createVirtualRegister(&RISCV::GPRRegClass)
1759 : DstReg;
1760 const RISCVMatInt::Inst &I = Seq[i];
1761 MachineInstr *Result;
1762
1763 switch (I.getOpndKind()) {
1764 case RISCVMatInt::Imm:
1765 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1766 .addImm(I.getImm());
1767 break;
1768 case RISCVMatInt::RegX0:
1769 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1770 .addReg(SrcReg)
1771 .addReg(RISCV::X0);
1772 break;
1774 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1775 .addReg(SrcReg)
1776 .addReg(SrcReg);
1777 break;
1779 Result = BuildMI(MBB, MI, DL, TII.get(I.getOpcode()), TmpReg)
1780 .addReg(SrcReg)
1781 .addImm(I.getImm());
1782 break;
1783 }
1784
1786
1787 SrcReg = TmpReg;
1788 }
1789
1790 return true;
1791}
1792
1793InstructionSelector::ComplexRendererFns
1794RISCVInstructionSelector::computeConstAddr(int64_t CVal, bool IsPrefetch,
1795 Register OrigBase) const {
1796 // Split the constant into a materialized high part (the base) and
1797 // a simm12 low part (the offset). For prefetch the low part
1798 // must additionally be a multiple of 32 (simm12_lsb00000).
1799 int64_t Lo12 = SignExtend64<12>(CVal);
1800 int64_t Hi = (uint64_t)CVal - (uint64_t)Lo12;
1801 auto emit = [&](ConstAddrPlan Plan) -> ComplexRendererFns {
1802 return {{[=](MachineInstrBuilder &MIB) {
1803 MIB.addReg(materializeConstBase(MIB, Plan, OrigBase));
1804 },
1805 [=](MachineInstrBuilder &MIB) { MIB.addImm(Plan.Lo12); }}};
1806 };
1807 if (!Subtarget->is64Bit() || isInt<32>(Hi)) {
1808 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1809 return std::nullopt;
1810 ConstAddrPlan Plan;
1811 Plan.Lo12 = Lo12;
1812 if (Hi) {
1813 Plan.Kind = ConstAddrPlan::LUI;
1814 Plan.Hi20 = (Hi >> 12) & 0xfffff;
1815 }
1816 return emit(std::move(Plan));
1817 }
1818
1819 // Otherwise ask constant materialization how it would handle the constant
1820 // and fold the trailing ADDI into the offset.
1821 RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(CVal, *Subtarget);
1822 if (Seq.back().getOpcode() != RISCV::ADDI)
1823 return std::nullopt;
1824 Lo12 = Seq.back().getImm();
1825 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1826 return std::nullopt;
1827 Seq.pop_back();
1828 if (Seq.empty())
1829 return std::nullopt;
1830 ConstAddrPlan Plan;
1831 Plan.Kind = ConstAddrPlan::InstSeq;
1832 Plan.Seq = std::move(Seq);
1833 Plan.Lo12 = Lo12;
1834 return emit(std::move(Plan));
1835}
1836
1838RISCVInstructionSelector::materializeConstBase(MachineInstrBuilder &MIB,
1839 const ConstAddrPlan &Plan,
1840 Register OrigBase) const {
1841 MachineBasicBlock &MBB = *MIB->getParent();
1842 DebugLoc DL = MIB->getDebugLoc();
1843 MachineInstr &InsertPt = *MIB.getInstr();
1844
1845 Register HiReg = RISCV::X0;
1846 switch (Plan.Kind) {
1847 case ConstAddrPlan::X0:
1848 break;
1849 case ConstAddrPlan::LUI: {
1850 HiReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1851 MachineInstr *LUI = BuildMI(MBB, InsertPt, DL, TII.get(RISCV::LUI), HiReg)
1852 .addImm(Plan.Hi20);
1854 break;
1855 }
1856 case ConstAddrPlan::InstSeq: {
1857 HiReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1858 materializeInstSeq(HiReg, Plan.Seq, InsertPt);
1859 break;
1860 }
1861 }
1862
1863 // For G_PTR_ADD + large constant, add the original base to the materialized
1864 // high part.
1865 if (OrigBase.isValid() && HiReg != RISCV::X0) {
1866 Register BaseReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1867 MachineInstr *Add = BuildMI(MBB, InsertPt, DL, TII.get(RISCV::ADD), BaseReg)
1868 .addReg(OrigBase)
1869 .addReg(HiReg);
1871 return BaseReg;
1872 }
1873 return OrigBase.isValid() ? OrigBase : HiReg;
1874}
1875
1876bool RISCVInstructionSelector::selectAddr(MachineInstr &MI, bool IsLocal,
1877 bool IsExternWeak) const {
1878 assert((MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1879 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1880 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1881 "Unexpected opcode");
1882
1883 const MachineOperand &DispMO = MI.getOperand(1);
1884
1885 Register DefReg = MI.getOperand(0).getReg();
1886 const LLT DefTy = MRI->getType(DefReg);
1887
1888 // When HWASAN is used and tagging of global variables is enabled
1889 // they should be accessed via the GOT, since the tagged address of a global
1890 // is incompatible with existing code models. This also applies to non-pic
1891 // mode.
1892 if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
1893 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1894 // Use PC-relative addressing to access the symbol. This generates the
1895 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
1896 // %pcrel_lo(auipc)).
1897 MI.setDesc(TII.get(RISCV::PseudoLLA));
1899 return true;
1900 }
1901
1902 // Use PC-relative addressing to access the GOT for this symbol, then
1903 // load the address from the GOT. This generates the pattern (PseudoLGA
1904 // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
1905 // %pcrel_lo(auipc))).
1906 MachineFunction &MF = *MI.getParent()->getParent();
1907 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1911 DefTy, Align(DefTy.getSizeInBits() / 8));
1912
1913 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1914 TII.get(RISCV::PseudoLGA), DefReg)
1915 .addDisp(DispMO, 0)
1916 .addMemOperand(MemOp);
1917
1919
1920 MI.eraseFromParent();
1921 return true;
1922 }
1923
1924 switch (TM.getCodeModel()) {
1925 default: {
1927 "Unsupported code model for lowering", MI);
1928 return false;
1929 }
1930 case CodeModel::Small: {
1931 // Must lie within a single 2 GiB address range and must lie between
1932 // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
1933 // (lui %hi(sym)) %lo(sym)).
1934 Register AddrHiDest = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1935 MachineInstr *AddrHi = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1936 TII.get(RISCV::LUI), AddrHiDest)
1937 .addDisp(DispMO, 0, RISCVII::MO_HI);
1938
1940
1941 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1942 TII.get(RISCV::ADDI), DefReg)
1943 .addReg(AddrHiDest)
1944 .addDisp(DispMO, 0, RISCVII::MO_LO);
1945
1947
1948 MI.eraseFromParent();
1949 return true;
1950 }
1951 case CodeModel::Medium:
1952 // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
1953 // relocation needs to reference a label that points to the auipc
1954 // instruction itself, not the global. This cannot be done inside the
1955 // instruction selector.
1956 if (IsExternWeak) {
1957 // An extern weak symbol may be undefined, i.e. have value 0, which may
1958 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
1959 // symbol. This generates the pattern (PseudoLGA sym), which expands to
1960 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
1961 MachineFunction &MF = *MI.getParent()->getParent();
1962 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1966 DefTy, Align(DefTy.getSizeInBits() / 8));
1967
1968 MachineInstr *Result = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
1969 TII.get(RISCV::PseudoLGA), DefReg)
1970 .addDisp(DispMO, 0)
1971 .addMemOperand(MemOp);
1972
1974
1975 MI.eraseFromParent();
1976 return true;
1977 }
1978
1979 // Generate a sequence for accessing addresses within any 2GiB range
1980 // within the address space. This generates the pattern (PseudoLLA sym),
1981 // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
1982 MI.setDesc(TII.get(RISCV::PseudoLLA));
1984 return true;
1985 }
1986
1987 return false;
1988}
1989
1990bool RISCVInstructionSelector::selectSelect(MachineInstr &MI) const {
1991 auto &SelectMI = cast<GSelect>(MI);
1992
1993 Register LHS, RHS;
1995 getOperandsForBranch(SelectMI.getCondReg(), CC, LHS, RHS, *MRI);
1996
1997 Register DstReg = SelectMI.getReg(0);
1998
1999 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
2000 if (RBI.getRegBank(DstReg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
2001 unsigned Size = MRI->getType(DstReg).getSizeInBits();
2002 Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
2003 : RISCV::Select_FPR64_Using_CC_GPR;
2004 }
2005
2006 MachineInstr *Result =
2007 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII.get(Opc))
2008 .addDef(DstReg)
2009 .addReg(LHS)
2010 .addReg(RHS)
2011 .addImm(CC)
2012 .addReg(SelectMI.getTrueReg())
2013 .addReg(SelectMI.getFalseReg());
2014 MI.eraseFromParent();
2016 return true;
2017}
2018
2019// Convert an FCMP predicate to one of the supported F or D instructions.
2020static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
2021 assert((Size == 16 || Size == 32 || Size == 64) && "Unsupported size");
2022 switch (Pred) {
2023 default:
2024 llvm_unreachable("Unsupported predicate");
2025 case CmpInst::FCMP_OLT:
2026 return Size == 16 ? RISCV::FLT_H : Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
2027 case CmpInst::FCMP_OLE:
2028 return Size == 16 ? RISCV::FLE_H : Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
2029 case CmpInst::FCMP_OEQ:
2030 return Size == 16 ? RISCV::FEQ_H : Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
2031 }
2032}
2033
2034// Try legalizing an FCMP by swapping or inverting the predicate to one that
2035// is supported.
2037 CmpInst::Predicate &Pred, bool &NeedInvert) {
2038 auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
2039 return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
2040 Pred == CmpInst::FCMP_OEQ;
2041 };
2042
2043 assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
2044
2046 if (isLegalFCmpPredicate(InvPred)) {
2047 Pred = InvPred;
2048 std::swap(LHS, RHS);
2049 return true;
2050 }
2051
2052 InvPred = CmpInst::getInversePredicate(Pred);
2053 NeedInvert = true;
2054 if (isLegalFCmpPredicate(InvPred)) {
2055 Pred = InvPred;
2056 return true;
2057 }
2058 InvPred = CmpInst::getSwappedPredicate(InvPred);
2059 if (isLegalFCmpPredicate(InvPred)) {
2060 Pred = InvPred;
2061 std::swap(LHS, RHS);
2062 return true;
2063 }
2064
2065 return false;
2066}
2067
2068// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
2069// the result in DstReg.
2070// FIXME: Maybe we should expand this earlier.
2071bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI) const {
2072 auto &CmpMI = cast<GFCmp>(MI);
2073 CmpInst::Predicate Pred = CmpMI.getCond();
2074
2075 Register DstReg = CmpMI.getReg(0);
2076 Register LHS = CmpMI.getLHSReg();
2077 Register RHS = CmpMI.getRHSReg();
2078
2079 unsigned Size = MRI->getType(LHS).getSizeInBits();
2080 assert((Size == 16 || Size == 32 || Size == 64) && "Unexpected size");
2081
2082 Register TmpReg = DstReg;
2083
2084 bool NeedInvert = false;
2085 // First try swapping operands or inverting.
2086 if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
2087 if (NeedInvert)
2088 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2089 MachineInstr *Cmp = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2090 TII.get(getFCmpOpcode(Pred, Size)), TmpReg)
2091 .addReg(LHS)
2092 .addReg(RHS);
2094 } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
2095 // fcmp one LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
2096 NeedInvert = Pred == CmpInst::FCMP_UEQ;
2097 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2098 MachineInstr *Cmp1 =
2099 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2100 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp1Reg)
2101 .addReg(LHS)
2102 .addReg(RHS);
2104 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2105 MachineInstr *Cmp2 =
2106 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2107 TII.get(getFCmpOpcode(CmpInst::FCMP_OLT, Size)), Cmp2Reg)
2108 .addReg(RHS)
2109 .addReg(LHS);
2111 if (NeedInvert)
2112 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2113 MachineInstr *Or = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2114 TII.get(RISCV::OR), TmpReg)
2115 .addReg(Cmp1Reg)
2116 .addReg(Cmp2Reg);
2118 } else if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
2119 // fcmp ord LHS, RHS => (AND (FEQ LHS, LHS), (FEQ RHS, RHS))
2120 // If LHS and RHS are the same, a single FEQ suffices.
2121 NeedInvert = Pred == CmpInst::FCMP_UNO;
2122 if (NeedInvert)
2123 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2124 if (LHS == RHS) {
2125 MachineInstr *Cmp =
2126 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2127 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), TmpReg)
2128 .addReg(LHS)
2129 .addReg(LHS);
2131 } else {
2132 Register Cmp1Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2133 MachineInstr *Cmp1 =
2134 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2135 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp1Reg)
2136 .addReg(LHS)
2137 .addReg(LHS);
2139 Register Cmp2Reg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
2140 MachineInstr *Cmp2 =
2141 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2142 TII.get(getFCmpOpcode(CmpInst::FCMP_OEQ, Size)), Cmp2Reg)
2143 .addReg(RHS)
2144 .addReg(RHS);
2146 MachineInstr *And = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2147 TII.get(RISCV::AND), TmpReg)
2148 .addReg(Cmp1Reg)
2149 .addReg(Cmp2Reg);
2151 }
2152 } else
2153 llvm_unreachable("Unhandled predicate");
2154
2155 // Emit an XORI to invert the result if needed.
2156 if (NeedInvert) {
2157 MachineInstr *Xor = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
2158 TII.get(RISCV::XORI), DstReg)
2159 .addReg(TmpReg)
2160 .addImm(1);
2162 }
2163
2164 MI.eraseFromParent();
2165 return true;
2166}
2167
2168void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
2169 SyncScope::ID FenceSSID,
2170 MachineInstr &MI) const {
2171 MachineBasicBlock &MBB = *MI.getParent();
2172 DebugLoc DL = MI.getDebugLoc();
2173
2174 if (STI.hasStdExtZtso()) {
2175 // The only fence that needs an instruction is a sequentially-consistent
2176 // cross-thread fence.
2177 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
2178 FenceSSID == SyncScope::System) {
2179 // fence rw, rw
2180 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE))
2183 return;
2184 }
2185
2186 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
2187 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2188 return;
2189 }
2190
2191 // singlethread fences only synchronize with signal handlers on the same
2192 // thread and thus only need to preserve instruction order, not actually
2193 // enforce memory ordering.
2194 if (FenceSSID == SyncScope::SingleThread) {
2195 BuildMI(MBB, MI, DL, TII.get(TargetOpcode::MEMBARRIER));
2196 return;
2197 }
2198
2199 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
2200 // Manual: Volume I.
2201 unsigned Pred, Succ;
2202 switch (FenceOrdering) {
2203 default:
2204 llvm_unreachable("Unexpected ordering");
2205 case AtomicOrdering::AcquireRelease:
2206 // fence acq_rel -> fence.tso
2207 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE_TSO));
2208 return;
2209 case AtomicOrdering::Acquire:
2210 // fence acquire -> fence r, rw
2211 Pred = RISCVFenceField::R;
2213 break;
2214 case AtomicOrdering::Release:
2215 // fence release -> fence rw, w
2217 Succ = RISCVFenceField::W;
2218 break;
2219 case AtomicOrdering::SequentiallyConsistent:
2220 // fence seq_cst -> fence rw, rw
2223 break;
2224 }
2225 BuildMI(MBB, MI, DL, TII.get(RISCV::FENCE)).addImm(Pred).addImm(Succ);
2226}
2227
2228namespace llvm {
2229InstructionSelector *
2231 const RISCVSubtarget &Subtarget,
2232 const RISCVRegisterBankInfo &RBI) {
2233 return new RISCVInstructionSelector(TM, Subtarget, RBI);
2234}
2235} // 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:1475
bool isPosZero() const
Definition APFloat.h:1594
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
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
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 isValid() const
Definition Register.h:112
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
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:326
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.
@ Add
Sum 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 int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:567
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.