39#define DEBUG_TYPE "riscv-copyelim"
41STATISTIC(NumCopiesRemoved,
"Number of copies removed.");
54 MachineFunctionProperties getRequiredProperties()
const override {
55 return MachineFunctionProperties().setNoVRegs();
58 StringRef getPassName()
const override {
59 return "RISC-V Redundant Copy Elimination";
62 void getAnalysisUsage(AnalysisUsage &AU)
const override {
73char RISCVRedundantCopyElimination::ID = 0;
76 "RISC-V Redundant Copy Elimination",
false,
false)
82 assert(
Cond.size() == 3 &&
"Unexpected number of operands");
83 assert(
TBB !=
nullptr &&
"Expected branch target basic block");
98 assert(
Cond.size() == 3 &&
"Unexpected number of operands");
99 assert(
TBB !=
nullptr &&
"Expected branch target basic block");
101 if ((
Opc == RISCV::QC_BEQI ||
Opc == RISCV::QC_E_BEQI ||
102 Opc == RISCV::NDS_BEQC ||
Opc == RISCV::BEQI) &&
105 if ((
Opc == RISCV::QC_BNEI ||
Opc == RISCV::QC_E_BNEI ||
106 Opc == RISCV::NDS_BNEC ||
Opc == RISCV::BNEI) &&
116 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(0).isReg() &&
117 MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
118 MI.getOperand(2).isImm())
119 return RegImmPair(
MI.getOperand(0).getReg(),
MI.getOperand(2).getImm());
120 if (
MI.getOpcode() == RISCV::QC_LI &&
MI.getOperand(0).isReg() &&
121 MI.getOperand(1).isImm())
122 return RegImmPair(
MI.getOperand(0).getReg(),
MI.getOperand(1).getImm());
126static std::optional<int64_t>
130 if (
Reg == RISCV::X0)
133 for (
auto I =
MBB.getFirstTerminator();
I !=
MBB.begin();) {
157 MachineBasicBlock *
TBB =
nullptr, *FBB =
nullptr;
168 bool IsZeroCopy = guaranteesZeroRegInBlock(
MBB,
Cond,
TBB);
170 int64_t CompareImm = IsImmCopy ?
Cond[2].getImm() : 0;
171 if (!IsZeroCopy && !IsImmCopy &&
Cond.
size() == 3 &&
172 (
Cond[0].getImm() == RISCV::BEQ ||
Cond[0].getImm() == RISCV::BNE) &&
177 std::optional<int64_t>
Imm =
180 TargetReg =
Cond[1].getReg();
186 TargetReg =
Cond[2].getReg();
193 IsImmCopy &= (
Cond[0].getImm() == RISCV::BEQ) == (
TBB == &
MBB);
196 if (!IsZeroCopy && !IsImmCopy)
203 MachineInstr *
MI = &*
I;
205 bool RemoveMI =
false;
207 if (
MI->isCopy() &&
MI->getOperand(0).isReg() &&
208 MI->getOperand(1).isReg()) {
212 if (SrcReg == RISCV::X0 && TargetReg == DefReg &&
220 if (Match.
Reg && TargetReg == Match.
Reg && Match.
Imm == CompareImm)
228 MI->eraseFromParent();
235 if (
MI->modifiesRegister(TargetReg,
TRI))
243 assert((CondBr->getOpcode() == RISCV::BEQ ||
244 CondBr->getOpcode() == RISCV::BNE ||
245 CondBr->getOpcode() == RISCV::BEQI ||
246 CondBr->getOpcode() == RISCV::BNEI ||
247 CondBr->getOpcode() == RISCV::QC_BEQI ||
248 CondBr->getOpcode() == RISCV::QC_BNEI ||
249 CondBr->getOpcode() == RISCV::QC_E_BEQI ||
250 CondBr->getOpcode() == RISCV::QC_E_BNEI ||
251 CondBr->getOpcode() == RISCV::NDS_BEQC ||
252 CondBr->getOpcode() == RISCV::NDS_BNEC) &&
253 "Unexpected opcode");
254 assert((CondBr->getOperand(0).getReg() == TargetReg ||
255 CondBr->getOperand(1).getReg() == TargetReg) &&
256 "Unexpected register");
260 CondBr->clearRegisterKills(TargetReg,
TRI);
268 MMI.clearRegisterKills(TargetReg,
TRI);
273bool RISCVRedundantCopyElimination::runOnMachineFunction(
MachineFunction &MF) {
282 for (MachineBasicBlock &
MBB : MF)
289 return new RISCVRedundantCopyElimination();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool guaranteesRegEqualsImmInBlock(MachineBasicBlock &MBB, const SmallVectorImpl< MachineOperand > &Cond, MachineBasicBlock *TBB)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(TBB !=nullptr &&"Expected branch target basic block")
static RegImmPair matchRegImmediate(const MachineInstr &MI)
static std::optional< int64_t > getRegImmediateBeforeTerminator(MachineBasicBlock &MBB, Register Reg, const TargetRegisterInfo *TRI)
static bool optimizeBlock(BasicBlock &BB, bool &ModifiedDT, const TargetTransformInfo &TTI, const DataLayout &DL, bool HasBranchDivergence, DomTreeUpdater *DTU)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
unsigned pred_size() const
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
pred_iterator pred_begin()
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
FunctionPass * createRISCVRedundantCopyEliminationPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Used to describe a register and immediate addition.