21#define RISCV_MOVE_MERGE_NAME "RISC-V Zcmp move merging pass"
36 bool isGPRPairCopyCandidate(
const DestSourcePair &RegPair,
bool EvenRegPair);
71char RISCVMoveMerge::ID = 0;
79 if (ST.hasStdExtZdinx())
80 return RISCV::FSGNJ_D_IN32X;
83 return RISCV::PADD_DW;
89 if (ST.hasStdExtZcmp())
90 return MoveFromSToA ? RISCV::CM_MVA01S : RISCV::CM_MVSA01;
92 if (ST.hasVendorXqccmp())
93 return MoveFromSToA ? RISCV::QC_CM_MVA01S : RISCV::QC_CM_MVSA01;
102 return RISCV::PLI_DB;
104 return RISCV::PLI_DH;
106 return RISCV::PLUI_DH;
112bool RISCVMoveMerge::isGPRPairCopyCandidate(
const DestSourcePair &RegPair,
117 if (Source == Destination)
120 if ((!ST->hasStdExtZdinx() && !ST->hasStdExtP()) || ST->
is64Bit())
123 unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
126 TRI->getMatchingSuperReg(Source, SubIdx, &RISCV::GPRPairRegClass);
128 TRI->getMatchingSuperReg(Destination, SubIdx, &RISCV::GPRPairRegClass);
134bool RISCVMoveMerge::isCandidateToMergeMVA01S(
const DestSourcePair &RegPair) {
138 if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
139 (Destination == RISCV::X10 || Destination == RISCV::X11) &&
140 RISCV::SR07RegClass.contains(Source))
146bool RISCVMoveMerge::isCandidateToMergeMVSA01(
const DestSourcePair &RegPair) {
150 if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
151 (Source == RISCV::X10 || Source == RISCV::X11) &&
152 RISCV::SR07RegClass.contains(Destination))
159bool RISCVMoveMerge::isPLIPairCandidate(
const MachineInstr &
MI,
161 if (!ST->hasStdExtP() || ST->
is64Bit())
165 unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
167 ->getMatchingSuperReg(
MI.getOperand(0).getReg(), SubIdx,
168 &RISCV::GPRPairRegClass)
175 bool RegPairIsEven) {
178 DestSourcePair FirstPair = *
TII->isCopyInstrImpl(*
I);
179 DestSourcePair SecondPair = *
TII->isCopyInstrImpl(*Paired);
187 MachineOperand PairedSource = *SecondPair.
Source;
189 unsigned Opcode = getGPRPairCopyOpcode(*ST);
190 for (
auto It = std::next(
I); It != Paired && PairedSource.
isKill(); ++It)
191 if (It->readsRegister(PairedSource.
getReg(),
TRI))
195 unsigned GPRPairIdx =
196 RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
197 SrcReg1 =
TRI->getMatchingSuperReg(FirstPair.
Source->
getReg(), GPRPairIdx,
198 &RISCV::GPRPairRegClass);
199 SrcReg2 = ST->hasStdExtZdinx() ? SrcReg1 :
Register(RISCV::X0_Pair);
201 GPRPairIdx, &RISCV::GPRPairRegClass);
210 Paired->eraseFromParent();
218 const MachineOperand *Sreg1, *Sreg2;
221 DestSourcePair FirstPair = *
TII->isCopyInstrImpl(*
I);
222 DestSourcePair PairedRegs = *
TII->isCopyInstrImpl(*Paired);
231 MachineOperand PairedSource = *PairedRegs.
Source;
246 for (
auto It = std::next(
I); It != Paired && PairedSource.
isKill(); ++It)
247 if (It->readsRegister(PairedSource.
getReg(),
TRI))
251 Sreg2 = &PairedSource;
264 Paired->eraseFromParent();
271 bool RegPairIsEven) {
280 unsigned GPRPairIdx =
281 RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
283 I->getOperand(0).getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
286 .
addImm(
I->getOperand(1).getImm());
289 Paired->eraseFromParent();
296 const DestSourcePair &RegPair) {
298 ModifiedRegUnits.
clear();
299 UsedRegUnits.
clear();
300 unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
301 unsigned SecondPairIdx =
302 !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
306 RegPair.
Source->
getReg(), RegPairIdx, &RISCV::GPRPairRegClass);
309 Register ExpectedSourceReg =
TRI->getSubReg(SrcGPRPair, SecondPairIdx);
310 Register ExpectedDestReg =
TRI->getSubReg(DestGPRPair, SecondPairIdx);
315 MachineInstr &
MI = *
I;
317 if (
auto SecondPair =
TII->isCopyInstrImpl(
MI)) {
327 if (SourceReg == ExpectedSourceReg && DestReg == ExpectedDestReg)
334 if (!ModifiedRegUnits.
available(ExpectedDestReg) ||
335 !UsedRegUnits.
available(ExpectedDestReg) ||
336 !ModifiedRegUnits.
available(ExpectedSourceReg))
345 const DestSourcePair &RegPair) {
350 ModifiedRegUnits.
clear();
351 UsedRegUnits.
clear();
356 MachineInstr &
MI = *
I;
358 if (
auto SecondPair =
TII->isCopyInstrImpl(
MI)) {
362 bool IsCandidate = MoveFromSToA ? isCandidateToMergeMVA01S(*SecondPair)
363 : isCandidateToMergeMVSA01(*SecondPair);
370 if (!MoveFromSToA && RegPair.
Source->
getReg() == SourceReg)
376 if (!ModifiedRegUnits.
available(DestReg) ||
396 ModifiedRegUnits.
clear();
397 UsedRegUnits.
clear();
398 unsigned Opc =
MBBI->getOpcode();
400 int64_t FirstImm =
MBBI->getOperand(1).getImm();
401 unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
402 unsigned SecondPairIdx =
403 !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
406 Register DestGPRPair =
TRI->getMatchingSuperReg(FirstDestReg, RegPairIdx,
407 &RISCV::GPRPairRegClass);
408 Register ExpectedDestReg =
TRI->getSubReg(DestGPRPair, SecondPairIdx);
413 MachineInstr &
MI = *
I;
415 if (
MI.getOpcode() ==
Opc) {
417 int64_t
Imm =
MI.getOperand(1).getImm();
419 if (FirstDestReg == DestReg)
423 if (DestReg == ExpectedDestReg && Imm == FirstImm)
430 if (!ModifiedRegUnits.
available(ExpectedDestReg) ||
431 !UsedRegUnits.
available(ExpectedDestReg))
439bool RISCVMoveMerge::mergeMovePairs(MachineBasicBlock &
MBB) {
445 bool IsPLIEven = isPLIPairCandidate(*
MBBI,
true);
446 bool IsPLIOdd = isPLIPairCandidate(*
MBBI,
false);
447 if (IsPLIEven != IsPLIOdd) {
450 MBBI = mergePLIPair(
MBBI, Paired, IsPLIEven);
458 auto RegPair =
TII->isCopyInstrImpl(*
MBBI);
459 if (RegPair.has_value()) {
460 bool MoveFromSToA = isCandidateToMergeMVA01S(*RegPair);
461 bool MoveFromAToS = isCandidateToMergeMVSA01(*RegPair);
462 bool IsEven = isGPRPairCopyCandidate(*RegPair,
true);
463 bool IsOdd = isGPRPairCopyCandidate(*RegPair,
false);
464 if (!MoveFromSToA && !MoveFromAToS && !IsEven && !IsOdd) {
470 if (MoveFromSToA || MoveFromAToS) {
471 Paired = findMatchingSACopy(
MBBI, MoveFromSToA, *RegPair);
473 MBBI = mergePairedInsns(
MBBI, Paired, MoveFromSToA);
478 if (IsEven != IsOdd) {
479 Paired = findMatchingGPRPairCopy(
MBBI, IsEven, *RegPair);
481 MBBI = mergeGPRPairInsns(
MBBI, Paired, IsEven);
492bool RISCVMoveMerge::runOnMachineFunction(MachineFunction &Fn) {
497 bool HasGPRPairCopy =
498 !ST->
is64Bit() && (ST->hasStdExtZdinx() || ST->hasStdExtP());
499 if (!ST->hasStdExtZcmp() && !ST->hasVendorXqccmp() && !HasGPRPairCopy)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static unsigned getCM_MVOpcode(const RISCVSubtarget &ST, bool MoveFromSToA)
#define RISCV_MOVE_MERGE_NAME
static unsigned getPairedPLIOpcode(unsigned Opc)
FunctionPass class - This class is used to implement most global optimizations.
A set of register units used to track register liveness.
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
void clear()
Clears the set.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
constexpr bool isValid() const
Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionPass * createRISCVMoveMergePass()
createRISCVMoveMergePass - returns an instance of the move merge pass.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr RegState getKillRegState(bool B)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
const MachineOperand * Source
const MachineOperand * Destination