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)
55 ARCOptAddrMode() : MachineFunctionPass(ID) {}
59 void getAnalysisUsage(AnalysisUsage &AU)
const override {
68 const ARCSubtarget *AST =
nullptr;
69 const ARCInstrInfo *AII =
nullptr;
70 MachineRegisterInfo *MRI =
nullptr;
71 MachineDominatorTree *MDT =
nullptr;
75 MachineInstr *tryToCombine(MachineInstr &Ldst);
78 bool noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
79 const MachineInstr *Ldst);
83 bool canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To);
93 MachineInstr *canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
94 SmallVectorImpl<MachineInstr *> *
Uses);
99 MachineOperand &Incr,
unsigned BaseReg);
109 void changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
110 unsigned NewBase, MachineOperand &NewOffset);
117char ARCOptAddrMode::ID = 0;
129 switch (
MI.getOpcode()) {
134 assert(
MI.getOperand(2).isImm() &&
"Expected immediate operand");
135 Amount = Sign *
MI.getOperand(2).getImm();
156 assert(InstBB !=
MBB &&
"Instruction found in empty MBB");
175 unsigned BasePos, OffPos;
176 if (!
TII->getBaseAndOffsetPosition(
MI, BasePos, OffPos))
185bool ARCOptAddrMode::noUseOfAddBeforeLoadOrStore(
const MachineInstr *
Add,
191MachineInstr *ARCOptAddrMode::tryToCombine(MachineInstr &Ldst) {
194 unsigned BasePos, OffsetPos;
205 assert(
Base.isReg() &&
"Base operand must be register");
212 if (!Register::isVirtualRegister(
B)) {
218 if (
Offset.getImm() != 0) {
230 SmallVector<MachineInstr *, 8>
Uses;
231 MachineInstr *MoveTo = canJoinInstructions(&Ldst, &
Add, &
Uses);
236 if (!canFixPastUses(
Uses,
Add.getOperand(2),
B))
241 dbgs() <<
"[ABAW] Instructions " << *
First <<
" and " << *
Last
247 if (MoveTo == &
Add) {
254 fixPastUses(
Uses,
B, Incr);
256 int NewOpcode = ARC::getPostIncOpcode(Ldst.
getOpcode());
257 assert(NewOpcode > 0 &&
"No postincrement form found");
258 unsigned NewBaseReg =
Add.getOperand(0).getReg();
259 changeToAddrMode(Ldst, NewOpcode, NewBaseReg,
Add.getOperand(2));
260 Add.eraseFromParent();
268ARCOptAddrMode::canJoinInstructions(MachineInstr *Ldst, MachineInstr *
Add,
269 SmallVectorImpl<MachineInstr *> *
Uses) {
270 assert(Ldst &&
Add &&
"NULL instruction passed");
273 MachineInstr *
Last = Ldst;
281 unsigned BasePos, OffPos;
286 <<
"[canJoinInstructions] Cannot determine base/offset position\n");
300 if (
Add->getOperand(0).getReg() == StReg || BaseReg == StReg) {
301 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Store uses result of Add\n");
306 SmallVector<MachineInstr *, 4> UsesAfterLdst;
307 SmallVector<MachineInstr *, 4> UsesAfterAdd;
319 MachineInstr *
Result =
nullptr;
326 if (noUseOfAddBeforeLoadOrStore(
First,
Last)) {
328 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can sink Add down to Ldst\n");
329 }
else if (canHoistLoadStoreTo(Ldst,
Add)) {
331 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Ldst to Add\n");
338 LLVM_DEBUG(
dbgs() <<
"[canJoinInstructions] Can hoist Add to Ldst\n");
341 *
Uses = (
Result == Ldst) ? UsesAfterLdst : UsesAfterAdd;
346 MachineOperand &Incr,
unsigned BaseReg) {
348 assert(Incr.
isImm() &&
"Expected immediate increment");
349 int64_t NewOffset = Incr.
getImm();
350 for (MachineInstr *
MI :
Uses) {
359 LLVM_DEBUG(
dbgs() <<
"Instruction cannot handle displacement " << -NewOffset
367 unsigned NewBase, int64_t NewOffset) {
369 for (MachineInstr *
MI :
Uses) {
371 unsigned BasePos, OffPos;
375 "New offset won't fit into ADD instr");
379 MachineOperand &MO =
MI->getOperand(OffPos);
380 assert(MO.
isImm() &&
"expected immediate operand");
383 "New offset won't fit into LD/ST");
387 MI->getOperand(BasePos).setReg(NewBase);
388 MI->getOperand(OffPos).setImm(NewOffset);
392bool ARCOptAddrMode::canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To) {
399 for (;
MI != ME &&
MI != End; ++
MI) {
400 if (
MI->isDebugValue())
402 if (
MI->mayStore() ||
MI->isCall() ||
MI->isInlineAsm() ||
403 MI->hasUnmodeledSideEffects())
405 if (IsStore &&
MI->mayLoad())
410 if (!
O.isReg() || !
O.isUse())
413 if (!OpDef || !MDT->
dominates(OpDef, To))
444void ARCOptAddrMode::changeToAddrMode(MachineInstr &Ldst,
unsigned NewOpcode,
446 MachineOperand &NewOffset) {
448 unsigned BasePos, OffPos;
471bool ARCOptAddrMode::processBasicBlock(MachineBasicBlock &
MBB) {
474 if (
MI->isDebugValue())
476 if (!
MI->mayLoad() && !
MI->mayStore())
478 if (ARC::getPostIncOpcode(
MI->getOpcode()) < 0)
480 MachineInstr *Res = tryToCombine(*
MI);
494#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
504 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
510#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 bool isAddConstantOp(const MachineInstr &MI, int64_t &Amount)
static bool isValidLoadStoreOffset(int64_t Off)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Promote Memory to Register
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.
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 LLVM_READONLY 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
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.
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.