LLVM 20.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
48 CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI,
49 BlockFrequencyInfo *BFI) override {
50 InstructionSelector::setupMF(MF, KB, 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 bool isRegInGprb(Register Reg) const;
61 bool isRegInFprb(Register Reg) const;
62
63 // tblgen-erated 'select' implementation, used as the initial selector for
64 // the patterns that don't require complex C++.
65 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
66
67 // A lowering phase that runs before any selection attempts.
68 // Returns true if the instruction was modified.
69 void preISelLower(MachineInstr &MI, MachineIRBuilder &MIB);
70
71 bool replacePtrWithInt(MachineOperand &Op, MachineIRBuilder &MIB);
72
73 // Custom selection methods
74 bool selectCopy(MachineInstr &MI) const;
75 bool selectImplicitDef(MachineInstr &MI, MachineIRBuilder &MIB) const;
76 bool materializeImm(Register Reg, int64_t Imm, MachineIRBuilder &MIB) const;
77 bool selectAddr(MachineInstr &MI, MachineIRBuilder &MIB, bool IsLocal = true,
78 bool IsExternWeak = false) const;
79 bool selectSelect(MachineInstr &MI, MachineIRBuilder &MIB) const;
80 bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB) const;
81 void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
82 MachineIRBuilder &MIB) const;
85
86 ComplexRendererFns selectShiftMask(MachineOperand &Root,
87 unsigned ShiftWidth) const;
88 ComplexRendererFns selectShiftMaskXLen(MachineOperand &Root) const {
89 return selectShiftMask(Root, STI.getXLen());
90 }
91 ComplexRendererFns selectShiftMask32(MachineOperand &Root) const {
92 return selectShiftMask(Root, 32);
93 }
94 ComplexRendererFns selectAddrRegImm(MachineOperand &Root) const;
95
96 ComplexRendererFns selectSExtBits(MachineOperand &Root, unsigned Bits) const;
97 template <unsigned Bits>
98 ComplexRendererFns selectSExtBits(MachineOperand &Root) const {
99 return selectSExtBits(Root, Bits);
100 }
101
102 ComplexRendererFns selectZExtBits(MachineOperand &Root, unsigned Bits) const;
103 template <unsigned Bits>
104 ComplexRendererFns selectZExtBits(MachineOperand &Root) const {
105 return selectZExtBits(Root, Bits);
106 }
107
108 ComplexRendererFns selectSHXADDOp(MachineOperand &Root, unsigned ShAmt) const;
109 template <unsigned ShAmt>
110 ComplexRendererFns selectSHXADDOp(MachineOperand &Root) const {
111 return selectSHXADDOp(Root, ShAmt);
112 }
113
114 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root,
115 unsigned ShAmt) const;
116 template <unsigned ShAmt>
117 ComplexRendererFns selectSHXADD_UWOp(MachineOperand &Root) const {
118 return selectSHXADD_UWOp(Root, ShAmt);
119 }
120
121 ComplexRendererFns renderVLOp(MachineOperand &Root) const;
122
123 // Custom renderers for tablegen
124 void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
125 int OpIdx) const;
126 void renderImmSubFromXLen(MachineInstrBuilder &MIB, const MachineInstr &MI,
127 int OpIdx) const;
128 void renderImmSubFrom32(MachineInstrBuilder &MIB, const MachineInstr &MI,
129 int OpIdx) const;
130 void renderImmPlus1(MachineInstrBuilder &MIB, const MachineInstr &MI,
131 int OpIdx) const;
132 void renderImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
133 int OpIdx) const;
134
135 void renderTrailingZeros(MachineInstrBuilder &MIB, const MachineInstr &MI,
136 int OpIdx) const;
137 void renderXLenSubTrailingOnes(MachineInstrBuilder &MIB,
138 const MachineInstr &MI, int OpIdx) const;
139
140 const RISCVSubtarget &STI;
141 const RISCVInstrInfo &TII;
142 const RISCVRegisterInfo &TRI;
143 const RISCVRegisterBankInfo &RBI;
144 const RISCVTargetMachine &TM;
145
146 MachineRegisterInfo *MRI = nullptr;
147
148 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
149 // uses "STI." in the code generated by TableGen. We need to unify the name of
150 // Subtarget variable.
151 const RISCVSubtarget *Subtarget = &STI;
152
153#define GET_GLOBALISEL_PREDICATES_DECL
154#include "RISCVGenGlobalISel.inc"
155#undef GET_GLOBALISEL_PREDICATES_DECL
156
157#define GET_GLOBALISEL_TEMPORARIES_DECL
158#include "RISCVGenGlobalISel.inc"
159#undef GET_GLOBALISEL_TEMPORARIES_DECL
160};
161
162} // end anonymous namespace
163
164#define GET_GLOBALISEL_IMPL
165#include "RISCVGenGlobalISel.inc"
166#undef GET_GLOBALISEL_IMPL
167
168RISCVInstructionSelector::RISCVInstructionSelector(
169 const RISCVTargetMachine &TM, const RISCVSubtarget &STI,
170 const RISCVRegisterBankInfo &RBI)
171 : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
172 TM(TM),
173
175#include "RISCVGenGlobalISel.inc"
178#include "RISCVGenGlobalISel.inc"
180{
181}
182
184RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
185 unsigned ShiftWidth) const {
186 if (!Root.isReg())
187 return std::nullopt;
188
189 using namespace llvm::MIPatternMatch;
190
191 Register ShAmtReg = Root.getReg();
192 // Peek through zext.
193 Register ZExtSrcReg;
194 if (mi_match(ShAmtReg, *MRI, m_GZExt(m_Reg(ZExtSrcReg))))
195 ShAmtReg = ZExtSrcReg;
196
197 APInt AndMask;
198 Register AndSrcReg;
199 // Try to combine the following pattern (applicable to other shift
200 // instructions as well as 32-bit ones):
201 //
202 // %4:gprb(s64) = G_AND %3, %2
203 // %5:gprb(s64) = G_LSHR %1, %4(s64)
204 //
205 // According to RISC-V's ISA manual, SLL, SRL, and SRA ignore other bits than
206 // the lowest log2(XLEN) bits of register rs2. As for the above pattern, if
207 // the lowest log2(XLEN) bits of register rd and rs2 of G_AND are the same,
208 // then it can be eliminated. Given register rs1 or rs2 holding a constant
209 // (the and mask), there are two cases G_AND can be erased:
210 //
211 // 1. the lowest log2(XLEN) bits of the and mask are all set
212 // 2. the bits of the register being masked are already unset (zero set)
213 if (mi_match(ShAmtReg, *MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
214 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
215 if (ShMask.isSubsetOf(AndMask)) {
216 ShAmtReg = AndSrcReg;
217 } else {
218 // SimplifyDemandedBits may have optimized the mask so try restoring any
219 // bits that are known zero.
220 KnownBits Known = KB->getKnownBits(AndSrcReg);
221 if (ShMask.isSubsetOf(AndMask | Known.Zero))
222 ShAmtReg = AndSrcReg;
223 }
224 }
225
226 APInt Imm;
228 if (mi_match(ShAmtReg, *MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
229 if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
230 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
231 // to avoid the ADD.
232 ShAmtReg = Reg;
233 } else if (mi_match(ShAmtReg, *MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
234 if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
235 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X
236 // to generate a NEG instead of a SUB of a constant.
237 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
238 unsigned NegOpc = Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
239 return {{[=](MachineInstrBuilder &MIB) {
240 MachineIRBuilder(*MIB.getInstr())
241 .buildInstr(NegOpc, {ShAmtReg}, {Register(RISCV::X0), Reg});
242 MIB.addReg(ShAmtReg);
243 }}};
244 }
245 if (Imm.urem(ShiftWidth) == ShiftWidth - 1) {
246 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
247 // to generate a NOT instead of a SUB of a constant.
248 ShAmtReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
249 return {{[=](MachineInstrBuilder &MIB) {
250 MachineIRBuilder(*MIB.getInstr())
251 .buildInstr(RISCV::XORI, {ShAmtReg}, {Reg})
252 .addImm(-1);
253 MIB.addReg(ShAmtReg);
254 }}};
255 }
256 }
257
258 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
259}
260
262RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
263 unsigned Bits) const {
264 if (!Root.isReg())
265 return std::nullopt;
266 Register RootReg = Root.getReg();
267 MachineInstr *RootDef = MRI->getVRegDef(RootReg);
268
269 if (RootDef->getOpcode() == TargetOpcode::G_SEXT_INREG &&
270 RootDef->getOperand(2).getImm() == Bits) {
271 return {
272 {[=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); }}};
273 }
274
275 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
276 if ((Size - KB->computeNumSignBits(RootReg)) < Bits)
277 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
278
279 return std::nullopt;
280}
281
283RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
284 unsigned Bits) const {
285 if (!Root.isReg())
286 return std::nullopt;
287 Register RootReg = Root.getReg();
288
289 Register RegX;
290 uint64_t Mask = maskTrailingOnes<uint64_t>(Bits);
291 if (mi_match(RootReg, *MRI, m_GAnd(m_Reg(RegX), m_SpecificICst(Mask)))) {
292 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
293 }
294
295 if (mi_match(RootReg, *MRI, m_GZExt(m_Reg(RegX))) &&
296 MRI->getType(RegX).getScalarSizeInBits() == Bits)
297 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
298
299 unsigned Size = MRI->getType(RootReg).getScalarSizeInBits();
300 if (KB->maskedValueIsZero(RootReg, APInt::getBitsSetFrom(Size, Bits)))
301 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
302
303 return std::nullopt;
304}
305
307RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
308 unsigned ShAmt) const {
309 using namespace llvm::MIPatternMatch;
310
311 if (!Root.isReg())
312 return std::nullopt;
313 Register RootReg = Root.getReg();
314
315 const unsigned XLen = STI.getXLen();
316 APInt Mask, C2;
317 Register RegY;
318 std::optional<bool> LeftShift;
319 // (and (shl y, c2), mask)
320 if (mi_match(RootReg, *MRI,
321 m_GAnd(m_GShl(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
322 LeftShift = true;
323 // (and (lshr y, c2), mask)
324 else if (mi_match(RootReg, *MRI,
325 m_GAnd(m_GLShr(m_Reg(RegY), m_ICst(C2)), m_ICst(Mask))))
326 LeftShift = false;
327
328 if (LeftShift.has_value()) {
329 if (*LeftShift)
330 Mask &= maskTrailingZeros<uint64_t>(C2.getLimitedValue());
331 else
332 Mask &= maskTrailingOnes<uint64_t>(XLen - C2.getLimitedValue());
333
334 if (Mask.isShiftedMask()) {
335 unsigned Leading = XLen - Mask.getActiveBits();
336 unsigned Trailing = Mask.countr_zero();
337 // Given (and (shl y, c2), mask) in which mask has no leading zeros and
338 // c3 trailing zeros. We can use an SRLI by c3 - c2 followed by a SHXADD.
339 if (*LeftShift && Leading == 0 && C2.ult(Trailing) && Trailing == ShAmt) {
340 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
341 return {{[=](MachineInstrBuilder &MIB) {
342 MachineIRBuilder(*MIB.getInstr())
343 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
344 .addImm(Trailing - C2.getLimitedValue());
345 MIB.addReg(DstReg);
346 }}};
347 }
348
349 // Given (and (lshr y, c2), mask) in which mask has c2 leading zeros and
350 // c3 trailing zeros. We can use an SRLI by c2 + c3 followed by a SHXADD.
351 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
352 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
353 return {{[=](MachineInstrBuilder &MIB) {
354 MachineIRBuilder(*MIB.getInstr())
355 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
356 .addImm(Leading + Trailing);
357 MIB.addReg(DstReg);
358 }}};
359 }
360 }
361 }
362
363 LeftShift.reset();
364
365 // (shl (and y, mask), c2)
366 if (mi_match(RootReg, *MRI,
367 m_GShl(m_OneNonDBGUse(m_GAnd(m_Reg(RegY), m_ICst(Mask))),
368 m_ICst(C2))))
369 LeftShift = true;
370 // (lshr (and y, mask), c2)
371 else if (mi_match(RootReg, *MRI,
373 m_ICst(C2))))
374 LeftShift = false;
375
376 if (LeftShift.has_value() && Mask.isShiftedMask()) {
377 unsigned Leading = XLen - Mask.getActiveBits();
378 unsigned Trailing = Mask.countr_zero();
379
380 // Given (shl (and y, mask), c2) in which mask has 32 leading zeros and
381 // c3 trailing zeros. If c1 + c3 == ShAmt, we can emit SRLIW + SHXADD.
382 bool Cond = *LeftShift && Leading == 32 && Trailing > 0 &&
383 (Trailing + C2.getLimitedValue()) == ShAmt;
384 if (!Cond)
385 // Given (lshr (and y, mask), c2) in which mask has 32 leading zeros and
386 // c3 trailing zeros. If c3 - c1 == ShAmt, we can emit SRLIW + SHXADD.
387 Cond = !*LeftShift && Leading == 32 && C2.ult(Trailing) &&
388 (Trailing - C2.getLimitedValue()) == ShAmt;
389
390 if (Cond) {
391 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
392 return {{[=](MachineInstrBuilder &MIB) {
393 MachineIRBuilder(*MIB.getInstr())
394 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
395 .addImm(Trailing);
396 MIB.addReg(DstReg);
397 }}};
398 }
399 }
400
401 return std::nullopt;
402}
403
405RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
406 unsigned ShAmt) const {
407 using namespace llvm::MIPatternMatch;
408
409 if (!Root.isReg())
410 return std::nullopt;
411 Register RootReg = Root.getReg();
412
413 // Given (and (shl x, c2), mask) in which mask is a shifted mask with
414 // 32 - ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
415 // c2 - ShAmt followed by SHXADD_UW with ShAmt for x amount.
416 APInt Mask, C2;
417 Register RegX;
418 if (mi_match(
419 RootReg, *MRI,
421 m_ICst(Mask))))) {
422 Mask &= maskTrailingZeros<uint64_t>(C2.getLimitedValue());
423
424 if (Mask.isShiftedMask()) {
425 unsigned Leading = Mask.countl_zero();
426 unsigned Trailing = Mask.countr_zero();
427 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
428 Register DstReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
429 return {{[=](MachineInstrBuilder &MIB) {
430 MachineIRBuilder(*MIB.getInstr())
431 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
432 .addImm(C2.getLimitedValue() - ShAmt);
433 MIB.addReg(DstReg);
434 }}};
435 }
436 }
437 }
438
439 return std::nullopt;
440}
441
443RISCVInstructionSelector::renderVLOp(MachineOperand &Root) const {
444 assert(Root.isReg() && "Expected operand to be a Register");
445 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
446
447 if (RootDef->getOpcode() == TargetOpcode::G_CONSTANT) {
448 auto C = RootDef->getOperand(1).getCImm();
449 if (C->getValue().isAllOnes())
450 // If the operand is a G_CONSTANT with value of all ones it is larger than
451 // VLMAX. We convert it to an immediate with value VLMaxSentinel. This is
452 // recognized specially by the vsetvli insertion pass.
453 return {{[=](MachineInstrBuilder &MIB) {
454 MIB.addImm(RISCV::VLMaxSentinel);
455 }}};
456
457 if (isUInt<5>(C->getZExtValue())) {
458 uint64_t ZExtC = C->getZExtValue();
459 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
460 }
461 }
462 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); }}};
463}
464
466RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
467 if (!Root.isReg())
468 return std::nullopt;
469
470 MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
471 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
472 return {{
473 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
474 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
475 }};
476 }
477
478 if (isBaseWithConstantOffset(Root, *MRI)) {
479 MachineOperand &LHS = RootDef->getOperand(1);
480 MachineOperand &RHS = RootDef->getOperand(2);
481 MachineInstr *LHSDef = MRI->getVRegDef(LHS.getReg());
482 MachineInstr *RHSDef = MRI->getVRegDef(RHS.getReg());
483
484 int64_t RHSC = RHSDef->getOperand(1).getCImm()->getSExtValue();
485 if (isInt<12>(RHSC)) {
486 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
487 return {{
488 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
489 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
490 }};
491
492 return {{[=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
493 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
494 }
495 }
496
497 // TODO: Need to get the immediate from a G_PTR_ADD. Should this be done in
498 // the combiner?
499 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
500 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
501}
502
503/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
504/// CC Must be an ICMP Predicate.
505static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
506 switch (CC) {
507 default:
508 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
509 case CmpInst::Predicate::ICMP_EQ:
510 return RISCVCC::COND_EQ;
511 case CmpInst::Predicate::ICMP_NE:
512 return RISCVCC::COND_NE;
513 case CmpInst::Predicate::ICMP_ULT:
514 return RISCVCC::COND_LTU;
515 case CmpInst::Predicate::ICMP_SLT:
516 return RISCVCC::COND_LT;
517 case CmpInst::Predicate::ICMP_UGE:
518 return RISCVCC::COND_GEU;
519 case CmpInst::Predicate::ICMP_SGE:
520 return RISCVCC::COND_GE;
521 }
522}
523
525 Register &LHS, Register &RHS,
527 // Try to fold an ICmp. If that fails, use a NE compare with X0.
529 if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
530 LHS = CondReg;
531 RHS = RISCV::X0;
533 return;
534 }
535
536 // We found an ICmp, do some canonicalizations.
537
538 // Adjust comparisons to use comparison with 0 if possible.
540 switch (Pred) {
541 case CmpInst::Predicate::ICMP_SGT:
542 // Convert X > -1 to X >= 0
543 if (*Constant == -1) {
545 RHS = RISCV::X0;
546 return;
547 }
548 break;
549 case CmpInst::Predicate::ICMP_SLT:
550 // Convert X < 1 to 0 >= X
551 if (*Constant == 1) {
553 RHS = LHS;
554 LHS = RISCV::X0;
555 return;
556 }
557 break;
558 default:
559 break;
560 }
561 }
562
563 switch (Pred) {
564 default:
565 llvm_unreachable("Expected ICMP CmpInst::Predicate.");
566 case CmpInst::Predicate::ICMP_EQ:
567 case CmpInst::Predicate::ICMP_NE:
568 case CmpInst::Predicate::ICMP_ULT:
569 case CmpInst::Predicate::ICMP_SLT:
570 case CmpInst::Predicate::ICMP_UGE:
571 case CmpInst::Predicate::ICMP_SGE:
572 // These CCs are supported directly by RISC-V branches.
573 break;
574 case CmpInst::Predicate::ICMP_SGT:
575 case CmpInst::Predicate::ICMP_SLE:
576 case CmpInst::Predicate::ICMP_UGT:
577 case CmpInst::Predicate::ICMP_ULE:
578 // These CCs are not supported directly by RISC-V branches, but changing the
579 // direction of the CC and swapping LHS and RHS are.
580 Pred = CmpInst::getSwappedPredicate(Pred);
581 std::swap(LHS, RHS);
582 break;
583 }
584
585 CC = getRISCVCCFromICmp(Pred);
586}
587
588bool RISCVInstructionSelector::select(MachineInstr &MI) {
589 MachineIRBuilder MIB(MI);
590
591 preISelLower(MI, MIB);
592 const unsigned Opc = MI.getOpcode();
593
594 if (!MI.isPreISelOpcode() || Opc == TargetOpcode::G_PHI) {
595 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
596 const Register DefReg = MI.getOperand(0).getReg();
597 const LLT DefTy = MRI->getType(DefReg);
598
599 const RegClassOrRegBank &RegClassOrBank =
600 MRI->getRegClassOrRegBank(DefReg);
601
602 const TargetRegisterClass *DefRC =
603 dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
604 if (!DefRC) {
605 if (!DefTy.isValid()) {
606 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
607 return false;
608 }
609
610 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
611 DefRC = getRegClassForTypeOnBank(DefTy, RB);
612 if (!DefRC) {
613 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
614 return false;
615 }
616 }
617
618 MI.setDesc(TII.get(TargetOpcode::PHI));
619 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
620 }
621
622 // Certain non-generic instructions also need some special handling.
623 if (MI.isCopy())
624 return selectCopy(MI);
625
626 return true;
627 }
628
629 if (selectImpl(MI, *CoverageInfo))
630 return true;
631
632 switch (Opc) {
633 case TargetOpcode::G_ANYEXT:
634 case TargetOpcode::G_PTRTOINT:
635 case TargetOpcode::G_INTTOPTR:
636 case TargetOpcode::G_TRUNC:
637 case TargetOpcode::G_FREEZE:
638 return selectCopy(MI);
639 case TargetOpcode::G_CONSTANT: {
640 Register DstReg = MI.getOperand(0).getReg();
641 int64_t Imm = MI.getOperand(1).getCImm()->getSExtValue();
642
643 if (!materializeImm(DstReg, Imm, MIB))
644 return false;
645
646 MI.eraseFromParent();
647 return true;
648 }
649 case TargetOpcode::G_FCONSTANT: {
650 // TODO: Use constant pool for complext constants.
651 // TODO: Optimize +0.0 to use fcvt.d.w for s64 on rv32.
652 Register DstReg = MI.getOperand(0).getReg();
653 const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
654 APInt Imm = FPimm.bitcastToAPInt();
655 unsigned Size = MRI->getType(DstReg).getSizeInBits();
656 if (Size == 16 || Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
657 Register GPRReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
658 if (!materializeImm(GPRReg, Imm.getSExtValue(), MIB))
659 return false;
660
661 unsigned Opcode = Size == 64 ? RISCV::FMV_D_X
662 : Size == 32 ? RISCV::FMV_W_X
663 : RISCV::FMV_H_X;
664 auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
665 if (!FMV.constrainAllUses(TII, TRI, RBI))
666 return false;
667 } else {
668 assert(Size == 64 && !Subtarget->is64Bit() &&
669 "Unexpected size or subtarget");
670 // Split into two pieces and build through the stack.
671 Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
672 Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
673 if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
674 MIB))
675 return false;
676 if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MIB))
677 return false;
678 MachineInstrBuilder PairF64 = MIB.buildInstr(
679 RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
680 if (!PairF64.constrainAllUses(TII, TRI, RBI))
681 return false;
682 }
683
684 MI.eraseFromParent();
685 return true;
686 }
687 case TargetOpcode::G_GLOBAL_VALUE: {
688 auto *GV = MI.getOperand(1).getGlobal();
689 if (GV->isThreadLocal()) {
690 // TODO: implement this case.
691 return false;
692 }
693
694 return selectAddr(MI, MIB, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
695 }
696 case TargetOpcode::G_JUMP_TABLE:
697 case TargetOpcode::G_CONSTANT_POOL:
698 return selectAddr(MI, MIB, MRI);
699 case TargetOpcode::G_BRCOND: {
702 getOperandsForBranch(MI.getOperand(0).getReg(), CC, LHS, RHS, *MRI);
703
704 auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(CC), {}, {LHS, RHS})
705 .addMBB(MI.getOperand(1).getMBB());
706 MI.eraseFromParent();
707 return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
708 }
709 case TargetOpcode::G_BRINDIRECT:
710 MI.setDesc(TII.get(RISCV::PseudoBRIND));
711 MI.addOperand(MachineOperand::CreateImm(0));
713 case TargetOpcode::G_FRAME_INDEX: {
714 // TODO: We may want to replace this code with the SelectionDAG patterns,
715 // which fail to get imported because it uses FrameAddrRegImm, which is a
716 // ComplexPattern
717 MI.setDesc(TII.get(RISCV::ADDI));
718 MI.addOperand(MachineOperand::CreateImm(0));
720 }
721 case TargetOpcode::G_SELECT:
722 return selectSelect(MI, MIB);
723 case TargetOpcode::G_FCMP:
724 return selectFPCompare(MI, MIB);
725 case TargetOpcode::G_FENCE: {
726 AtomicOrdering FenceOrdering =
727 static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
728 SyncScope::ID FenceSSID =
729 static_cast<SyncScope::ID>(MI.getOperand(1).getImm());
730 emitFence(FenceOrdering, FenceSSID, MIB);
731 MI.eraseFromParent();
732 return true;
733 }
734 case TargetOpcode::G_IMPLICIT_DEF:
735 return selectImplicitDef(MI, MIB);
736 case TargetOpcode::G_MERGE_VALUES:
737 return selectMergeValues(MI, MIB);
738 case TargetOpcode::G_UNMERGE_VALUES:
739 return selectUnmergeValues(MI, MIB);
740 default:
741 return false;
742 }
743}
744
745bool RISCVInstructionSelector::selectMergeValues(MachineInstr &MI,
746 MachineIRBuilder &MIB) const {
747 assert(MI.getOpcode() == TargetOpcode::G_MERGE_VALUES);
748
749 // Build a F64 Pair from operands
750 if (MI.getNumOperands() != 3)
751 return false;
752 Register Dst = MI.getOperand(0).getReg();
753 Register Lo = MI.getOperand(1).getReg();
754 Register Hi = MI.getOperand(2).getReg();
755 if (!isRegInFprb(Dst) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
756 return false;
757 MI.setDesc(TII.get(RISCV::BuildPairF64Pseudo));
759}
760
761bool RISCVInstructionSelector::selectUnmergeValues(
762 MachineInstr &MI, MachineIRBuilder &MIB) const {
763 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
764
765 // Split F64 Src into two s32 parts
766 if (MI.getNumOperands() != 3)
767 return false;
768 Register Src = MI.getOperand(2).getReg();
769 Register Lo = MI.getOperand(0).getReg();
770 Register Hi = MI.getOperand(1).getReg();
771 if (!isRegInFprb(Src) || !isRegInGprb(Lo) || !isRegInGprb(Hi))
772 return false;
773 MI.setDesc(TII.get(RISCV::SplitF64Pseudo));
775}
776
777bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &Op,
778 MachineIRBuilder &MIB) {
779 Register PtrReg = Op.getReg();
780 assert(MRI->getType(PtrReg).isPointer() && "Operand is not a pointer!");
781
782 const LLT sXLen = LLT::scalar(STI.getXLen());
783 auto PtrToInt = MIB.buildPtrToInt(sXLen, PtrReg);
784 MRI->setRegBank(PtrToInt.getReg(0), RBI.getRegBank(RISCV::GPRBRegBankID));
785 Op.setReg(PtrToInt.getReg(0));
786 return select(*PtrToInt);
787}
788
789void RISCVInstructionSelector::preISelLower(MachineInstr &MI,
790 MachineIRBuilder &MIB) {
791 switch (MI.getOpcode()) {
792 case TargetOpcode::G_PTR_ADD: {
793 Register DstReg = MI.getOperand(0).getReg();
794 const LLT sXLen = LLT::scalar(STI.getXLen());
795
796 replacePtrWithInt(MI.getOperand(1), MIB);
797 MI.setDesc(TII.get(TargetOpcode::G_ADD));
798 MRI->setType(DstReg, sXLen);
799 break;
800 }
801 case TargetOpcode::G_PTRMASK: {
802 Register DstReg = MI.getOperand(0).getReg();
803 const LLT sXLen = LLT::scalar(STI.getXLen());
804 replacePtrWithInt(MI.getOperand(1), MIB);
805 MI.setDesc(TII.get(TargetOpcode::G_AND));
806 MRI->setType(DstReg, sXLen);
807 break;
808 }
809 }
810}
811
812void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
813 const MachineInstr &MI,
814 int OpIdx) const {
815 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
816 "Expected G_CONSTANT");
817 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
818 MIB.addImm(-CstVal);
819}
820
821void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
822 const MachineInstr &MI,
823 int OpIdx) const {
824 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
825 "Expected G_CONSTANT");
826 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
827 MIB.addImm(STI.getXLen() - CstVal);
828}
829
830void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
831 const MachineInstr &MI,
832 int OpIdx) const {
833 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
834 "Expected G_CONSTANT");
835 uint64_t CstVal = MI.getOperand(1).getCImm()->getZExtValue();
836 MIB.addImm(32 - CstVal);
837}
838
839void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
840 const MachineInstr &MI,
841 int OpIdx) const {
842 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
843 "Expected G_CONSTANT");
844 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
845 MIB.addImm(CstVal + 1);
846}
847
848void RISCVInstructionSelector::renderImm(MachineInstrBuilder &MIB,
849 const MachineInstr &MI,
850 int OpIdx) const {
851 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
852 "Expected G_CONSTANT");
853 int64_t CstVal = MI.getOperand(1).getCImm()->getSExtValue();
854 MIB.addImm(CstVal);
855}
856
857void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
858 const MachineInstr &MI,
859 int OpIdx) const {
860 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
861 "Expected G_CONSTANT");
862 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
864}
865
866void RISCVInstructionSelector::renderXLenSubTrailingOnes(
867 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
868 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
869 "Expected G_CONSTANT");
870 uint64_t C = MI.getOperand(1).getCImm()->getZExtValue();
871 MIB.addImm(Subtarget->getXLen() - llvm::countr_one(C));
872}
873
874const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
875 LLT Ty, const RegisterBank &RB) const {
876 if (RB.getID() == RISCV::GPRBRegBankID) {
877 if (Ty.getSizeInBits() <= 32 || (STI.is64Bit() && Ty.getSizeInBits() == 64))
878 return &RISCV::GPRRegClass;
879 }
880
881 if (RB.getID() == RISCV::FPRBRegBankID) {
882 if (Ty.getSizeInBits() == 16)
883 return &RISCV::FPR16RegClass;
884 if (Ty.getSizeInBits() == 32)
885 return &RISCV::FPR32RegClass;
886 if (Ty.getSizeInBits() == 64)
887 return &RISCV::FPR64RegClass;
888 }
889
890 if (RB.getID() == RISCV::VRBRegBankID) {
891 if (Ty.getSizeInBits().getKnownMinValue() <= 64)
892 return &RISCV::VRRegClass;
893
894 if (Ty.getSizeInBits().getKnownMinValue() == 128)
895 return &RISCV::VRM2RegClass;
896
897 if (Ty.getSizeInBits().getKnownMinValue() == 256)
898 return &RISCV::VRM4RegClass;
899
900 if (Ty.getSizeInBits().getKnownMinValue() == 512)
901 return &RISCV::VRM8RegClass;
902 }
903
904 return nullptr;
905}
906
907bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
908 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
909}
910
911bool RISCVInstructionSelector::isRegInFprb(Register Reg) const {
912 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID;
913}
914
915bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
916 Register DstReg = MI.getOperand(0).getReg();
917
918 if (DstReg.isPhysical())
919 return true;
920
921 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
922 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
923 assert(DstRC &&
924 "Register class not available for LLT, register bank combination");
925
926 // No need to constrain SrcReg. It will get constrained when
927 // we hit another of its uses or its defs.
928 // Copies do not have constraints.
929 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
930 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
931 << " operand\n");
932 return false;
933 }
934
935 MI.setDesc(TII.get(RISCV::COPY));
936 return true;
937}
938
939bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI,
940 MachineIRBuilder &MIB) const {
941 assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
942
943 const Register DstReg = MI.getOperand(0).getReg();
944 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
945 MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
946
947 assert(DstRC &&
948 "Register class not available for LLT, register bank combination");
949
950 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
951 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(MI.getOpcode())
952 << " operand\n");
953 }
954 MI.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
955 return true;
956}
957
958bool RISCVInstructionSelector::materializeImm(Register DstReg, int64_t Imm,
959 MachineIRBuilder &MIB) const {
960 if (Imm == 0) {
961 MIB.buildCopy(DstReg, Register(RISCV::X0));
962 RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, *MRI);
963 return true;
964 }
965
967 unsigned NumInsts = Seq.size();
968 Register SrcReg = RISCV::X0;
969
970 for (unsigned i = 0; i < NumInsts; i++) {
971 Register TmpReg = i < NumInsts - 1
972 ? MRI->createVirtualRegister(&RISCV::GPRRegClass)
973 : DstReg;
974 const RISCVMatInt::Inst &I = Seq[i];
976
977 switch (I.getOpndKind()) {
978 case RISCVMatInt::Imm:
979 // clang-format off
980 Result = MIB.buildInstr(I.getOpcode(), {TmpReg}, {})
981 .addImm(I.getImm());
982 // clang-format on
983 break;
985 Result = MIB.buildInstr(I.getOpcode(), {TmpReg},
986 {SrcReg, Register(RISCV::X0)});
987 break;
989 Result = MIB.buildInstr(I.getOpcode(), {TmpReg}, {SrcReg, SrcReg});
990 break;
992 Result =
993 MIB.buildInstr(I.getOpcode(), {TmpReg}, {SrcReg}).addImm(I.getImm());
994 break;
995 }
996
997 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
998 return false;
999
1000 SrcReg = TmpReg;
1001 }
1002
1003 return true;
1004}
1005
1006bool RISCVInstructionSelector::selectAddr(MachineInstr &MI,
1007 MachineIRBuilder &MIB, bool IsLocal,
1008 bool IsExternWeak) const {
1009 assert((MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1010 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1011 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1012 "Unexpected opcode");
1013
1014 const MachineOperand &DispMO = MI.getOperand(1);
1015
1016 Register DefReg = MI.getOperand(0).getReg();
1017 const LLT DefTy = MRI->getType(DefReg);
1018
1019 // When HWASAN is used and tagging of global variables is enabled
1020 // they should be accessed via the GOT, since the tagged address of a global
1021 // is incompatible with existing code models. This also applies to non-pic
1022 // mode.
1023 if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
1024 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1025 // Use PC-relative addressing to access the symbol. This generates the
1026 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
1027 // %pcrel_lo(auipc)).
1028 MI.setDesc(TII.get(RISCV::PseudoLLA));
1030 }
1031
1032 // Use PC-relative addressing to access the GOT for this symbol, then
1033 // load the address from the GOT. This generates the pattern (PseudoLGA
1034 // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
1035 // %pcrel_lo(auipc))).
1036 MachineFunction &MF = *MI.getParent()->getParent();
1041 DefTy, Align(DefTy.getSizeInBits() / 8));
1042
1043 auto Result = MIB.buildInstr(RISCV::PseudoLGA, {DefReg}, {})
1044 .addDisp(DispMO, 0)
1046
1047 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1048 return false;
1049
1050 MI.eraseFromParent();
1051 return true;
1052 }
1053
1054 switch (TM.getCodeModel()) {
1055 default: {
1056 reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
1057 getName(), "Unsupported code model for lowering", MI);
1058 return false;
1059 }
1060 case CodeModel::Small: {
1061 // Must lie within a single 2 GiB address range and must lie between
1062 // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
1063 // (lui %hi(sym)) %lo(sym)).
1064 Register AddrHiDest = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1065 MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI, {AddrHiDest}, {})
1066 .addDisp(DispMO, 0, RISCVII::MO_HI);
1067
1068 if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
1069 return false;
1070
1071 auto Result = MIB.buildInstr(RISCV::ADDI, {DefReg}, {AddrHiDest})
1072 .addDisp(DispMO, 0, RISCVII::MO_LO);
1073
1074 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1075 return false;
1076
1077 MI.eraseFromParent();
1078 return true;
1079 }
1080 case CodeModel::Medium:
1081 // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
1082 // relocation needs to reference a label that points to the auipc
1083 // instruction itself, not the global. This cannot be done inside the
1084 // instruction selector.
1085 if (IsExternWeak) {
1086 // An extern weak symbol may be undefined, i.e. have value 0, which may
1087 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
1088 // symbol. This generates the pattern (PseudoLGA sym), which expands to
1089 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
1090 MachineFunction &MF = *MI.getParent()->getParent();
1095 DefTy, Align(DefTy.getSizeInBits() / 8));
1096
1097 auto Result = MIB.buildInstr(RISCV::PseudoLGA, {DefReg}, {})
1098 .addDisp(DispMO, 0)
1100
1101 if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
1102 return false;
1103
1104 MI.eraseFromParent();
1105 return true;
1106 }
1107
1108 // Generate a sequence for accessing addresses within any 2GiB range
1109 // within the address space. This generates the pattern (PseudoLLA sym),
1110 // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
1111 MI.setDesc(TII.get(RISCV::PseudoLLA));
1113 }
1114
1115 return false;
1116}
1117
1118bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
1119 MachineIRBuilder &MIB) const {
1120 auto &SelectMI = cast<GSelect>(MI);
1121
1122 Register LHS, RHS;
1124 getOperandsForBranch(SelectMI.getCondReg(), CC, LHS, RHS, *MRI);
1125
1126 Register DstReg = SelectMI.getReg(0);
1127
1128 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1129 if (RBI.getRegBank(DstReg, *MRI, TRI)->getID() == RISCV::FPRBRegBankID) {
1130 unsigned Size = MRI->getType(DstReg).getSizeInBits();
1131 Opc = Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1132 : RISCV::Select_FPR64_Using_CC_GPR;
1133 }
1134
1135 MachineInstr *Result = MIB.buildInstr(Opc)
1136 .addDef(DstReg)
1137 .addReg(LHS)
1138 .addReg(RHS)
1139 .addImm(CC)
1140 .addReg(SelectMI.getTrueReg())
1141 .addReg(SelectMI.getFalseReg());
1142 MI.eraseFromParent();
1143 return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
1144}
1145
1146// Convert an FCMP predicate to one of the supported F or D instructions.
1147static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size) {
1148 assert((Size == 16 || Size == 32 || Size == 64) && "Unsupported size");
1149 switch (Pred) {
1150 default:
1151 llvm_unreachable("Unsupported predicate");
1152 case CmpInst::FCMP_OLT:
1153 return Size == 16 ? RISCV::FLT_H : Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1154 case CmpInst::FCMP_OLE:
1155 return Size == 16 ? RISCV::FLE_H : Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1156 case CmpInst::FCMP_OEQ:
1157 return Size == 16 ? RISCV::FEQ_H : Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1158 }
1159}
1160
1161// Try legalizing an FCMP by swapping or inverting the predicate to one that
1162// is supported.
1164 CmpInst::Predicate &Pred, bool &NeedInvert) {
1165 auto isLegalFCmpPredicate = [](CmpInst::Predicate Pred) {
1166 return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE ||
1167 Pred == CmpInst::FCMP_OEQ;
1168 };
1169
1170 assert(!isLegalFCmpPredicate(Pred) && "Predicate already legal?");
1171
1173 if (isLegalFCmpPredicate(InvPred)) {
1174 Pred = InvPred;
1175 std::swap(LHS, RHS);
1176 return true;
1177 }
1178
1179 InvPred = CmpInst::getInversePredicate(Pred);
1180 NeedInvert = true;
1181 if (isLegalFCmpPredicate(InvPred)) {
1182 Pred = InvPred;
1183 return true;
1184 }
1185 InvPred = CmpInst::getSwappedPredicate(InvPred);
1186 if (isLegalFCmpPredicate(InvPred)) {
1187 Pred = InvPred;
1188 std::swap(LHS, RHS);
1189 return true;
1190 }
1191
1192 return false;
1193}
1194
1195// Emit a sequence of instructions to compare LHS and RHS using Pred. Return
1196// the result in DstReg.
1197// FIXME: Maybe we should expand this earlier.
1198bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
1199 MachineIRBuilder &MIB) const {
1200 auto &CmpMI = cast<GFCmp>(MI);
1201 CmpInst::Predicate Pred = CmpMI.getCond();
1202
1203 Register DstReg = CmpMI.getReg(0);
1204 Register LHS = CmpMI.getLHSReg();
1205 Register RHS = CmpMI.getRHSReg();
1206
1207 unsigned Size = MRI->getType(LHS).getSizeInBits();
1208 assert((Size == 16 || Size == 32 || Size == 64) && "Unexpected size");
1209
1210 Register TmpReg = DstReg;
1211
1212 bool NeedInvert = false;
1213 // First try swapping operands or inverting.
1214 if (legalizeFCmpPredicate(LHS, RHS, Pred, NeedInvert)) {
1215 if (NeedInvert)
1216 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1217 auto Cmp = MIB.buildInstr(getFCmpOpcode(Pred, Size), {TmpReg}, {LHS, RHS});
1218 if (!Cmp.constrainAllUses(TII, TRI, RBI))
1219 return false;
1220 } else if (Pred == CmpInst::FCMP_ONE || Pred == CmpInst::FCMP_UEQ) {
1221 // fcmp one LHS, RHS => (OR (FLT LHS, RHS), (FLT RHS, LHS))
1222 NeedInvert = Pred == CmpInst::FCMP_UEQ;
1224 {&RISCV::GPRRegClass}, {LHS, RHS});
1225 if (!Cmp1.constrainAllUses(TII, TRI, RBI))
1226 return false;
1228 {&RISCV::GPRRegClass}, {RHS, LHS});
1229 if (!Cmp2.constrainAllUses(TII, TRI, RBI))
1230 return false;
1231 if (NeedInvert)
1232 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1233 auto Or =
1234 MIB.buildInstr(RISCV::OR, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1235 if (!Or.constrainAllUses(TII, TRI, RBI))
1236 return false;
1237 } else if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) {
1238 // fcmp ord LHS, RHS => (AND (FEQ LHS, LHS), (FEQ RHS, RHS))
1239 // FIXME: If LHS and RHS are the same we can use a single FEQ.
1240 NeedInvert = Pred == CmpInst::FCMP_UNO;
1242 {&RISCV::GPRRegClass}, {LHS, LHS});
1243 if (!Cmp1.constrainAllUses(TII, TRI, RBI))
1244 return false;
1246 {&RISCV::GPRRegClass}, {RHS, RHS});
1247 if (!Cmp2.constrainAllUses(TII, TRI, RBI))
1248 return false;
1249 if (NeedInvert)
1250 TmpReg = MRI->createVirtualRegister(&RISCV::GPRRegClass);
1251 auto And =
1252 MIB.buildInstr(RISCV::AND, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1253 if (!And.constrainAllUses(TII, TRI, RBI))
1254 return false;
1255 } else
1256 llvm_unreachable("Unhandled predicate");
1257
1258 // Emit an XORI to invert the result if needed.
1259 if (NeedInvert) {
1260 auto Xor = MIB.buildInstr(RISCV::XORI, {DstReg}, {TmpReg}).addImm(1);
1261 if (!Xor.constrainAllUses(TII, TRI, RBI))
1262 return false;
1263 }
1264
1265 MI.eraseFromParent();
1266 return true;
1267}
1268
1269void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
1270 SyncScope::ID FenceSSID,
1271 MachineIRBuilder &MIB) const {
1272 if (STI.hasStdExtZtso()) {
1273 // The only fence that needs an instruction is a sequentially-consistent
1274 // cross-thread fence.
1275 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1276 FenceSSID == SyncScope::System) {
1277 // fence rw, rw
1278 MIB.buildInstr(RISCV::FENCE, {}, {})
1281 return;
1282 }
1283
1284 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
1285 MIB.buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1286 return;
1287 }
1288
1289 // singlethread fences only synchronize with signal handlers on the same
1290 // thread and thus only need to preserve instruction order, not actually
1291 // enforce memory ordering.
1292 if (FenceSSID == SyncScope::SingleThread) {
1293 MIB.buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1294 return;
1295 }
1296
1297 // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1298 // Manual: Volume I.
1299 unsigned Pred, Succ;
1300 switch (FenceOrdering) {
1301 default:
1302 llvm_unreachable("Unexpected ordering");
1303 case AtomicOrdering::AcquireRelease:
1304 // fence acq_rel -> fence.tso
1305 MIB.buildInstr(RISCV::FENCE_TSO, {}, {});
1306 return;
1307 case AtomicOrdering::Acquire:
1308 // fence acquire -> fence r, rw
1309 Pred = RISCVFenceField::R;
1311 break;
1312 case AtomicOrdering::Release:
1313 // fence release -> fence rw, w
1315 Succ = RISCVFenceField::W;
1316 break;
1317 case AtomicOrdering::SequentiallyConsistent:
1318 // fence seq_cst -> fence rw, rw
1321 break;
1322 }
1323 MIB.buildInstr(RISCV::FENCE, {}, {}).addImm(Pred).addImm(Succ);
1324}
1325
1326namespace llvm {
1329 const RISCVSubtarget &Subtarget,
1330 const RISCVRegisterBankInfo &RBI) {
1331 return new RISCVInstructionSelector(TM, Subtarget, RBI);
1332}
1333} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
#define LLVM_DEBUG(...)
Definition: Debug.h:106
uint64_t Size
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
#define I(x, y, z)
Definition: MD5.cpp:58
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static StringRef getName(Value *V)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
Value * LHS
support::ulittle16_t & Lo
Definition: aarch32.cpp:204
support::ulittle16_t & Hi
Definition: aarch32.cpp:203
APInt bitcastToAPInt() const
Definition: APFloat.h:1346
Class for arbitrary precision integers.
Definition: APInt.h:78
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1468
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:673
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:676
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition: InstrTypes.h:679
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition: InstrTypes.h:681
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition: InstrTypes.h:684
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition: InstrTypes.h:680
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition: InstrTypes.h:682
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition: InstrTypes.h:683
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition: InstrTypes.h:825
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition: InstrTypes.h:787
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:163
This is an important base class in LLVM.
Definition: Constant.h:42
This class represents an Operation in the Expression.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual void setupMF(MachineFunction &mf, GISelKnownBits *kb, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr bool isValid() const
Definition: LowLevelType.h:145
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:190
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 & 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 & 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.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
A description of a memory reference used in the backend.
@ 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).
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.
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
This class implements the register bank concept.
Definition: RegisterBank.h:28
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:45
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:95
size_t size() const
Definition: SmallVector.h:78
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
unsigned getID() const
Return the register class ID number.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition: TypeSize.h:168
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
Definition: BitmaskEnum.h:125
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(int64_t 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, bool Imm=false)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
static constexpr int64_t VLMaxSentinel
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition: LLVMContext.h:54
@ System
Synchronized with respect to all concurrently executing threads.
Definition: LLVMContext.h:57
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition: bit.h:307
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
InstructionSelector * createRISCVInstructionSelector(const RISCVTargetMachine &TM, const RISCVSubtarget &Subtarget, const RISCVRegisterBankInfo &RBI)
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:299
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:215
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
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ Xor
Bitwise or logical XOR of integers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
#define MORE()
Definition: regcomp.c:252
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Matching combinators.
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.