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