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 {
66 bool runOnMachineFunction(MachineFunction &MF)
override;
69 const ARCSubtarget *AST =
nullptr;
70 const ARCInstrInfo *AII =
nullptr;
71 MachineRegisterInfo *MRI =
nullptr;
72 MachineDominatorTree *MDT =
nullptr;
76 MachineInstr *tryToCombine(MachineInstr &Ldst);
79 bool noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
80 const MachineInstr *Ldst);
84 bool canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To);
94 MachineInstr *canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
95 SmallVectorImpl<MachineInstr *> *
Uses);
100 MachineOperand &Incr,
unsigned BaseReg);
110 void changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
111 unsigned NewBase, MachineOperand &NewOffset);
118char ARCOptAddrMode::ID = 0;
135 switch (
MI.getOpcode()) {
140 assert(
MI.getOperand(2).isImm() &&
"Expected immediate operand");
141 Amount = Sign *
MI.getOperand(2).getImm();
162 assert(InstBB !=
MBB &&
"Instruction found in empty MBB");
181 unsigned BasePos, OffPos;
182 if (!
TII->getBaseAndOffsetPosition(
MI, BasePos, OffPos))
191bool ARCOptAddrMode::noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
197MachineInstr *ARCOptAddrMode::tryToCombine(MachineInstr &Ldst) {
200 unsigned BasePos, OffsetPos;
211 assert(
Base.isReg() &&
"Base operand must be register");
218 if (!Register::isVirtualRegister(
B)) {
224 if (
Offset.getImm() != 0) {
236 SmallVector<MachineInstr *, 8>
Uses;
237 MachineInstr *MoveTo = canJoinInstructions(&Ldst, &
Add, &
Uses);
242 if (!canFixPastUses(
Uses,
Add.getOperand(2),
B))
247 dbgs() <<
"[ABAW] Instructions " << *
First <<
" and " << *
Last
253 if (MoveTo == &
Add) {
260 fixPastUses(
Uses,
B, Incr);
262 int NewOpcode = ARC::getPostIncOpcode(Ldst.
getOpcode());
263 assert(NewOpcode > 0 &&
"No postincrement form found");
264 unsigned NewBaseReg =
Add.getOperand(0).getReg();
265 changeToAddrMode(Ldst, NewOpcode, NewBaseReg,
Add.getOperand(2));
266 Add.eraseFromParent();
274ARCOptAddrMode::canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
275 SmallVectorImpl<MachineInstr *> *
Uses) {
276 assert(Ldst &&
Add &&
"NULL instruction passed");
279 MachineInstr *
Last = Ldst;
287 unsigned BasePos, OffPos;
292 <<
"[canJoinInstructions] Cannot determine base/offset position\n");
306 if (
Add->getOperand(0).getReg() == StReg || BaseReg == StReg) {
307 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Store uses result of Add\n");
312 SmallVector<MachineInstr *, 4> UsesAfterLdst;
313 SmallVector<MachineInstr *, 4> UsesAfterAdd;
325 MachineInstr *
Result =
nullptr;
332 if (noUseOfAddBeforeLoadOrStore(
First,
Last)) {
334 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can sink Add down to Ldst\n");
335 }
else if (canHoistLoadStoreTo(Ldst,
Add)) {
337 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Ldst to Add\n");
344 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Add to Ldst\n");
347 *
Uses = (
Result == Ldst) ? UsesAfterLdst : UsesAfterAdd;
352 MachineOperand &Incr,
unsigned BaseReg) {
354 assert(Incr.
isImm() &&
"Expected immediate increment");
355 int64_t NewOffset = Incr.
getImm();
356 for (MachineInstr *
MI :
Uses) {
365 LLVM_DEBUG(
dbgs() <<
"Instruction cannot handle displacement " << -NewOffset
373 unsigned NewBase, int64_t NewOffset) {
375 for (MachineInstr *
MI :
Uses) {
377 unsigned BasePos, OffPos;
381 "New offset won't fit into ADD instr");
385 MachineOperand &MO =
MI->getOperand(OffPos);
386 assert(MO.
isImm() &&
"expected immediate operand");
389 "New offset won't fit into LD/ST");
393 MI->getOperand(BasePos).setReg(NewBase);
394 MI->getOperand(OffPos).setImm(NewOffset);
398bool ARCOptAddrMode::canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To) {
405 for (;
MI != ME &&
MI != End; ++
MI) {
406 if (
MI->isDebugValue())
408 if (
MI->mayStore() ||
MI->isCall() ||
MI->isInlineAsm() ||
409 MI->hasUnmodeledSideEffects())
411 if (IsStore &&
MI->mayLoad())
416 if (!
O.isReg() || !
O.isUse())
419 if (!OpDef || !MDT->
dominates(OpDef, To))
450void ARCOptAddrMode::changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
452 MachineOperand &NewOffset) {
454 unsigned BasePos, OffPos;
477bool ARCOptAddrMode::processBasicBlock(MachineBasicBlock &
MBB) {
480 if (
MI->isDebugValue())
482 if (!
MI->mayLoad() && !
MI->mayStore())
484 if (ARC::getPostIncOpcode(
MI->getOpcode()) < 0)
486 MachineInstr *Res = tryToCombine(*
MI);
496bool ARCOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
500#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
510 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
516#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
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
static bool processBasicBlock(MachineBasicBlock &MBB, BlockStateMap &BlockStates, DirtySuccessorsWorkList &DirtySuccessors, bool IsX86INTR, const TargetInstrInfo *TII)
Loop over all of the instructions in the basic block, inserting vzeroupper instructions before functi...
virtual bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
const ARCInstrInfo * getInstrInfo() const override
AnalysisUsage & addRequired()
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,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
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.
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.