LLVM 22.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:
58 getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
59
60 static constexpr unsigned MaxRecursionDepth = 6;
61
62 bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits,
63 const unsigned Depth = 0) const;
64 bool hasAllHUsers(const MachineInstr &MI) const {
65 return hasAllNBitUsers(MI, 16);
66 }
67 bool hasAllWUsers(const MachineInstr &MI) const {
68 return hasAllNBitUsers(MI, 32);
69 }
70
71 bool isRegInGprb(Register Reg) const;
72 bool isRegInFprb(Register Reg) const;
73
74 // tblgen-erated 'select' implementation, used as the initial selector for
75 // the patterns that don't require complex C++.
76 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
77
78 // A lowering phase that runs before any selection attempts.
79 // Returns true if the instruction was modified.
80 void preISelLower(MachineInstr &MI, MachineIRBuilder &MIB);
81
82 bool replacePtrWithInt(MachineOperand &Op, MachineIRBuilder &MIB);
83
84 // Custom selection methods
85 bool selectCopy(MachineInstr &MI) const;
86 bool selectImplicitDef(MachineInstr &MI, MachineIRBuilder &MIB) const;
87 bool materializeImm(Register Reg, int64_t Imm, MachineIRBuilder &MIB) const;
88 bool selectAddr(MachineInstr &MI, MachineIRBuilder &MIB, bool IsLocal = true,
89 bool IsExternWeak = false) const;
90 bool selectSelect(MachineInstr &MI, MachineIRBuilder &MIB) const;
91 bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB) const;
92 void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
93 MachineIRBuilder &MIB) const;
95 void addVectorLoadStoreOperands(MachineInstr &I,
97 unsigned &CurOp, bool IsMasked,
98 bool IsStrided) const;
99 bool selectIntrinsicWithSideEffects(MachineInstr &I,
100 MachineIRBuilder &MIB) const;
101
102 ComplexRendererFns selectShiftMask(MachineOperand &Root,
103 unsigned ShiftWidth) const;
104 ComplexRendererFns selectShiftMaskXLen(MachineOperand &Root) const {
105 return selectShiftMask(Root, STI.getXLen());
106 }
107 ComplexRendererFns selectShiftMask32(MachineOperand &Root) const {
108 return selectShiftMask(Root, 32);
109 }
110 ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
111
112 ComplexRendererFns selectSExtBits(MachineOperand &Root, unsigned Bits) const;
113 template <unsigned Bits>
114 ComplexRendererFns selectSExtBits(MachineOperand &Root) const {
115 return selectSExtBits(Root, Bits);
116 }
117
118 ComplexRendererFns selectZExtBits(MachineOperand &Root, unsigned Bits) const;
119 template <unsigned Bits>
120 ComplexRendererFns selectZExtBits(MachineOperand &Root) const {
121 return selectZExtBits(Root, Bits);
122 }
123
124 ComplexRendererFns selectSHXADDOp(MachineOperand &Root, unsigned ShAmt) const;
125 template <unsigned ShAmt>
126 ComplexRendererFns selectSHXADDOp(MachineOperand &Root) const {
127 return selectSHXADDOp(Root, ShAmt);
128 }
129
130 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root,
131 unsigned ShAmt) const;
132 template <unsigned ShAmt>
133 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root) const {
134 return selectSHXADD_UWOp(Root, ShAmt);
135 }
136
137 ComplexRendererFns renderVLOp(MachineOperand &Root) const;
138
139 // Custom renderers for tablegen
140 void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
141 int OpIdx) const;
142 void renderImmSubFromXLen(MachineInstrBuilder &MIB, const MachineInstr &MI,
143 int OpIdx) const;
144 void renderImmSubFrom32(MachineInstrBuilder &MIB, const MachineInstr &MI,
145 int OpIdx) const;
146 void renderImmPlus1(MachineInstrBuilder &MIB, const MachineInstr &MI,
147 int OpIdx) const;
148 void renderFrameIndex(MachineInstrBuilder &MIB, const MachineInstr &MI,
149 int OpIdx) const;
150
151 void renderTrailingZeros(MachineInstrBuilder &MIB, const MachineInstr &MI,
152 int OpIdx) const;
153 void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
154 const MachineInstr &MI, int OpIdx) const;
155
156 void renderAddiPairImmLarge(MachineInstrBuilder &MIB, const MachineInstr &MI,
157 int OpIdx) const;
158 void renderAddiPairImmSmall(MachineInstrBuilder &MIB, const MachineInstr &MI,
159 int OpIdx) const;
160
161 const RISCVSubtarget &STI;
162 const RISCVInstrInfo &TII;
163 const RISCVRegisterInfo &TRI;
164 const RISCVRegisterBankInfo &RBI;
165 const RISCVTargetMachine &TM;
166
167 MachineRegisterInfo *MRI = nullptr;
168
169 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
170 // uses "STI." in the code generated by TableGen. We need to unify the name of
171 // Subtarget variable.
172 const RISCVSubtarget *Subtarget = &STI;
173
174#define GET_GLOBALISEL_PREDICATES_DECL
175#include "RISCVGenGlobalISel.inc"
176#undef GET_GLOBALISEL_PREDICATES_DECL
177
178#define GET_GLOBALISEL_TEMPORARIES_DECL
179#include "RISCVGenGlobalISel.inc"
180#undef GET_GLOBALISEL_TEMPORARIES_DECL
181};
182
183} // end anonymous namespace
184
185#define GET_GLOBALISEL_IMPL
186#include "RISCVGenGlobalISel.inc"
187#undef GET_GLOBALISEL_IMPL
188
189RISCVInstructionSelector::RISCVInstructionSelector(
190 const RISCVTargetMachine &TM, const RISCVSubtarget &STI,
191 const RISCVRegisterBankInfo &RBI)
192 : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
193 TM(TM),
194
196#include "RISCVGenGlobalISel.inc"
199#include "RISCVGenGlobalISel.inc"
201{
202}
203
204// Mimics optimizations in ISel and RISCVOptWInst Pass
205bool RISCVInstructionSelector::hasAllNBitUsers(const MachineInstr &MI,
206 unsigned Bits,
207 const unsigned Depth) const {
208
209 assert((MI.getOpcode() == TargetOpcode::G_ADD ||
210 MI.getOpcode() == TargetOpcode::G_SUB ||
211 MI.getOpcode() == TargetOpcode::G_MUL ||
212 MI.getOpcode() == TargetOpcode::G_SHL ||
213 MI.getOpcode() == TargetOpcode::G_LSHR ||
214 MI.getOpcode() == TargetOpcode::G_AND ||
215 MI.getOpcode() == TargetOpcode::G_OR ||
216 MI.getOpcode() == TargetOpcode::G_XOR ||
217 MI.getOpcode() == TargetOpcode::G_SEXT_INREG || Depth != 0) &&
218 "Unexpected opcode");
219
220 if (Depth >= RISCVInstructionSelector::MaxRecursionDepth)
221 return false;
222
223 auto DestReg = MI.getOperand(0).getReg();
224 for (auto &UserOp : MRI->use_nodbg_operands(DestReg)) {
225 assert(UserOp.getParent() && "UserOp must have a parent");
226 const MachineInstr &UserMI = *UserOp.getParent();
227 unsigned OpIdx = UserOp.getOperandNo();
228
229 switch (UserMI.getOpcode()) {
230 default:
231 return false;
232 case RISCV::ADDW:
233 case RISCV::ADDIW:
234 case RISCV::SUBW:
235 case RISCV::FCVT_D_W:
236 case RISCV::FCVT_S_W:
237 if (Bits >= 32)
238 break;
239 return false;
240 case RISCV::SLL:
241 case RISCV::SRA:
242 case RISCV::SRL:
243 // Shift amount operands only use log2(Xlen) bits.
244 if (OpIdx == 2 && Bits >= Log2_32(Subtarget->getXLen()))
245 break;
246 return false;
247 case RISCV::SLLI:
248 // SLLI only uses the lower (XLen - ShAmt) bits.
249 if (Bits >= Subtarget->getXLen() - UserMI.getOperand(2).getImm())
250 break;
251 return false;
252 case RISCV::ANDI:
253 if (Bits >= (unsigned)llvm::bit_width<uint64_t>(
254 (uint64_t)UserMI.getOperand(2).getImm()))
255 break;
256 goto RecCheck;
257 case RISCV::AND:
258 case RISCV::OR:
259 case RISCV::XOR:
260 RecCheck:
261 if (hasAllNBitUsers(UserMI, Bits, Depth + 1))
262 break;
263 return false;
264 case RISCV::SRLI: {
265 unsigned ShAmt = UserMI.getOperand(2).getImm();
266 // If we are shifting right by less than Bits, and users don't demand any
267 // bits that were shifted into [Bits-1:0], then we can consider this as an
268 // N-Bit user.
269 if (Bits > ShAmt && hasAllNBitUsers(UserMI, Bits - ShAmt, Depth + 1))
270 break;
271 return false;
272 }
273 }
274 }
275
276 return true;
277}
278
279InstructionSelector::ComplexRendererFns
280RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
281 unsigned ShiftWidth) const {
282 if (!Root.isReg())
283 return std::nullopt;
284
285 using namespace llvm::MIPatternMatch;
286
287 Register ShAmtReg = Root.getReg();
288 // Peek through zext.
289 Register ZExtSrcReg;
290 if (mi_match(ShAmtReg, *MRI, m_GZExt(m_Reg(ZExtSrcReg))))
291 ShAmtReg = ZExtSrcReg;
292
293 APInt AndMask;
294 Register AndSrcReg;
295 // Try to combine the following pattern (applicable to other shift
296 // instructions as well as 32-bit ones):
297 //
298 // %4:gprb(s64) = G_AND %3, %2
299 // %5:gprb(s64) = G_LSHR %1, %4(s64)
300 //
301 // According to RISC-V's ISA manual, SLL, SRL, and SRA ignore other bits than
302 // the lowest log2(XLEN) bits of register rs2. As for the above pattern, if
303 // the lowest log2(XLEN) bits of register rd and rs2 of G_AND are the same,
304 // then it can be eliminated. Given register rs1 or rs2 holding a constant
305 // (the and mask), there are two cases G_AND can be erased:
306 //
307 // 1. the lowest log2(XLEN) bits of the and mask are all set
308 // 2. the bits of the register being masked are already unset (zero set)
309 if (mi_match(ShAmtReg, *MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
310 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
311 if (ShMask.isSubsetOf(AndMask)) {
312 ShAmtReg = AndSrcReg;
313 } else {
314 // SimplifyDemandedBits may have optimized the mask so try restoring any
315 // bits that are known zero.
316 KnownBits Known = VT->getKnownBits(AndSrcReg);
317 if (ShMask.isSubsetOf(AndMask | Known.Zero))
318 ShAmtReg = AndSrcReg;
319 }
320 }
321
322 APInt Imm;
324 if (mi_match(ShAmtReg, *MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
325 if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
326 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
327 // to avoid the ADD.
328 ShAmtReg = Reg;
329 } else if (mi_match(ShAmtReg, *MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
330 if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
331 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
332 // to generate a NEG instead of a SUB of a constant.
333 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
334 unsigned NegOpc = Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
335 return {{[=](MachineInstrBuilder &MIB) {
336 MachineIRBuilder(*MIB.getInstr())
337 .buildInstr(NegOpc, {ShAmtReg}, {Register(RISCV::X0), Reg});
338 MIB.addReg(ShAmtReg);
339 }}};
340 }
341 if (Imm.urem(ShiftWidth) == ShiftWidth - 1) {
342 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
343 // to generate a NOT instead of a SUB of a constant.
344 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
345 return {{[=](MachineInstrBuilder &MIB) {
346 MachineIRBuilder(*MIB.getInstr())
347 .buildInstr(RISCV::XORI, {ShAmtReg}, {Reg})
348 .addImm(-1);
349 MIB.addReg(ShAmtReg);
350 }}};
351 }
352 }
353
354 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
355}
356
357InstructionSelector::ComplexRendererFns
358RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
359 unsigned Bits) const {
360 if (!Root.isReg())
361 return std::nullopt;
362 Register RootReg = Root.getReg();
363 MachineInstr *RootDef = MRI->getVRegDef(RootReg);
364
365 if (RootDef->getOpcode() == TargetOpcode::G_SEXT_INREG &&
366 RootDef->getOperand(2).getImm() == Bits) {
367 return {
368 {[=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); }}};
369 }
370
371 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
372 if ((Size - VT->computeNumSignBits(RootReg)) < Bits)
373 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
374
375 return std::nullopt;
376}
377
378InstructionSelector::ComplexRendererFns
379RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
380 unsigned Bits) const {
381 if (!Root.isReg())
382 return std::nullopt;
383 Register RootReg = Root.getReg();
384
385 Register RegX;
386 uint64_t Mask = maskTrailingOnes<uint64_t>(Bits);
387 if (mi_match(RootReg, *MRI, m_GAnd(m_Reg(RegX), m_SpecificICst(Mask)))) {
388 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
389 }
390
391 if (mi_match(RootReg, *MRI, m_GZExt(m_Reg(RegX))) &&
392 MRI->getType(RegX).getScalarSizeInBits() == Bits)
393 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
394
395 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
396 if (VT->maskedValueIsZero(RootReg, APInt::getBitsSetFrom(Size, Bits)))
397 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
398
399 return std::nullopt;
400}
401
402InstructionSelector::ComplexRendererFns
403RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
404 unsigned ShAmt) const {
405 using namespace llvm::MIPatternMatch;
406
407 if (!Root.isReg())
408 return std::nullopt;
409 Register RootReg = Root.getReg();
410
411 const unsigned XLen = STI.getXLen();
412 APInt Mask, C2;
413 Register RegY;
414 std::optional<bool> LeftShift;
415 // (and (shl y, c2), mask)
416 if (mi_match(RootReg, *MRI,
417 m_GAnd(m_GShl(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
418 LeftShift = true;
419 // (and (lshr y, c2), mask)
420 else if (mi_match(RootReg, *MRI,
421 m_GAnd(m_GLShr(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
422 LeftShift = false;
423
424 if (LeftShift.has_value()) {
425 if (*LeftShift)
427 else
429
430 if (Mask.isShiftedMask()) {
431 unsigned Leading = XLen - Mask.getActiveBits();
432 unsigned Trailing = Mask.countr_zero();
433 // Given (and (shl y, c2), mask) in which mask has no leading zeros and
434 // c3 trailing zeros. We can use an SRLI by c3 - c2 followed by a SHXADD.
435 if (*LeftShift && Leading == 0 && C2.ult(Trailing) && Trailing == ShAmt) {
436 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
437 return {{[=](MachineInstrBuilder &MIB) {
438 MachineIRBuilder(*MIB.getInstr())
439 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
440 .addImm(Trailing - C2.getLimitedValue());
441 MIB.addReg(DstReg);
442 }}};
443 }
444
445 // Given (and (lshr y, c2), mask) in which mask has c2 leading zeros and
446 // c3 trailing zeros. We can use an SRLI by c2 + c3 followed by a SHXADD.
447 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
448 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
449 return {{[=](MachineInstrBuilder &MIB) {
450 MachineIRBuilder(*MIB.getInstr())
451 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
452 .addImm(Leading + Trailing);
453 MIB.addReg(DstReg);
454 }}};
455 }
456 }
457 }
458
459 LeftShift.reset();
460
461 // (shl (and y, mask), c2)
462 if (mi_match(RootReg, *MRI,
463 m_GShl(m_OneNonDBGUse(m_GAnd(m_Reg(RegY), m_ICst(Mask))),
464 m_ICst(C2))))
465 LeftShift = true;
466 // (lshr (and y, mask), c2)
467 else if (mi_match(RootReg, *MRI,
469 m_ICst(C2))))
470 LeftShift = false;
471
472 if (LeftShift.has_value() && Mask.isShiftedMask()) {
473 unsigned Leading = XLen - Mask.getActiveBits();
474 unsigned Trailing = Mask.countr_zero();
475
476 // Given (shl (and y, mask), c2) in which mask has 32 leading zeros and
477 // c3 trailing zeros. If c1 + c3 == ShAmt, we can emit SRLIW + SHXADD.
478 bool Cond = *LeftShift && Leading == 32 && Trailing > 0 &&
479 (Trailing + C2.getLimitedValue()) == ShAmt;
480 if (!Cond)
481 // Given (lshr (and y, mask), c2) in which mask has 32 leading zeros and
482 // c3 trailing zeros. If c3 - c1 == ShAmt, we can emit SRLIW + SHXADD.
483 Cond = !*LeftShift && Leading == 32 && C2.ult(Trailing) &&
484 (Trailing - C2.getLimitedValue()) == ShAmt;
485
486 if (Cond) {
487 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
488 return {{[=](MachineInstrBuilder &MIB) {
489 MachineIRBuilder(*MIB.getInstr())
490 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
491 .addImm(Trailing);
492 MIB.addReg(DstReg);
493 }}};
494 }
495 }
496
497 return std::nullopt;
498}
499
500InstructionSelector::ComplexRendererFns
501RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
502 unsigned ShAmt) const {
503 using namespace llvm::MIPatternMatch;
504
505 if (!Root.isReg())
506 return std::nullopt;
507 Register RootReg = Root.getReg();
508
509 // Given (and (shl x, c2), mask) in which mask is a shifted mask with
510 // 32 - ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
511 // c2 - ShAmt followed by SHXADD_UW with ShAmt for x amount.
512 APInt Mask, C2;
513 Register RegX;
514 if (mi_match(
515 RootReg, *MRI,
517 m_ICst(Mask))))) {
519
520 if (Mask.isShiftedMask()) {
521 unsigned Leading = Mask.countl_zero();
522 unsigned Trailing = Mask.countr_zero();
523 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
524 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
525 return {{[=](MachineInstrBuilder &MIB) {
526 MachineIRBuilder(*MIB.getInstr())
527 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
528 .addImm(C2.getLimitedValue() - ShAmt);
529 MIB.addReg(DstReg);
530 }}};
531 }
532 }
533 }
534
535 return std::nullopt;
536}
537
538InstructionSelector::ComplexRendererFns
539RISCVInstructionSelector::renderVLOp(MachineOperand &Root) const {
540 assert(Root.isReg() && "Expected operand to be a Register");
541 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
542
543 if (RootDef->getOpcode() == TargetOpcode::G_CONSTANT) {
544 auto C = RootDef->getOperand(1).getCImm();
545 if (C->getValue().isAllOnes())
546 // If the operand is a G_CONSTANT with value of all ones it is larger than
547 // VLMAX. We convert it to an immediate with value VLMaxSentinel. This is
548 // recognized specially by the vsetvli insertion pass.
549 return {{[=](MachineInstrBuilder &MIB) {
550 MIB.addImm(RISCV::VLMaxSentinel);
551 }}};
552
553 if (isUInt<5>(C->getZExtValue())) {
554 uint64_t ZExtC = C->getZExtValue();
555 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
556 }
557 }
558 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); }}};
559}
560
561InstructionSelector::ComplexRendererFns
562RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
563 if (!Root.isReg())
564 return std::nullopt;
565
566 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
567 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
568 return {{
569 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
570 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
571 }};
572 }
573
574 if (isBaseWithConstantOffset(Root, *MRI)) {
575 MachineOperand &LHS = RootDef->getOperand(1);
576 MachineOperand &RHS = RootDef->getOperand(2);
577 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
578 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
579
580 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
581 if (isInt<12>(RHSC)) {
582 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
583 return {{
584 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
585 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
586 }};
587
588 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
589 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
590 }
591 }
592
593 // TODO: Need to get the immediate from a G_PTR_ADD. Should this be done in
594 // the combiner?
595 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
596 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
597}
598
599/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
600/// CC Must be an ICMP Predicate.
601static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
602 switch (CC) {
603 default:
604 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
605 case CmpInst::Predicate::ICMP_EQ:
606 return RISCVCC::COND_EQ;
607 case CmpInst::Predicate::ICMP_NE:
608 return RISCVCC::COND_NE;
609 case CmpInst::Predicate::ICMP_ULT:
610 return RISCVCC::COND_LTU;
611 case CmpInst::Predicate::ICMP_SLT:
612 return RISCVCC::COND_LT;
613 case CmpInst::Predicate::ICMP_UGE:
614 return RISCVCC::COND_GEU;
615 case CmpInst::Predicate::ICMP_SGE:
616 return RISCVCC::COND_GE;
617 }
618}
619
623 // Try to fold an ICmp. If that fails, use a NE compare with X0.
625 if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
626 LHS = CondReg;
627 RHS = RISCV::X0;
628 CC = RISCVCC::COND_NE;
629 return;
630 }
631
632 // We found an ICmp, do some canonicalization.
633
634 // Adjust comparisons to use comparison with 0 if possible.
636 switch (Pred) {
638 // Convert X > -1 to X >= 0
639 if (*Constant == -1) {
640 CC = RISCVCC::COND_GE;
641 RHS = RISCV::X0;
642 return;
643 }
644 break;
646 // Convert X < 1 to 0 >= X
647 if (*Constant == 1) {
648 CC = RISCVCC::COND_GE;
649 RHS = LHS;
650 LHS = RISCV::X0;
651 return;
652 }
653 break;
654 default:
655 break;
656 }
657 }
658
659 switch (Pred) {
660 default:
661 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
668 // These CCs are supported directly by RISC-V branches.
669 break;
674 // These CCs are not supported directly by RISC-V branches, but changing the
675 // direction of the CC and swapping LHS and RHS are.
676 Pred = CmpInst::getSwappedPredicate(Pred);
677 std::swap(LHS, RHS);
678 break;
679 }
680
681 CC = getRISCVCCFromICmp(Pred);
682}
683
684/// Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation
685/// \p GenericOpc, appropriate for the GPR register bank and of memory access
686/// size \p OpSize.
687static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
688 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
689 switch (OpSize) {
690 default:
691 llvm_unreachable("Unexpected memory size");
692 case 8:
693 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
694 case 16:
695 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
696 case 32:
697 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
698 case 64:
699 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
700 }
701}
702
703/// Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation
704/// \p GenericOpc, appropriate for the GPR register bank and of memory access
705/// size \p OpSize. \returns \p GenericOpc if the combination is unsupported.
706static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
707 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
708 switch (OpSize) {
709 case 8:
710 // Prefer unsigned due to no c.lb in Zcb.
711 return IsStore ? RISCV::SB : RISCV::LBU;
712 case 16:
713 return IsStore ? RISCV::SH : RISCV::LH;
714 case 32:
715 return IsStore ? RISCV::SW : RISCV::LW;
716 case 64:
717 return IsStore ? RISCV::SD : RISCV::LD;
718 }
719
720 return GenericOpc;
721}
722
723void RISCVInstructionSelector::addVectorLoadStoreOperands(
724 MachineInstr &I, SmallVectorImpl<SrcOp> &SrcOps, unsigned &CurOp,
725 bool IsMasked, bool IsStrided) const {
726 // Base Pointer
727 auto PtrReg = I.getOperand(CurOp++).getReg();
728 SrcOps.push_back(PtrReg);
729
730 // Stride
731 if (IsStrided) {
732 auto StrideReg = I.getOperand(CurOp++).getReg();
733 SrcOps.push_back(StrideReg);
734 }
735
736 // Mask
737 if (IsMasked) {
738 auto MaskReg = I.getOperand(CurOp++).getReg();
739 SrcOps.push_back(MaskReg);
740 }
741}
742
743bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
744 MachineInstr &I, MachineIRBuilder &MIB) const {
745 // Find the intrinsic ID.
746 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
747 // Select the instruction.
748 switch (IntrinID) {
749 default:
750 return false;
751 case Intrinsic::riscv_vlm:
752 case Intrinsic::riscv_vle:
753 case Intrinsic::riscv_vle_mask:
754 case Intrinsic::riscv_vlse:
755 case Intrinsic::riscv_vlse_mask: {
756 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
757 IntrinID == Intrinsic::riscv_vlse_mask;
758 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
759 IntrinID == Intrinsic::riscv_vlse_mask;
760 LLT VT = MRI->getType(I.getOperand(0).getReg());
761 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
762
763 // Result vector
764 const Register DstReg = I.getOperand(0).getReg();
765
766 // Sources
767 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
768 unsigned CurOp = 2;
769 SmallVector<SrcOp, 4> SrcOps; // Source registers.
770
771 // Passthru
772 if (HasPassthruOperand) {
773 auto PassthruReg = I.getOperand(CurOp++).getReg();
774 SrcOps.push_back(PassthruReg);
775 } else {
776 SrcOps.push_back(Register(RISCV::NoRegister));
777 }
778
779 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
780
782 const RISCV::VLEPseudo *P =
783 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
784 static_cast<unsigned>(LMUL));
785
786 auto PseudoMI = MIB.buildInstr(P->Pseudo, {DstReg}, SrcOps);
787
788 // Select VL
789 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
790 for (auto &RenderFn : *VLOpFn)
791 RenderFn(PseudoMI);
792
793 // SEW
794 PseudoMI.addImm(Log2SEW);
795
796 // Policy
797 uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
798 if (IsMasked)
799 Policy = I.getOperand(CurOp++).getImm();
800 PseudoMI.addImm(Policy);
801
802 // Memref
803 PseudoMI.cloneMemRefs(I);
804
805 I.eraseFromParent();
806 return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
807 }
808 case Intrinsic::riscv_vsm:
809 case Intrinsic::riscv_vse:
810 case Intrinsic::riscv_vse_mask:
811 case Intrinsic::riscv_vsse:
812 case Intrinsic::riscv_vsse_mask: {
813 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
814 IntrinID == Intrinsic::riscv_vsse_mask;
815 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
816 IntrinID == Intrinsic::riscv_vsse_mask;
817 LLT VT = MRI->getType(I.getOperand(1).getReg());
818 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
819
820 // Sources
821 unsigned CurOp = 1;
822 SmallVector<SrcOp, 4> SrcOps; // Source registers.
823
824 // Store value
825 auto PassthruReg = I.getOperand(CurOp++).getReg();
826 SrcOps.push_back(PassthruReg);
827
828 addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, IsStrided);
829
831 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
832 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
833
834 auto PseudoMI = MIB.buildInstr(P->Pseudo, {}, SrcOps);
835
836 // Select VL
837 auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
838 for (auto &RenderFn : *VLOpFn)
839 RenderFn(PseudoMI);
840
841 // SEW
842 PseudoMI.addImm(Log2SEW);
843
844 // Memref
845 PseudoMI.cloneMemRefs(I);
846
847 I.eraseFromParent();
848 return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
849 }
850 }
851}
852
853bool RISCVInstructionSelector::select(MachineInstr &MI) {
854 MachineIRBuilder MIB(MI);
855
856 preISelLower(MI, MIB);
857 const unsigned Opc = MI.getOpcode();
858
859 if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
860 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
861 const Register DefReg = MI.getOperand(0).getReg();
862 const LLT DefTy = MRI->getType(DefReg);
863
864 const RegClassOrRegBank &RegClassOrBank =
865 MRI->getRegClassOrRegBank(DefReg);
866
867 const TargetRegisterClass *DefRC =
869 if (!DefRC) {
870 if (!DefTy.isValid()) {
871 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
872 return false;
873 }
874
875 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
876 DefRC = getRegClassForTypeOnBank(DefTy, RB);
877 if (!DefRC) {
878 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
879 return false;
880 }
881 }
882
883 MI.setDesc(TII.get(TargetOpcode::PHI));
884 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
885 }
886
887 // Certain non-generic instructions also need some special handling.
888 if (MI.isCopy())
889 return selectCopy(MI);
890
891 return true;
892 }
893
894 if (selectImpl(MI, *CoverageInfo))
895 return true;
896
897 switch (Opc) {
898 case TargetOpcode::G_ANYEXT:
899 case TargetOpcode::G_PTRTOINT:
900 case TargetOpcode::G_INTTOPTR:
901 case TargetOpcode::G_TRUNC:
902 case TargetOpcode::G_FREEZE:
903 return selectCopy(MI);
904 case TargetOpcode::G_CONSTANT: {
905 Register DstReg = MI.getOperand(0).getReg();
906 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
907
908 if (!materializeImm(DstReg, Imm, MIB))
909 return false;
910
911 MI.eraseFromParent();
912 return true;
913 }
914 case TargetOpcode::G_ZEXT:
915 case TargetOpcode::G_SEXT: {
916 bool IsSigned = Opc != TargetOpcode::G_ZEXT;
917 Register DstReg = MI.getOperand(0).getReg();
918 Register SrcReg = MI.getOperand(1).getReg();
919 LLT SrcTy = MRI->getType(SrcReg);
920 unsigned SrcSize = SrcTy.getSizeInBits();
921
922 if (SrcTy.isVector())
923 return false; // Should be handled by imported patterns.
924
925 assert((*RBI.getRegBank(DstReg, *MRI, TRI)).getID() ==
926 RISCV::GPRBRegBankID &&
927 "Unexpected ext regbank");
928
929 // Use addiw SrcReg, 0 (sext.w) for i32.
930 if (IsSigned && SrcSize == 32) {
931 MI.setDesc(TII.get(RISCV::ADDIW));
932 MI.addOperand(MachineOperand::CreateImm(0));
934 }
935
936 // Use add.uw SrcReg, X0 (zext.w) for i32 with Zba.
937 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
938 MI.setDesc(TII.get(RISCV::ADD_UW));
939 MI.addOperand(MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false));
941 }
942
943 // Use sext.h/zext.h for i16 with Zbb.
944 if (SrcSize == 16 && STI.hasStdExtZbb()) {
945 MI.setDesc(TII.get(IsSigned ? RISCV::SEXT_H
946 : STI.isRV64() ? RISCV::ZEXT_H_RV64
947 : RISCV::ZEXT_H_RV32));
949 }
950
951 // Use pack(w) SrcReg, X0 for i16 zext with Zbkb.
952 if (!IsSigned && SrcSize == 16 && STI.hasStdExtZbkb()) {
953 MI.setDesc(TII.get(STI.is64Bit() ? RISCV::PACKW : RISCV::PACK));
954 MI.addOperand(MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false));
956 }
957
958 // Fall back to shift pair.
959 auto ShiftLeft =
960 MIB.buildInstr(RISCV::SLLI, {&RISCV::GPRRegClass}, {SrcReg})
961 .addImm(STI.getXLen() - SrcSize);
962 constrainSelectedInstRegOperands(*ShiftLeft, TII, TRI, RBI);
963 auto ShiftRight = MIB.buildInstr(IsSigned ? RISCV::SRAI : RISCV::SRLI,
964 {DstReg}, {ShiftLeft})
965 .addImm(STI.getXLen() - SrcSize);
966 constrainSelectedInstRegOperands(*ShiftRight, TII, TRI, RBI);
967 MI.eraseFromParent();
968 return true;
969 }
970 case TargetOpcode::G_FCONSTANT: {
971 // TODO: Use constant pool for complex constants.
972 Register DstReg = MI.getOperand(0).getReg();
973 const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
974 unsigned Size = MRI->getType(DstReg).getSizeInBits();
975 if (Size == 16 || Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
976 Register GPRReg;
977 if (FPimm.isPosZero()) {
978 GPRReg = RISCV::X0;
979 } else {
980 GPRReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
981 APInt Imm = FPimm.bitcastToAPInt();
982 if (!materializeImm(GPRReg, Imm.getSExtValue(), MIB))
983 return false;
984 }
985
986 unsigned Opcode = Size == 64 ? RISCV::FMV_D_X
987 : Size == 32 ? RISCV::FMV_W_X
988 : RISCV::FMV_H_X;
989 auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
990 if (!FMV.constrainAllUses(TII, TRI, RBI))
991 return false;
992 } else {
993 // s64 on rv32
994 assert(Size == 64 && !Subtarget->is64Bit() &&
995 "Unexpected size or subtarget");
996
997 if (FPimm.isPosZero()) {
998 // Optimize +0.0 to use fcvt.d.w
999 MachineInstrBuilder FCVT =
1000 MIB.buildInstr(RISCV::FCVT_D_W, {DstReg}, {Register(RISCV::X0)})
1001 .addImm(RISCVFPRndMode::RNE);
1002 if (!FCVT.constrainAllUses(TII, TRI, RBI))
1003 return false;
1004
1005 MI.eraseFromParent();
1006 return true;
1007 }
1008
1009 // Split into two pieces and build through the stack.
1010 Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1011 Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1012 APInt Imm = FPimm.bitcastToAPInt();
1013 if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
1014 MIB))
1015 return false;
1016 if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MIB))
1017 return false;
1018 MachineInstrBuilder PairF64 = MIB.buildInstr(
1019 RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
1020 if (!PairF64.constrainAllUses(TII, TRI, RBI))
1021 return false;
1022 }
1023
1024 MI.eraseFromParent();
1025 return true;
1026 }
1027 case TargetOpcode::G_GLOBAL_VALUE: {
1028 auto *GV = MI.getOperand(1).getGlobal();
1029 if (GV->isThreadLocal()) {
1030 // TODO: implement this case.
1031 return false;
1032 }
1033
1034 return selectAddr(MI, MIB, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1035 }
1036 case TargetOpcode::G_JUMP_TABLE:
1037 case TargetOpcode::G_CONSTANT_POOL:
1038 return selectAddr(MI, MIB, MRI);
1039 case TargetOpcode::G_BRCOND: {
1040 Register LHS, RHS;
1042 getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
1043
1044 auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(CC), {}, {LHS, RHS})
1045 .addMBB(MI.getOperand(1).getMBB());
1046 MI.eraseFromParent();
1047 return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
1048 }
1049 case TargetOpcode::G_BRINDIRECT:
1050 MI.setDesc(TII.get(RISCV::PseudoBRIND));
1051 MI.addOperand(MachineOperand::CreateImm(0));
1053 case TargetOpcode::G_SELECT:
1054 return selectSelect(MI, MIB);
1055 case TargetOpcode::G_FCMP:
1056 return selectFPCompare(MI, MIB);
1057 case TargetOpcode::G_FENCE: {
1058 AtomicOrdering FenceOrdering =
1059 static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
1060 SyncScope::ID FenceSSID =
1061 static_cast<SyncScope::ID>(MI.getOperand(1).getImm());
1062 emitFence(FenceOrdering, FenceSSID, MIB);
1063 MI.eraseFromParent();
1064 return true;
1065 }
1066 case TargetOpcode::G_IMPLICIT_DEF:
1067 return selectImplicitDef(MI, MIB);
1068 case TargetOpcode::G_UNMERGE_VALUES:
1069 return selectUnmergeValues(MI, MIB);
1070 case TargetOpcode::G_LOAD:
1071 case TargetOpcode::G_STORE: {
1072 GLoadStore &LdSt = cast<GLoadStore>(MI);
1073 const Register ValReg = LdSt.getReg(0);
1074 const Register PtrReg = LdSt.getPointerReg();
1075 LLT PtrTy = MRI->getType(PtrReg);
1076
1077 const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
1078 if (RB.getID() != RISCV::GPRBRegBankID)
1079 return false;
1080
1081#ifndef NDEBUG
1082 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, *MRI, TRI);
1083 // Check that the pointer register is valid.
1084 assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
1085 "Load/Store pointer operand isn't a GPR");
1086 assert(PtrTy.isPointer() && "Load/Store pointer operand isn't a pointer");
1087#endif
1088
1089 // Can only handle AddressSpace 0.
1090 if (PtrTy.getAddressSpace() != 0)
1091 return false;
1092
1093 unsigned MemSize = LdSt.getMemSizeInBits().getValue();
1094 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
1095
1096 if (isStrongerThanMonotonic(Order)) {
1097 MI.setDesc(TII.get(selectZalasrLoadStoreOp(Opc, MemSize)));
1099 }
1100
1101 const unsigned NewOpc = selectRegImmLoadStoreOp(MI.getOpcode(), MemSize);
1102 if (NewOpc == MI.getOpcode())
1103 return false;
1104
1105 // Check if we can fold anything into the addressing mode.
1106 auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
1107 if (!AddrModeFns)
1108 return false;
1109
1110 // Folded something. Create a new instruction and return it.
1111 auto NewInst = MIB.buildInstr(NewOpc, {}, {}, MI.getFlags());
1112 if (isa<GStore>(MI))
1113 NewInst.addUse(ValReg);
1114 else
1115 NewInst.addDef(ValReg);
1116 NewInst.cloneMemRefs(MI);
1117 for (auto &Fn : *AddrModeFns)
1118 Fn(NewInst);
1119 MI.eraseFromParent();
1120
1121 return constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
1122 }
1123 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1124 return selectIntrinsicWithSideEffects(MI, MIB);
1125 default:
1126 return false;
1127 }
1128}
1129
1130bool RISCVInstructionSelector::selectUnmergeValues(
1131 MachineInstr &MI, MachineIRBuilder &MIB) const {
1132 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1133
1134 if (!Subtarget->hasStdExtZfa())
1135 return false;
1136
1137 // Split F64 Src into two s32 parts
1138 if (MI.getNumOperands() != 3)
1139 return false;
1140 Register Src = MI.getOperand(2).getReg();
1141 Register Lo = MI.getOperand(0).getReg();
1142 Register Hi = MI.getOperand(1).getReg();
1143 if (!isRegInFprb(Src) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
1144 return false;
1145
1146 MachineInstr *ExtractLo = MIB.buildInstr(RISCV::FMV_X_W_FPR64, {Lo}, {Src});
1147 if (!constrainSelectedInstRegOperands(*ExtractLo, TII, TRI, RBI))
1148 return false;
1149
1150 MachineInstr *ExtractHi = MIB.buildInstr(RISCV::FMVH_X_D, {Hi}, {Src});
1151 if (!constrainSelectedInstRegOperands(*ExtractHi, TII, TRI, RBI))
1152 return false;
1153
1154 MI.eraseFromParent();
1155 return true;
1156}
1157
1158bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &Op,
1159 MachineIRBuilder &MIB) {
1160 Register PtrReg = Op.getReg();
1161 assert(MRI->getType(PtrReg).isPointer() && "Operand is not a pointer!");
1162
1163 const LLT sXLen = LLT::scalar(STI.getXLen());
1164 auto PtrToInt = MIB.buildPtrToInt(sXLen, PtrReg);
1165 MRI->setRegBank(PtrToInt.getReg(0), RBI.getRegBank(RISCV::GPRBRegBankID));
1166 Op.setReg(PtrToInt.getReg(0));
1167 return select(*PtrToInt);
1168}
1169
1170void RISCVInstructionSelector::preISelLower(MachineInstr &MI,
1171 MachineIRBuilder &MIB) {
1172 switch (MI.getOpcode()) {
1173 case TargetOpcode::G_PTR_ADD: {
1174 Register DstReg = MI.getOperand(0).getReg();
1175 const LLT sXLen = LLT::scalar(STI.getXLen());
1176
1177 replacePtrWithInt(MI.getOperand(1), MIB);
1178 MI.setDesc(TII.get(TargetOpcode::G_ADD));
1179 MRI->setType(DstReg, sXLen);
1180 break;
1181 }
1182 case TargetOpcode::G_PTRMASK: {
1183 Register DstReg = MI.getOperand(0).getReg();
1184 const LLT sXLen = LLT::scalar(STI.getXLen());
1185 replacePtrWithInt(MI.getOperand(1), MIB);
1186 MI.setDesc(TII.get(TargetOpcode::G_AND));
1187 MRI->setType(DstReg, sXLen);
1188 break;
1189 }
1190 }
1191}
1192
1193void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1194 const MachineInstr &MI,
1195 int OpIdx) const {
1196 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1197 "Expected G_CONSTANT");
1198 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1199 MIB.addImm(-CstVal);
1200}
1201
1202void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1203 const MachineInstr &MI,
1204 int OpIdx) const {
1205 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1206 "Expected G_CONSTANT");
1207 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1208 MIB.addImm(STI.getXLen() - CstVal);
1209}
1210
1211void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1212 const MachineInstr &MI,
1213 int OpIdx) const {
1214 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1215 "Expected G_CONSTANT");
1216 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
1217 MIB.addImm(32 - CstVal);
1218}
1219
1220void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1221 const MachineInstr &MI,
1222 int OpIdx) const {
1223 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1224 "Expected G_CONSTANT");
1225 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
1226 MIB.addImm(CstVal + 1);
1227}
1228
1229void RISCVInstructionSelector::renderFrameIndex(MachineInstrBuilder &MIB,
1230 const MachineInstr &MI,
1231 int OpIdx) const {
1232 assert(MI.getOpcode() == TargetOpcode::G_FRAME_INDEX && OpIdx == -1 &&
1233 "Expected G_FRAME_INDEX");
1234 MIB.add(MI.getOperand(1));
1235}
1236
1237void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1238 const MachineInstr &MI,
1239 int OpIdx) const {
1240 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1241 "Expected G_CONSTANT");
1242 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1244}
1245
1246void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1247 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
1248 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1249 "Expected G_CONSTANT");
1250 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
1251 MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
1252}
1253
1254void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1255 const MachineInstr &MI,
1256 int OpIdx) const {
1257 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1258 "Expected G_CONSTANT");
1259 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
1260 int64_t Adj = Imm < 0 ? -2048 : 2047;
1261 MIB.addImm(Imm - Adj);
1262}
1263
1264void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1265 const MachineInstr &MI,
1266 int OpIdx) const {
1267 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1268 "Expected G_CONSTANT");
1269 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1270 MIB.addImm(Imm);
1271}
1272
1273const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
1274 LLT Ty, const RegisterBank &RB) const {
1275 if (RB.getID() == RISCV::GPRBRegBankID) {
1276 if (Ty.getSizeInBits() <= 32 || (STI.is64Bit() && Ty.getSizeInBits() == 64))
1277 return &RISCV::GPRRegClass;
1278 }
1279
1280 if (RB.getID() == RISCV::FPRBRegBankID) {
1281 if (Ty.getSizeInBits() == 16)
1282 return &RISCV::FPR16RegClass;
1283 if (Ty.getSizeInBits() == 32)
1284 return &RISCV::FPR32RegClass;
1285 if (Ty.getSizeInBits() == 64)
1286 return &RISCV::FPR64RegClass;
1287 }
1288
1289 if (RB.getID() == RISCV::VRBRegBankID) {
1290 if (Ty.getSizeInBits().getKnownMinValue() <= 64)
1291 return &RISCV::VRRegClass;
1292
1293 if (Ty.getSizeInBits().getKnownMinValue() == 128)
1294 return &RISCV::VRM2RegClass;
1295
1296 if (Ty.getSizeInBits().getKnownMinValue() == 256)
1297 return &RISCV::VRM4RegClass;
1298
1299 if (Ty.getSizeInBits().getKnownMinValue() == 512)
1300 return &RISCV::VRM8RegClass;
1301 }
1302
1303 return nullptr;
1304}
1305
1306bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
1307 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
1308}
1309
1310bool RISCVInstructionSelector::isRegInFprb(Register Reg) const {
1311 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID;
1312}
1313
1314bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
1315 Register DstReg = MI.getOperand(0).getReg();
1316
1317 if (DstReg.isPhysical())
1318 return true;
1319
1320 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1321 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
1322 assert(DstRC &&
1323 "Register class not available for LLT, register bank combination");
1324
1325 // No need to constrain SrcReg. It will get constrained when
1326 // we hit another of its uses or its defs.
1327 // Copies do not have constraints.
1328 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1329 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1330 << " operand\n");
1331 return false;
1332 }
1333
1334 MI.setDesc(TII.get(RISCV::COPY));
1335 return true;
1336}
1337
1338bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI,
1339 MachineIRBuilder &MIB) const {
1340 assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1341
1342 const Register DstReg = MI.getOperand(0).getReg();
1343 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1344 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
1345
1346 assert(DstRC &&
1347 "Register class not available for LLT, register bank combination");
1348
1349 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
1350 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
1351 << " operand\n");
1352 }
1353 MI.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1354 return true;
1355}
1356
1357bool RISCVInstructionSelector::materializeImm(Register DstReg, int64_t Imm,
1358 MachineIRBuilder &MIB) const {
1359 if (Imm == 0) {
1360 MIB.buildCopy(DstReg, Register(RISCV::X0));
1361 RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, *MRI);
1362 return true;
1363 }
1364
1366 unsigned NumInsts = Seq.size();
1367 Register SrcReg = RISCV::X0;
1368
1369 for (unsigned i = 0; i < NumInsts; i++) {
1370 Register TmpReg = i < NumInsts - 1
1371 ? MRI->createVirtualRegister(&RISCV::GPRRegClass)
1372 : DstReg;
1373 const RISCVMatInt::Inst &I = Seq[i];
1374 MachineInstr *Result;
1375
1376 switch (I.getOpndKind()) {
1377 case RISCVMatInt::Imm:
1378 // clang-format off
1379 Result = MIB.buildInstr(I.getOpcode(), {TmpReg}, {})
1380 .addImm(I.getImm());
1381 // clang-format on
1382 break;
1383 case RISCVMatInt::RegX0:
1384 Result = MIB.buildInstr(I.getOpcode(), {TmpReg},
1385 {SrcReg, Register(RISCV::X0)});
1386 break;
1388 Result = MIB.buildInstr(I.getOpcode(), {TmpReg}, {SrcReg, SrcReg});
1389 break;
1391 Result =
1392 MIB.buildInstr(I.getOpcode(), {TmpReg}, {SrcReg}).addImm(I.getImm());
1393 break;
1394 }
1395
1396 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1397 return false;
1398
1399 SrcReg = TmpReg;
1400 }
1401
1402 return true;
1403}
1404
1405bool RISCVInstructionSelector::selectAddr(MachineInstr &MI,
1406 MachineIRBuilder &MIB, bool IsLocal,
1407 bool IsExternWeak) const {
1408 assert((MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1409 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1410 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1411 "Unexpected opcode");
1412
1413 const MachineOperand &DispMO = MI.getOperand(1);
1414
1415 Register DefReg = MI.getOperand(0).getReg();
1416 const LLT DefTy = MRI->getType(DefReg);
1417
1418 // When HWASAN is used and tagging of global variables is enabled
1419 // they should be accessed via the GOT, since the tagged address of a global
1420 // is incompatible with existing code models. This also applies to non-pic
1421 // mode.
1422 if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
1423 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1424 // Use PC-relative addressing to access the symbol. This generates the
1425 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
1426 // %pcrel_lo(auipc)).
1427 MI.setDesc(TII.get(RISCV::PseudoLLA));
1429 }
1430
1431 // Use PC-relative addressing to access the GOT for this symbol, then
1432 // load the address from the GOT. This generates the pattern (PseudoLGA
1433 // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
1434 // %pcrel_lo(auipc))).
1435 MachineFunction &MF = *MI.getParent()->getParent();
1436 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1440 DefTy, Align(DefTy.getSizeInBits() / 8));
1441
1442 auto Result = MIB.buildInstr(RISCV::PseudoLGA, {DefReg}, {})
1443 .addDisp(DispMO, 0)
1444 .addMemOperand(MemOp);
1445
1446 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1447 return false;
1448
1449 MI.eraseFromParent();
1450 return true;
1451 }
1452
1453 switch (TM.getCodeModel()) {
1454 default: {
1455 reportGISelFailure(*MF, *TPC, *MORE, getName(),
1456 "Unsupported code model for lowering", MI);
1457 return false;
1458 }
1459 case CodeModel::Small: {
1460 // Must lie within a single 2 GiB address range and must lie between
1461 // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
1462 // (lui %hi(sym)) %lo(sym)).
1463 Register AddrHiDest = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1464 MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI, {AddrHiDest}, {})
1465 .addDisp(DispMO, 0, RISCVII::MO_HI);
1466
1467 if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
1468 return false;
1469
1470 auto Result = MIB.buildInstr(RISCV::ADDI, {DefReg}, {AddrHiDest})
1471 .addDisp(DispMO, 0, RISCVII::MO_LO);
1472
1473 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1474 return false;
1475
1476 MI.eraseFromParent();
1477 return true;
1478 }
1479 case CodeModel::Medium:
1480 // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
1481 // relocation needs to reference a label that points to the auipc
1482 // instruction itself, not the global. This cannot be done inside the
1483 // instruction selector.
1484 if (IsExternWeak) {
1485 // An extern weak symbol may be undefined, i.e. have value 0, which may
1486 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
1487 // symbol. This generates the pattern (PseudoLGA sym), which expands to
1488 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
1489 MachineFunction &MF = *MI.getParent()->getParent();
1490 MachineMemOperand *MemOp = MF.getMachineMemOperand(
1494 DefTy, Align(DefTy.getSizeInBits() / 8));
1495
1496 auto Result = MIB.buildInstr(RISCV::PseudoLGA, {DefReg}, {})
1497 .addDisp(DispMO, 0)
1498 .addMemOperand(MemOp);
1499
1500 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1501 return false;
1502
1503 MI.eraseFromParent();
1504 return true;
1505 }
1506
1507 // Generate a sequence for accessing addresses within any 2GiB range
1508 // within the address space. This generates the pattern (PseudoLLA sym),
1509 // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
1510 MI.setDesc(TII.get(RISCV::PseudoLLA));
1512 }
1513
1514 return false;
1515}
1516
1517bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
1518 MachineIRBuilder &MIB) const {
1519 auto &SelectMI = cast<GSelect>(MI);
1520
1521 Register LHS, RHS;
1523 getOperandsForBranch(SelectMI.getCondReg(), CC, LHS, RHS, *MRI);
1524
1525 Register DstReg = SelectMI.getReg(0);
1526
1527 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1528 if (RBI.getRegBank(DstReg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
1529 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1530 Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1531 : RISCV::Select_FPR64_Using_CC_GPR;
1532 }
1533
1534 MachineInstr *Result = MIB.buildInstr(Opc)
1535 .addDef(DstReg)
1536 .addReg(LHS)
1537 .addReg(RHS)
1538 .addImm(CC)
1539 .addReg(SelectMI.getTrueReg())
1540 .addReg(SelectMI.getFalseReg());
1541 MI.eraseFromParent();
1542 return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
1543}
1544
1545// Convert an FCMP predicate to one of the supported F or D instructions.
1546static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
1547 assert((Size == 16 || Size == 32 || Size == 64) && "Unsupported size");
1548 switch (Pred) {
1549 default:
1550 llvm_unreachable("Unsupported predicate");
1551 case CmpInst::FCMP_OLT:
1552 return Size == 16 ? RISCV::FLT_H : Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1553 case CmpInst::FCMP_OLE:
1554 return Size == 16 ? RISCV::FLE_H : Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1555 case CmpInst::FCMP_OEQ:
1556 return Size == 16 ? RISCV::FEQ_H : Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1557 }
1558}
1559
1560// Try legalizing an FCMP by swapping or inverting the predicate to one that
1561// is supported.
1563 CmpInst::Predicate &Pred, bool &NeedInvert) {
1564 auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
1565 return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
1566 Pred == CmpInst::FCMP_OEQ;
1567 };
1568
1569 assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
1570
1572 if (isLegalFCmpPredicate(InvPred)) {
1573 Pred = InvPred;
1574 std::swap(LHS, RHS);
1575 return true;
1576 }
1577
1578 InvPred = CmpInst::getInversePredicate(Pred);
1579 NeedInvert = true;
1580 if (isLegalFCmpPredicate(InvPred)) {
1581 Pred = InvPred;
1582 return true;
1583 }
1584 InvPred = CmpInst::getSwappedPredicate(InvPred);
1585 if (isLegalFCmpPredicate(InvPred)) {
1586 Pred = InvPred;
1587 std::swap(LHS, RHS);
1588 return true;
1589 }
1590
1591 return false;
1592}
1593
1594// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
1595// the result in DstReg.
1596// FIXME: Maybe we should expand this earlier.
1597bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
1598 MachineIRBuilder &MIB) const {
1599 auto &CmpMI = cast<GFCmp>(MI);
1600 CmpInst::Predicate Pred = CmpMI.getCond();
1601
1602 Register DstReg = CmpMI.getReg(0);
1603 Register LHS = CmpMI.getLHSReg();
1604 Register RHS = CmpMI.getRHSReg();
1605
1606 unsigned Size = MRI->getType(LHS).getSizeInBits();
1607 assert((Size == 16 || Size == 32 || Size == 64) && "Unexpected size");
1608
1609 Register TmpReg = DstReg;
1610
1611 bool NeedInvert = false;
1612 // First try swapping operands or inverting.
1613 if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
1614 if (NeedInvert)
1615 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1616 auto Cmp = MIB.buildInstr(getFCmpOpcode(Pred, Size), {TmpReg}, {LHS, RHS});
1617 if (!Cmp.constrainAllUses(TII, TRI, RBI))
1618 return false;
1619 } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
1620 // fcmp one LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
1621 NeedInvert = Pred == CmpInst::FCMP_UEQ;
1623 {&RISCV::GPRRegClass}, {LHS, RHS});
1624 if (!Cmp1.constrainAllUses(TII, TRI, RBI))
1625 return false;
1627 {&RISCV::GPRRegClass}, {RHS, LHS});
1628 if (!Cmp2.constrainAllUses(TII, TRI, RBI))
1629 return false;
1630 if (NeedInvert)
1631 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1632 auto Or =
1633 MIB.buildInstr(RISCV::OR, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1634 if (!Or.constrainAllUses(TII, TRI, RBI))
1635 return false;
1636 } else if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
1637 // fcmp ord LHS, RHS => (AND (FEQ LHS, LHS), (FEQ RHS, RHS))
1638 // FIXME: If LHS and RHS are the same we can use a single FEQ.
1639 NeedInvert = Pred == CmpInst::FCMP_UNO;
1641 {&RISCV::GPRRegClass}, {LHS, LHS});
1642 if (!Cmp1.constrainAllUses(TII, TRI, RBI))
1643 return false;
1645 {&RISCV::GPRRegClass}, {RHS, RHS});
1646 if (!Cmp2.constrainAllUses(TII, TRI, RBI))
1647 return false;
1648 if (NeedInvert)
1649 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1650 auto And =
1651 MIB.buildInstr(RISCV::AND, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1652 if (!And.constrainAllUses(TII, TRI, RBI))
1653 return false;
1654 } else
1655 llvm_unreachable("Unhandled predicate");
1656
1657 // Emit an XORI to invert the result if needed.
1658 if (NeedInvert) {
1659 auto Xor = MIB.buildInstr(RISCV::XORI, {DstReg}, {TmpReg}).addImm(1);
1660 if (!Xor.constrainAllUses(TII, TRI, RBI))
1661 return false;
1662 }
1663
1664 MI.eraseFromParent();
1665 return true;
1666}
1667
1668void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
1669 SyncScope::ID FenceSSID,
1670 MachineIRBuilder &MIB) const {
1671 if (STI.hasStdExtZtso()) {
1672 // The only fence that needs an instruction is a sequentially-consistent
1673 // cross-thread fence.
1674 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1675 FenceSSID == SyncScope::System) {
1676 // fence rw, rw
1677 MIB.buildInstr(RISCV::FENCE, {}, {})
1680 return;
1681 }
1682
1683 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
1684 MIB.buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1685 return;
1686 }
1687
1688 // singlethread fences only synchronize with signal handlers on the same
1689 // thread and thus only need to preserve instruction order, not actually
1690 // enforce memory ordering.
1691 if (FenceSSID == SyncScope::SingleThread) {
1692 MIB.buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1693 return;
1694 }
1695
1696 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1697 // Manual: Volume I.
1698 unsigned Pred, Succ;
1699 switch (FenceOrdering) {
1700 default:
1701 llvm_unreachable("Unexpected ordering");
1702 case AtomicOrdering::AcquireRelease:
1703 // fence acq_rel -> fence.tso
1704 MIB.buildInstr(RISCV::FENCE_TSO, {}, {});
1705 return;
1706 case AtomicOrdering::Acquire:
1707 // fence acquire -> fence r, rw
1708 Pred = RISCVFenceField::R;
1710 break;
1711 case AtomicOrdering::Release:
1712 // fence release -> fence rw, w
1714 Succ = RISCVFenceField::W;
1715 break;
1716 case AtomicOrdering::SequentiallyConsistent:
1717 // fence seq_cst -> fence rw, rw
1720 break;
1721 }
1722 MIB.buildInstr(RISCV::FENCE, {}, {}).addImm(Pred).addImm(Succ);
1723}
1724
1725namespace llvm {
1726InstructionSelector *
1728 const RISCVSubtarget &Subtarget,
1729 const RISCVRegisterBankInfo &RBI) {
1730 return new RISCVInstructionSelector(TM, Subtarget, RBI);
1731}
1732} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
#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)
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:58
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:114
Value * RHS
Value * LHS
APInt bitcastToAPInt() const
Definition APFloat.h:1335
bool isPosZero() const
Definition APFloat.h:1442
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1488
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1111
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition APInt.h:475
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
Definition APInt.h:286
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:679
@ ICMP_SLT
signed less than
Definition InstrTypes.h:705
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:706
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:682
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:700
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:699
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:703
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:684
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:687
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:701
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:683
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:685
@ ICMP_NE
not equal
Definition InstrTypes.h:698
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:704
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:702
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:686
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:827
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:789
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:169
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.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_PTRTOINT instruction.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
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,...
Analysis providing profile information.
This class provides the information for the target register banks.
unsigned getXLen() const
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.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:19
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:78
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.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
#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 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.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
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:293
LLVM_ABI bool 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:155
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:303
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:314
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:202
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:331
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
Definition Utils.cpp:259
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
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:94
@ 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
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:77
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
#define MORE()
Definition regcomp.c:246
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.