21#include "llvm/IR/IntrinsicsRISCV.h"
24#define DEBUG_TYPE "riscv-isel"
28#define GET_GLOBALISEL_PREDICATE_BITSET
29#include "RISCVGenGlobalISel.inc"
30#undef GET_GLOBALISEL_PREDICATE_BITSET
72#define GET_GLOBALISEL_PREDICATES_DECL
73#include "RISCVGenGlobalISel.inc"
74#undef GET_GLOBALISEL_PREDICATES_DECL
76#define GET_GLOBALISEL_TEMPORARIES_DECL
77#include "RISCVGenGlobalISel.inc"
78#undef GET_GLOBALISEL_TEMPORARIES_DECL
83#define GET_GLOBALISEL_IMPL
84#include "RISCVGenGlobalISel.inc"
85#undef GET_GLOBALISEL_IMPL
87RISCVInstructionSelector::RISCVInstructionSelector(
90 : STI(STI),
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI),
93#include
"RISCVGenGlobalISel.inc"
96#include
"RISCVGenGlobalISel.inc"
102RISCVInstructionSelector::selectShiftMask(
MachineOperand &Root)
const {
110bool RISCVInstructionSelector::earlySelectShift(
113 if (!Subtarget->is64Bit())
116 LLT Ty =
MRI.getType(
I.getOperand(0).getReg());
120 std::optional<int64_t> CstVal =
122 if (!CstVal || !isUInt<5>(*CstVal))
133 unsigned Opc =
MI.getOpcode();
140 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
141 const Register DefReg =
MI.getOperand(0).getReg();
142 const LLT DefTy =
MRI.getType(DefReg);
145 MRI.getRegClassOrRegBank(DefReg);
156 DefRC = getRegClassForTypeOnBank(DefTy, RB);
163 MI.setDesc(
TII.get(TargetOpcode::PHI));
164 return RBI.constrainGenericRegister(DefReg, *DefRC,
MRI);
175 case TargetOpcode::G_ADD: {
178 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
180 std::optional<int64_t> CstVal =
182 if (CstVal && isInt<12>(*CstVal)) {
186 MI.eraseFromParent();
192 case TargetOpcode::G_SUB: {
195 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
197 std::optional<int64_t> CstVal =
199 if (CstVal && ((isInt<12>(*CstVal) && *CstVal != -2048) || *CstVal == 2048)) {
203 MI.eraseFromParent();
209 case TargetOpcode::G_ASHR:
210 if (earlySelectShift(RISCV::SRAIW,
MI, MIB,
MRI))
213 case TargetOpcode::G_LSHR:
214 if (earlySelectShift(RISCV::SRLIW,
MI, MIB,
MRI))
217 case TargetOpcode::G_SHL:
218 if (earlySelectShift(RISCV::SLLIW,
MI, MIB,
MRI))
223 if (selectImpl(
MI, *CoverageInfo))
227 case TargetOpcode::G_ANYEXT:
228 case TargetOpcode::G_TRUNC:
230 case TargetOpcode::G_CONSTANT:
231 return selectConstant(
MI, MIB,
MRI);
232 case TargetOpcode::G_BRCOND: {
236 .addMBB(
MI.getOperand(1).getMBB());
237 MI.eraseFromParent();
240 case TargetOpcode::G_SEXT_INREG:
241 return selectSExtInreg(
MI, MIB);
250 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
251 "Expected G_CONSTANT");
252 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
258 if (RB.
getID() == RISCV::GPRRegBankID) {
260 return &RISCV::GPRRegClass;
275 MRI.getType(DstReg), *RBI.getRegBank(DstReg,
MRI,
TRI));
277 "Register class not available for LLT, register bank combination");
282 if (!RBI.constrainGenericRegister(DstReg, *DstRC,
MRI)) {
288 MI.setDesc(
TII.get(RISCV::COPY));
295 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT);
296 Register FinalReg =
MI.getOperand(0).getReg();
297 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
300 MI.getOperand(1).ChangeToRegister(RISCV::X0,
false);
301 RBI.constrainGenericRegister(FinalReg, RISCV::GPRRegClass,
MRI);
302 MI.setDesc(
TII.get(TargetOpcode::COPY));
308 unsigned NumInsts = Seq.
size();
311 for (
unsigned i = 0; i < NumInsts; i++) {
313 ?
MRI.createVirtualRegister(&RISCV::GPRRegClass)
318 switch (
I.getOpndKind()) {
352 MI.eraseFromParent();
363 if (!
Size.isImm() ||
Size.getImm() != 32)
370 MIB.
buildInstr(RISCV::ADDIW, {Dst.getReg()}, {Src.getReg()}).addImm(0U);
375 MI.eraseFromParent();
384 return new RISCVInstructionSelector(
TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
const HexagonInstrInfo * TII
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const char LLVMTargetMachineRef TM
static StringRef getName(Value *V)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
This file declares the targeting of the RegisterBankInfo class for RISC-V.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
constexpr bool isScalar() const
constexpr bool isValid() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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>.
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.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
T get() const
Returns the value of the specified pointer type.
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwise returns null.
This class provides the information for the target register banks.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures)
This is an optimization pass for GlobalISel generic memory operations.
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...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
InstructionSelector * createRISCVInstructionSelector(const RISCVTargetMachine &TM, RISCVSubtarget &Subtarget, RISCVRegisterBankInfo &RBI)