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)
111 void changeToAddrMode(
MachineInstr &Ldst,
unsigned NewOpcode,
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;
192bool ARCOptAddrMode::noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
201 unsigned BasePos, OffsetPos;
204 if (!AII->getBaseAndOffsetPosition(Ldst, BasePos, OffsetPos)) {
212 assert(
Base.isReg() &&
"Base operand must be register");
225 if (
Offset.getImm() != 0) {
230 for (
auto &
Add :
MRI->use_nodbg_instructions(
B)) {
243 if (!canFixPastUses(
Uses,
Add.getOperand(2),
B))
248 dbgs() <<
"[ABAW] Instructions " << *
First <<
" and " << *
Last
254 if (MoveTo == &
Add) {
256 Add.getParent()->insertAfter(
Add.getIterator(), &Ldst);
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();
277 assert(Ldst &&
Add &&
"NULL instruction passed");
281 if (MDT->dominates(Ldst,
Add))
283 else if (!MDT->dominates(
Add, Ldst))
288 unsigned BasePos, OffPos;
290 if (!AII->getBaseAndOffsetPosition(*Ldst, 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");
318 if (&
MI !=
Add && MDT->dominates(Ldst, &
MI))
320 else if (!MDT->dominates(&
MI, Ldst))
322 if (MDT->dominates(
Add, &
MI))
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;
355 assert(Incr.
isImm() &&
"Expected immediate increment");
356 int64_t NewOffset = Incr.
getImm();
366 LLVM_DEBUG(
dbgs() <<
"Instruction cannot handle displacement " << -NewOffset
374 unsigned NewBase, int64_t NewOffset) {
378 unsigned BasePos, OffPos;
382 "New offset won't fit into ADD instr");
385 }
else if (AII->getBaseAndOffsetPosition(*
MI, BasePos, 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);
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())
420 if (!OpDef || !MDT->dominates(OpDef, To))
451void ARCOptAddrMode::changeToAddrMode(
MachineInstr &Ldst,
unsigned NewOpcode,
455 unsigned BasePos, OffPos;
457 AII->getBaseAndOffsetPosition(Ldst, BasePos, OffPos);
469 Ldst.
setDesc(AST->getInstrInfo()->get(NewOpcode));
479 bool Changed =
false;
481 if (
MI->isDebugValue())
483 if (!
MI->mayLoad() && !
MI->mayStore())
485 if (ARC::getPostIncOpcode(
MI->getOpcode()) < 0)
501#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
511 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
513 bool Changed =
false;
515 Changed |= processBasicBlock(
MBB);
517#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
unsigned const MachineRegisterInfo * MRI
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
#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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const ARCInstrInfo * getInstrInfo() const override
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
FunctionPass class - This class is used to implement most global optimizations.
bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
For instructions with a base and offset, return the position of the base register and offset operands...
reverse_iterator rbegin()
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
const MachineBasicBlock * getParent() const
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
iterator_range< mop_iterator > explicit_operands()
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
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...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
static constexpr bool isStackSlot(unsigned Reg)
isStackSlot - Sometimes it is useful to be able to store a non-negative frame index in a variable tha...
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
A Use represents the edge between a Value definition and its users.
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)
This is an optimization pass for GlobalISel generic memory operations.
void initializeARCOptAddrModePass(PassRegistry &)
static cl::opt< unsigned > ArcKillAddrMode("arc-kill-addr-mode", cl::init(0), cl::ReallyHidden)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionPass * createARCOptAddrMode()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.