Go to the documentation of this file.
36 #define DEBUG_TYPE "riscv-merge-base-offset"
37 #define RISCV_MERGE_BASE_OFFSET_NAME "RISCV Merge Base Offset"
74 std::set<MachineInstr *> DeadInstrs;
92 bool RISCVMergeBaseOffsetOpt::detectLuiAddiGlobal(
MachineInstr &HiLUI,
94 if (HiLUI.getOpcode() != RISCV::LUI ||
96 !HiLUI.getOperand(1).isGlobal() ||
97 HiLUI.getOperand(1).getOffset() != 0 ||
100 Register HiLuiDestReg = HiLUI.getOperand(0).getReg();
102 if (LoADDI->getOpcode() != RISCV::ADDI ||
104 !LoADDI->getOperand(2).isGlobal() ||
105 LoADDI->getOperand(2).getOffset() != 0)
113 void RISCVMergeBaseOffsetOpt::foldOffset(
MachineInstr &HiLUI,
121 DeadInstrs.insert(&
Tail);
124 LLVM_DEBUG(
dbgs() <<
" Merged offset " << Offset <<
" into base.\n"
125 <<
" " << HiLUI <<
" " << LoADDI;);
146 bool RISCVMergeBaseOffsetOpt::matchLargeOffset(
MachineInstr &TailAdd,
159 if (OffsetTail.
getOpcode() == RISCV::ADDI ||
160 OffsetTail.
getOpcode() == RISCV::ADDIW) {
166 int64_t OffLo = AddiImmOp.
getImm();
170 if (OffsetLui.
getOpcode() != RISCV::LUI ||
177 if (!
ST->is64Bit() || OffsetTail.
getOpcode() == RISCV::ADDIW)
178 Offset = SignExtend64<32>(Offset);
183 <<
" " << OffsetLui);
184 DeadInstrs.insert(&OffsetTail);
185 DeadInstrs.insert(&OffsetLui);
187 }
else if (OffsetTail.
getOpcode() == RISCV::LUI) {
192 DeadInstrs.insert(&OffsetTail);
207 bool RISCVMergeBaseOffsetOpt::matchShiftedOffset(
MachineInstr &TailShXAdd,
211 TailShXAdd.
getOpcode() == RISCV::SH2ADD ||
212 TailShXAdd.
getOpcode() == RISCV::SH3ADD) &&
213 "Expected SHXADD instruction!");
226 if (OffsetTail.
getOpcode() != RISCV::ADDI)
234 assert(isInt<12>(Offset) &&
"Unexpected offset");
239 case RISCV::SH1ADD: ShAmt = 1;
break;
240 case RISCV::SH2ADD: ShAmt = 2;
break;
241 case RISCV::SH3ADD: ShAmt = 3;
break;
247 DeadInstrs.insert(&OffsetTail);
251 bool RISCVMergeBaseOffsetOpt::detectAndFoldOffset(
MachineInstr &HiLUI,
261 switch (
Tail.getOpcode()) {
263 LLVM_DEBUG(
dbgs() <<
"Don't know how to get offset from this instr:"
274 if (TailTail.
getOpcode() == RISCV::ADDI) {
277 DeadInstrs.insert(&
Tail);
278 foldOffset(HiLUI, LoADDI, TailTail, Offset);
284 foldOffset(HiLUI, LoADDI,
Tail, Offset);
297 if (!matchLargeOffset(
Tail, DestReg, Offset))
299 foldOffset(HiLUI, LoADDI,
Tail, Offset);
304 case RISCV::SH3ADD: {
309 if (!matchShiftedOffset(
Tail, DestReg, Offset))
311 foldOffset(HiLUI, LoADDI,
Tail, Offset);
325 switch (
UseMI.getOpcode()) {
346 if (
UseMI.getOperand(1).isFI())
352 "Expected base address use");
355 if (CommonOffset && Offset != CommonOffset)
371 UseMI.removeOperand(2);
372 UseMI.addOperand(ImmOp);
379 DeadInstrs.insert(&LoADDI);
383 bool RISCVMergeBaseOffsetOpt::runOnMachineFunction(
MachineFunction &Fn) {
389 bool MadeChange =
false;
396 if (!detectLuiAddiGlobal(HiLUI, LoADDI))
400 MadeChange |= detectAndFoldOffset(HiLUI, *LoADDI);
404 for (
auto *
MI : DeadInstrs)
405 MI->eraseFromParent();
411 return new RISCVMergeBaseOffsetOpt();
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder & UseMI
const GlobalValue * getGlobal() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Reg
All possible values of the reg field in the ModR/M byte.
FunctionPass * createRISCVMergeBaseOffsetOptPass()
Returns an instance of the Merge Base Offset Optimization pass.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
Properties which a MachineFunction may have at a given point in time.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
@ Tail
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
MachineOperand class - Representation of each machine instruction operand.
MachineFunctionProperties & set(Property P)
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
constexpr bool isInt< 32 >(int64_t x)
unsigned getTargetFlags() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Representation of each machine instruction.
use_instr_iterator use_instr_begin(Register RegNo) const
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Register getReg() const
getReg - Returns the register number.
StringRef - Represent a constant reference to a string, i.e.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ FLD
This instruction implements an extending load to FP stack slots.
#define RISCV_MERGE_BASE_OFFSET_NAME
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Function & getFunction()
Return the LLVM function that this machine code represents.
INITIALIZE_PASS(RISCVMergeBaseOffsetOpt, DEBUG_TYPE, RISCV_MERGE_BASE_OFFSET_NAME, false, false) bool RISCVMergeBaseOffsetOpt
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
@ ADD
Simple integer binary arithmetic operators.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
FunctionPass class - This class is used to implement most global optimizations.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
void setOffset(int64_t Offset)