15#define GET_INSTRMAP_INFO
32#define OPTADDRMODE_DESC "ARC load/store address mode"
33#define OPTADDRMODE_NAME "arc-addr-mode"
34#define DEBUG_TYPE "arc-addr-mode"
41#define DUMP_BEFORE() ((ArcKillAddrMode & 0x0001) != 0)
42#define DUMP_AFTER() ((ArcKillAddrMode & 0x0002) != 0)
43#define VIEW_BEFORE() ((ArcKillAddrMode & 0x0004) != 0)
44#define VIEW_AFTER() ((ArcKillAddrMode & 0x0008) != 0)
45#define KILL_PASS() ((ArcKillAddrMode & 0x0010) != 0)
60 void getAnalysisUsage(AnalysisUsage &AU)
const override {
67 bool runOnMachineFunction(MachineFunction &MF)
override;
70 const ARCSubtarget *AST =
nullptr;
71 const ARCInstrInfo *AII =
nullptr;
72 MachineRegisterInfo *MRI =
nullptr;
73 MachineDominatorTree *MDT =
nullptr;
77 MachineInstr *tryToCombine(MachineInstr &Ldst);
80 bool noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
81 const MachineInstr *Ldst);
85 bool canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To);
95 MachineInstr *canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
96 SmallVectorImpl<MachineInstr *> *
Uses);
101 MachineOperand &Incr,
unsigned BaseReg);
111 void changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
112 unsigned NewBase, MachineOperand &NewOffset);
114 bool processBasicBlock(MachineBasicBlock &
MBB);
119char ARCOptAddrMode::ID = 0;
136 switch (
MI.getOpcode()) {
141 assert(
MI.getOperand(2).isImm() &&
"Expected immediate operand");
142 Amount = Sign *
MI.getOperand(2).getImm();
163 assert(InstBB !=
MBB &&
"Instruction found in empty MBB");
182 unsigned BasePos, OffPos;
183 if (!
TII->getBaseAndOffsetPosition(
MI, BasePos, OffPos))
192bool ARCOptAddrMode::noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
198MachineInstr *ARCOptAddrMode::tryToCombine(MachineInstr &Ldst) {
201 unsigned BasePos, OffsetPos;
212 assert(
Base.isReg() &&
"Base operand must be register");
219 if (!Register::isVirtualRegister(
B)) {
225 if (
Offset.getImm() != 0) {
230 for (
auto &
Add :
MRI->use_nodbg_instructions(
B)) {
237 SmallVector<MachineInstr *, 8>
Uses;
238 MachineInstr *MoveTo = canJoinInstructions(&Ldst, &
Add, &
Uses);
243 if (!canFixPastUses(
Uses,
Add.getOperand(2),
B))
248 dbgs() <<
"[ABAW] Instructions " << *
First <<
" and " << *
Last
254 if (MoveTo == &
Add) {
261 fixPastUses(
Uses,
B, Incr);
263 int NewOpcode = ARC::getPostIncOpcode(Ldst.
getOpcode());
264 assert(NewOpcode > 0 &&
"No postincrement form found");
265 unsigned NewBaseReg =
Add.getOperand(0).getReg();
266 changeToAddrMode(Ldst, NewOpcode, NewBaseReg,
Add.getOperand(2));
267 Add.eraseFromParent();
275ARCOptAddrMode::canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
276 SmallVectorImpl<MachineInstr *> *
Uses) {
277 assert(Ldst &&
Add &&
"NULL instruction passed");
280 MachineInstr *
Last = Ldst;
288 unsigned BasePos, OffPos;
293 <<
"[canJoinInstructions] Cannot determine base/offset position\n");
307 if (
Add->getOperand(0).getReg() == StReg || BaseReg == StReg) {
308 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Store uses result of Add\n");
313 SmallVector<MachineInstr *, 4> UsesAfterLdst;
314 SmallVector<MachineInstr *, 4> UsesAfterAdd;
315 for (MachineInstr &
MI :
MRI->use_nodbg_instructions(BaseReg)) {
326 MachineInstr *
Result =
nullptr;
333 if (noUseOfAddBeforeLoadOrStore(
First,
Last)) {
335 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can sink Add down to Ldst\n");
336 }
else if (canHoistLoadStoreTo(Ldst,
Add)) {
338 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Ldst to Add\n");
345 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Add to Ldst\n");
348 *
Uses = (
Result == Ldst) ? UsesAfterLdst : UsesAfterAdd;
353 MachineOperand &Incr,
unsigned BaseReg) {
355 assert(Incr.
isImm() &&
"Expected immediate increment");
356 int64_t NewOffset = Incr.
getImm();
357 for (MachineInstr *
MI :
Uses) {
366 LLVM_DEBUG(
dbgs() <<
"Instruction cannot handle displacement " << -NewOffset
374 unsigned NewBase, int64_t NewOffset) {
376 for (MachineInstr *
MI :
Uses) {
378 unsigned BasePos, OffPos;
382 "New offset won't fit into ADD instr");
386 MachineOperand &MO =
MI->getOperand(OffPos);
387 assert(MO.
isImm() &&
"expected immediate operand");
390 "New offset won't fit into LD/ST");
394 MI->getOperand(BasePos).setReg(NewBase);
395 MI->getOperand(OffPos).setImm(NewOffset);
399bool ARCOptAddrMode::canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To) {
406 for (;
MI != ME &&
MI != End; ++
MI) {
407 if (
MI->isDebugValue())
409 if (
MI->mayStore() ||
MI->isCall() ||
MI->isInlineAsm() ||
410 MI->hasUnmodeledSideEffects())
412 if (IsStore &&
MI->mayLoad())
417 if (!
O.isReg() || !
O.isUse())
419 MachineInstr *OpDef =
MRI->getVRegDef(
O.getReg());
420 if (!OpDef || !MDT->
dominates(OpDef, To))
451void ARCOptAddrMode::changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
453 MachineOperand &NewOffset) {
455 unsigned BasePos, OffPos;
478bool ARCOptAddrMode::processBasicBlock(MachineBasicBlock &
MBB) {
481 if (
MI->isDebugValue())
483 if (!
MI->mayLoad() && !
MI->mayStore())
485 if (ARC::getPostIncOpcode(
MI->getOpcode()) < 0)
487 MachineInstr *Res = tryToCombine(*
MI);
497bool ARCOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
501#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
511 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
517#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isLoadStoreThatCanHandleDisplacement(const TargetInstrInfo *TII, const MachineInstr &MI, int64_t Disp)
static bool dominatesAllUsesOf(const MachineInstr *MI, unsigned VReg, MachineDominatorTree *MDT, MachineRegisterInfo *MRI)
static bool isValidIncrementOffset(int64_t Off)
static false bool isValidLoadStoreOffset(int64_t Off)
static bool isAddConstantOp(const MachineInstr &MI, int64_t &Amount)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
virtual bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
const ARCInstrInfo * getInstrInfo() const override
AnalysisUsage & addRequired()
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:
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBundleIterator< const MachineInstr > const_iterator
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
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.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void viewCFG() const
viewCFG - This function is meant for use from the debugger.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
LLVM_ABI MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
const MachineBasicBlock * getParent() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
mop_range explicit_operands()
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
void push_back(const T &Elt)
TargetInstrInfo - Interface to description of machine instruction set.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#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.
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
void initializeARCOptAddrModePass(PassRegistry &)
static cl::opt< unsigned > ArcKillAddrMode("arc-kill-addr-mode", cl::init(0), cl::ReallyHidden)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
ArrayRef(const T &OneElt) -> ArrayRef< T >
FunctionPass * createARCOptAddrMode()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.