41#define DEBUG_TYPE "opt-addr-mode"
66 return "Optimize addressing mode of load/store";
97 bool analyzeUses(
unsigned DefR,
const NodeList &UNodeList,
98 InstrEvalMap &InstrEvalResult,
short &SizeInc);
103 unsigned LRExtReg,
const NodeList &UNodeList);
119char HexagonOptAddrMode::ID = 0;
122 "Optimize addressing mode",
false,
false)
128bool HexagonOptAddrMode::hasRepForm(
MachineInstr &
MI,
unsigned TfrDefR) {
142 return (HII->changeAddrMode_rr_ur(
MI) >= 0);
145 return (HII->changeAddrMode_io_abs(
MI) >= 0);
168 Register OffsetReg =
MI.getOperand(2).getReg();
173 if (OffsetReg == RR.
Reg) {
175 OffsetRegRD = UA.Addr->getReachingDef();
179 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
185 if ((DFG->IsDef(AA) && AA.
Id != OffsetRegRD) ||
186 AA.
Addr->getReachingDef() != OffsetRegRD)
193 MI.getParent() !=
UseMI.getParent())
199 getBaseWithLongOffset(
UseMI) < 0)
207 for (
auto &Mo :
UseMI.operands())
216 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
220 const auto &
P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
223 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n"
225 <<
"The program's complexity may exceed the limits.\n";
229 const auto &ReachingDefs =
P.first;
230 if (ReachingDefs.size() > 1) {
232 dbgs() <<
"*** Multiple Reaching Defs found!!! ***\n";
233 for (
auto DI : ReachingDefs) {
236 dbgs() <<
"\t\t[Reaching Def]: "
253 auto UseSet = LV->getAllReachedUses(DR, DA);
255 for (
auto UI : UseSet) {
259 dbgs() <<
"\t\t\t[Reached Use]: "
269 if (!phiUse.empty()) {
270 for (
auto I : phiUse) {
273 auto phiUseSet =
I.second;
274 for (
auto phiUI : phiUseSet) {
276 UNodeList.push_back(phiUA);
281 UNodeList.push_back(UA);
295 if (LRExtReg == RR.
Reg) {
297 LRExtRegRD = UA.
Addr->getReachingDef();
301 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
309 if ((DFG->IsDef(AA) && AA.
Id != LRExtRegRD) ||
310 AA.
Addr->getReachingDef() != LRExtRegRD) {
312 dbgs() <<
"isSafeToExtLR: Returning false; another reaching def\n");
333 if (HII->isHVXVec(*
MI)) {
336 switch (
MI->getOpcode()) {
337 case Hexagon::V6_vgathermh_pseudo:
338 case Hexagon::V6_vgathermw_pseudo:
339 case Hexagon::V6_vgathermhw_pseudo:
340 case Hexagon::V6_vgathermhq_pseudo:
341 case Hexagon::V6_vgathermwq_pseudo:
342 case Hexagon::V6_vgathermhwq_pseudo:
343 return HII->isValidOffset(
MI->getOpcode(),
Offset, HRI,
false);
352 unsigned AlignMask = 0;
353 switch (HII->getMemAccessSize(*
MI)) {
354 case HexagonII::MemAccessSize::DoubleWordAccess:
357 case HexagonII::MemAccessSize::WordAccess:
360 case HexagonII::MemAccessSize::HalfWordAccess:
363 case HexagonII::MemAccessSize::ByteAccess:
370 if ((AlignMask &
Offset) != 0)
372 return HII->isValidOffset(
MI->getOpcode(),
Offset, HRI,
false);
377 switch (
MI->getOpcode()) {
381 case Hexagon::V6_vgathermh_pseudo:
382 case Hexagon::V6_vgathermw_pseudo:
383 case Hexagon::V6_vgathermhw_pseudo:
384 case Hexagon::V6_vgathermhq_pseudo:
385 case Hexagon::V6_vgathermwq_pseudo:
386 case Hexagon::V6_vgathermhwq_pseudo:
393unsigned HexagonOptAddrMode::getOffsetOpPosition(
MachineInstr *
MI) {
396 "Looking for an offset in non-BaseImmOffset addressing mode instruction");
399 switch (
MI->getOpcode()) {
403 case Hexagon::V6_vgathermh_pseudo:
404 case Hexagon::V6_vgathermw_pseudo:
405 case Hexagon::V6_vgathermhw_pseudo:
406 case Hexagon::V6_vgathermhq_pseudo:
407 case Hexagon::V6_vgathermwq_pseudo:
408 case Hexagon::V6_vgathermhwq_pseudo:
421 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
436 if (!OffsetOp.
isImm())
440 if (!isValidOffset(
MI, newOffset))
450 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
459 if (BaseReg == RR.
Reg)
460 LRExtRegRD = UA.
Addr->getReachingDef();
465 bool Changed =
false;
466 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
469 "Found a PhiRef node as a real reached use!!");
474 <<
">]: " << *
UseMI <<
"\n");
475 Changed |= updateAddUses(AddMI,
UseMI);
481 UseN.
Addr->linkToDef(UseN.
Id, LRExtRegDN);
490bool HexagonOptAddrMode::updateAddUses(
MachineInstr *AddMI,
502 MRI->clearKillFlags(NewReg);
507bool HexagonOptAddrMode::analyzeUses(
unsigned tfrDefR,
509 InstrEvalMap &InstrEvalResult,
511 bool KeepTfr =
false;
512 bool HasRepInstr =
false;
513 InstrEvalResult.clear();
515 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
516 bool CanBeReplaced =
false;
522 if (!hasRepForm(
MI, tfrDefR)) {
527 CanBeReplaced =
true;
528 }
else if (
MI.getOpcode() == Hexagon::S2_addasl_rrri) {
532 getAllRealUses(SN, AddaslUseList);
534 if (allValidCandidates(SN, AddaslUseList) &&
535 canRemoveAddasl(SN,
MI, AddaslUseList)) {
536 SizeInc += AddaslUseList.size();
538 CanBeReplaced =
true;
548 InstrEvalResult[&
MI] = CanBeReplaced;
549 HasRepInstr |= CanBeReplaced;
561 bool Changed =
false;
572 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
573 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
583 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
584 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
598 }
else if (ImmOpNum == 2) {
600 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
601 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
614 for (
unsigned i = OpStart; i < OpEnd; ++i)
622 bool Changed =
false;
623 unsigned OpStart = 0;
632 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
633 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
642 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
643 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
653 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
654 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
665 for (
unsigned i = OpStart; i < OpEnd; ++i)
672short HexagonOptAddrMode::getBaseWithLongOffset(
const MachineInstr &
MI)
const {
674 short TempOpCode = HII->changeAddrMode_io_rr(
MI);
675 return HII->changeAddrMode_rr_ur(TempOpCode);
677 return HII->changeAddrMode_rr_ur(
MI);
689 getAllRealUses(SA, UNodeList);
691 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
694 "Can't transform this 'AddAsl' instruction!");
701 <<
">]: " << *
UseMI <<
"\n");
707 short NewOpCode = getBaseWithLongOffset(*
UseMI);
708 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
736 for (
unsigned i = OpStart; i < OpEnd; ++i)
750 unsigned Changed =
false;
752 Changed = changeLoad(
UseMI, ImmOp, UseMOnum);
754 Changed = changeStore(
UseMI, ImmOp, UseMOnum);
756 Changed = changeAddAsl(UseN,
UseMI, ImmOp, UseMOnum);
765 bool Changed =
false;
767 for (
auto IA : BA.
Addr->members(*DFG)) {
773 if ((
MI->getOpcode() != Hexagon::A2_tfrsi ||
774 !
MI->getOperand(1).isGlobal()) &&
775 (
MI->getOpcode() != Hexagon::A2_addi ||
776 !
MI->getOperand(2).isImm() || HII->isConstExtended(*
MI)))
780 <<
"]: " << *
MI <<
"\n\t[InstrNode]: "
784 getAllRealUses(SA, UNodeList);
786 if (!allValidCandidates(SA, UNodeList))
799 if (
MI->getOpcode() == Hexagon::A2_addi) {
800 Changed |= processAddUses(SA,
MI, UNodeList);
806 InstrEvalMap InstrEvalResult;
810 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
815 bool KeepTfr =
false;
817 LLVM_DEBUG(
dbgs() <<
"\t[Total reached uses] : " << UNodeList.size()
820 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
823 "Found a PhiRef node as a real reached use!!");
828 <<
">]: " << *
UseMI <<
"\n");
832 for (
unsigned j = 0;
j < NumOperands - 1; ++
j) {
834 if (
op.isReg() &&
op.isUse() && DefR ==
op.getReg())
843 bool Xformed =
false;
844 if (UseMOnum >= 0 && InstrEvalResult[
UseMI])
845 Xformed = xformUseMI(
MI,
UseMI, UseN, UseMOnum);
859 bool Changed =
false;
862 HII = HST.getInstrInfo();
863 HRI = HST.getRegisterInfo();
864 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
865 MDT = &getAnalysis<MachineDominatorTree>();
883 Changed |= processBlock(BA);
886 MI->eraseFromParent();
903 return new HexagonOptAddrMode();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " "optimization"))
amode Optimize addressing mode
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Implements a dense probed hash-table based set.
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MachineInstrBundleIterator< MachineInstr > iterator
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getTargetFlags() const
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
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.
StringRef - Represent a constant reference to a string, i.e.
Iterator for intrusive lists based on ilist_node.
#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 initializeHexagonOptAddrModePass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonOptAddrMode()
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
std::unordered_map< RegisterId, DefStack > DefStackMap
std::unordered_map< RegisterId, NodeRefSet > RefMap