44#define DEBUG_TYPE "riscv-redundant-copy-elimination"
46STATISTIC(NumCopiesRemoved,
"Number of copies removed.");
55 MachineFunctionProperties getRequiredProperties()
const override {
56 return MachineFunctionProperties().setNoVRegs();
59 StringRef getPassName()
const override {
60 return "RISC-V Redundant Copy Elimination";
63 void getAnalysisUsage(AnalysisUsage &AU)
const override {
72char RISCVRedundantCopyEliminationLegacy::ID = 0;
75 "RISC-V Redundant Copy Elimination",
false,
false)
81 assert(
Cond.size() == 3 &&
"Unexpected number of operands");
82 assert(
TBB !=
nullptr &&
"Expected branch target basic block");
97 assert(
Cond.size() == 3 &&
"Unexpected number of operands");
98 assert(
TBB !=
nullptr &&
"Expected branch target basic block");
100 if ((
Opc == RISCV::QC_BEQI ||
Opc == RISCV::QC_E_BEQI ||
101 Opc == RISCV::NDS_BEQC ||
Opc == RISCV::BEQI) &&
104 if ((
Opc == RISCV::QC_BNEI ||
Opc == RISCV::QC_E_BNEI ||
105 Opc == RISCV::NDS_BNEC ||
Opc == RISCV::BNEI) &&
114 if (
MI.isCopy() &&
MI.getOperand(0).isReg() &&
MI.getOperand(1).isReg() &&
115 MI.getOperand(1).getReg() == RISCV::X0)
117 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(0).isReg() &&
118 MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
119 MI.getOperand(2).isImm())
120 return RegImmPair(
MI.getOperand(0).getReg(),
MI.getOperand(2).getImm());
121 if (
MI.getOpcode() == RISCV::QC_LI &&
MI.getOperand(0).isReg() &&
122 MI.getOperand(1).isImm())
123 return RegImmPair(
MI.getOperand(0).getReg(),
MI.getOperand(1).getImm());
127static std::optional<int64_t>
131 if (
Reg == RISCV::X0)
134 for (
auto I =
MBB.getFirstTerminator();
I !=
MBB.begin();) {
152 if (
MBB.pred_size() != 1)
163 if (
TII->analyzeBranch(*PredMBB,
TBB, FBB,
Cond,
false) ||
172 bool IsZeroCopy = guaranteesZeroRegInBlock(
MBB,
Cond,
TBB);
174 int64_t CompareImm = IsImmCopy ?
Cond[2].getImm() : 0;
175 if (!IsZeroCopy && !IsImmCopy &&
Cond.size() == 3 &&
176 (
Cond[0].getImm() == RISCV::BEQ ||
Cond[0].getImm() == RISCV::BNE) &&
181 std::optional<int64_t>
Imm =
184 TargetReg =
Cond[1].getReg();
190 TargetReg =
Cond[2].getReg();
197 IsImmCopy &= (
Cond[0].getImm() == RISCV::BEQ) == (
TBB == &
MBB);
200 if (!IsZeroCopy && !IsImmCopy)
212 if (Match.
Reg && TargetReg == Match.
Reg && Match.
Imm == CompareImm &&
213 !
MRI->isReserved(Match.
Reg)) {
217 MI->eraseFromParent();
224 if (
MI->modifiesRegister(TargetReg,
TRI))
232 assert((CondBr->getOpcode() == RISCV::BEQ ||
233 CondBr->getOpcode() == RISCV::BNE ||
234 CondBr->getOpcode() == RISCV::BEQI ||
235 CondBr->getOpcode() == RISCV::BNEI ||
236 CondBr->getOpcode() == RISCV::QC_BEQI ||
237 CondBr->getOpcode() == RISCV::QC_BNEI ||
238 CondBr->getOpcode() == RISCV::QC_E_BEQI ||
239 CondBr->getOpcode() == RISCV::QC_E_BNEI ||
240 CondBr->getOpcode() == RISCV::NDS_BEQC ||
241 CondBr->getOpcode() == RISCV::NDS_BNEC) &&
242 "Unexpected opcode");
243 assert((CondBr->getOperand(0).getReg() == TargetReg ||
244 CondBr->getOperand(1).getReg() == TargetReg) &&
245 "Unexpected register");
249 CondBr->clearRegisterKills(TargetReg,
TRI);
252 if (!
MBB.isLiveIn(TargetReg))
253 MBB.addLiveIn(TargetReg);
257 MMI.clearRegisterKills(TargetReg,
TRI);
275 return new RISCVRedundantCopyEliminationLegacy();
278bool RISCVRedundantCopyEliminationLegacy::runOnMachineFunction(
294 .preserve<MachineRegisterClassAnalysis>();
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)
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
static bool guaranteesRegEqualsImmInBlock(MachineBasicBlock &MBB, const SmallVectorImpl< MachineOperand > &Cond, MachineBasicBlock *TBB)
static bool runRedundantCopyElimination(MachineFunction &MF)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
assert(TBB !=nullptr &&"Expected branch target basic block")
static bool optimizeBlockForRedundantCopies(MachineBasicBlock &MBB, const MachineRegisterInfo *MRI, const TargetRegisterInfo *TRI, const TargetInstrInfo *TII)
static RegImmPair matchRegKnownVal(const MachineInstr &MI)
static std::optional< int64_t > getRegImmediateBeforeTerminator(MachineBasicBlock &MBB, Register Reg, const TargetRegisterInfo *TRI)
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.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
An RAII based helper class to modify MachineFunctionProperties when running pass.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
MachineInstrBundleIterator< MachineInstr > iterator
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,...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
Pass manager infrastructure for declaring and invalidating analyses.
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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createRISCVRedundantCopyEliminationLegacyPass()
Used to describe a register and immediate addition.