26#define DEBUG_TYPE "riscv-fold-mem-offset"
27#define RISCV_FOLD_MEM_OFFSET_NAME "RISC-V Fold Memory Offset"
31class RISCVFoldMemOffsetImpl {
36 bool foldOffset(
Register OrigReg, int64_t InitialOffset,
60 std::optional<int64_t>
Offset;
63 bool hasValue()
const {
return Offset.has_value(); }
66 FoldableOffset &operator=(int64_t
RHS) {
83char RISCVFoldMemOffsetLegacy::ID = 0;
88 return new RISCVFoldMemOffsetLegacy();
98bool RISCVFoldMemOffsetImpl::foldOffset(
102 DenseMap<Register, int64_t> RegToOffsetMap;
105 RegToOffsetMap[OrigReg] = InitialOffset;
107 std::queue<Register> Worklist;
108 Worklist.push(OrigReg);
110 while (!Worklist.empty()) {
120 switch (
User.getOpcode()) {
124 if (
auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
125 I != RegToOffsetMap.
end())
127 if (
auto I = RegToOffsetMap.
find(
User.getOperand(2).getReg());
128 I != RegToOffsetMap.
end())
132 if (
auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
133 I != RegToOffsetMap.
end())
135 if (
auto I = RegToOffsetMap.
find(
User.getOperand(2).getReg());
136 I != RegToOffsetMap.
end())
140 if (
auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
141 I != RegToOffsetMap.
end())
143 if (
auto I = RegToOffsetMap.
find(
User.getOperand(2).getReg());
144 I != RegToOffsetMap.
end())
148 if (
auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
149 I != RegToOffsetMap.
end())
151 if (
auto I = RegToOffsetMap.
find(
User.getOperand(2).getReg());
152 I != RegToOffsetMap.
end())
156 case RISCV::SH1ADD_UW:
157 case RISCV::SH2ADD_UW:
158 case RISCV::SH3ADD_UW:
160 if (
User.getOperand(1).getReg() ==
Reg)
162 if (
auto I = RegToOffsetMap.
find(
User.getOperand(2).getReg());
163 I != RegToOffsetMap.
end())
167 unsigned ShAmt =
User.getOperand(2).getImm();
168 if (
auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
169 I != RegToOffsetMap.
end())
197 if (
User.getOperand(0).getReg() ==
Reg)
201 if (!
User.getOperand(2).isImm())
206 if (
User.getOperand(1).getReg() == OrigReg)
209 auto I = RegToOffsetMap.
find(
User.getOperand(1).getReg());
210 if (
I == RegToOffsetMap.
end())
213 int64_t LocalOffset =
User.getOperand(2).getImm();
219 FoldableInstrs[&
User] = CombinedOffset;
229 int64_t OffsetVal =
Offset.getValue();
233 Worklist.push(
User.getOperand(0).getReg());
234 }
else if (
P.first->second != OffsetVal) {
235 P.first->second = OffsetVal;
236 Worklist.push(
User.getOperand(0).getReg());
251 bool MadeChange =
false;
252 for (MachineBasicBlock &
MBB : MF) {
256 if (
MI.getOpcode() != RISCV::ADDI)
260 if (!
MI.getOperand(1).isReg() || !
MI.getOperand(2).isImm())
264 if (
MI.getOperand(1).getReg() == RISCV::X0)
267 int64_t
Offset =
MI.getOperand(2).getImm();
270 DenseMap<MachineInstr *, int64_t> FoldableInstrs;
272 if (!foldOffset(
MI.getOperand(0).getReg(),
Offset, MRI, FoldableInstrs))
275 if (FoldableInstrs.
empty())
280 for (
auto [MemMI, NewOffset] : FoldableInstrs)
281 MemMI->getOperand(2).setImm(NewOffset);
285 MI.eraseFromParent();
293bool RISCVFoldMemOffsetLegacy::runOnMachineFunction(
MachineFunction &MF) {
296 return RISCVFoldMemOffsetImpl().run(MF);
302 bool Changed = RISCVFoldMemOffsetImpl().run(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr Value * getValue(Ty &ValueOrUse)
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_FOLD_MEM_OFFSET_NAME
Represent the analysis usage information of a pass.
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.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Represent a constant reference to a string, i.e.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
APInt operator*(APInt a, uint64_t RHS)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createRISCVFoldMemOffsetLegacyPass()