41#define DEBUG_TYPE "opt-addr-mode"
68 return "Optimize addressing mode of load/store";
99 bool analyzeUses(
unsigned DefR,
const NodeList &UNodeList,
100 InstrEvalMap &InstrEvalResult,
short &SizeInc);
105 unsigned LRExtReg,
const NodeList &UNodeList);
121char HexagonOptAddrMode::ID = 0;
124 "Optimize addressing mode",
false,
false)
130bool HexagonOptAddrMode::hasRepForm(
MachineInstr &
MI,
unsigned TfrDefR) {
144 return (HII->changeAddrMode_rr_ur(
MI) >= 0);
147 return (HII->changeAddrMode_io_abs(
MI) >= 0);
170 Register OffsetReg =
MI.getOperand(2).getReg();
175 if (OffsetReg == RR.
Reg) {
177 OffsetRegRD = UA.Addr->getReachingDef();
181 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
187 if ((DFG->IsDef(AA) && AA.
Id != OffsetRegRD) ||
188 AA.
Addr->getReachingDef() != OffsetRegRD)
195 MI.getParent() !=
UseMI.getParent())
201 getBaseWithLongOffset(
UseMI) < 0)
209 for (
auto &Mo :
UseMI.operands())
218 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
222 const auto &
P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
225 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n"
227 <<
"The program's complexity may exceed the limits.\n";
231 const auto &ReachingDefs =
P.first;
232 if (ReachingDefs.size() > 1) {
234 dbgs() <<
"*** Multiple Reaching Defs found!!! ***\n";
235 for (
auto DI : ReachingDefs) {
238 dbgs() <<
"\t\t[Reaching Def]: "
255 auto UseSet = LV->getAllReachedUses(DR, DA);
257 for (
auto UI : UseSet) {
261 dbgs() <<
"\t\t\t[Reached Use]: "
271 if (!phiUse.empty()) {
272 for (
auto I : phiUse) {
275 auto phiUseSet =
I.second;
276 for (
auto phiUI : phiUseSet) {
278 UNodeList.push_back(phiUA);
283 UNodeList.push_back(UA);
297 if (LRExtReg == RR.
Reg) {
299 LRExtRegRD = UA.
Addr->getReachingDef();
303 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
311 if ((DFG->IsDef(AA) && AA.
Id != LRExtRegRD) ||
312 AA.
Addr->getReachingDef() != LRExtRegRD) {
314 dbgs() <<
"isSafeToExtLR: Returning false; another reaching def\n");
335 if (HII->isHVXVec(*
MI)) {
338 switch (
MI->getOpcode()) {
339 case Hexagon::V6_vgathermh_pseudo:
340 case Hexagon::V6_vgathermw_pseudo:
341 case Hexagon::V6_vgathermhw_pseudo:
342 case Hexagon::V6_vgathermhq_pseudo:
343 case Hexagon::V6_vgathermwq_pseudo:
344 case Hexagon::V6_vgathermhwq_pseudo:
345 return HII->isValidOffset(
MI->getOpcode(),
Offset, HRI,
false);
354 unsigned AlignMask = 0;
355 switch (HII->getMemAccessSize(*
MI)) {
356 case HexagonII::MemAccessSize::DoubleWordAccess:
359 case HexagonII::MemAccessSize::WordAccess:
362 case HexagonII::MemAccessSize::HalfWordAccess:
365 case HexagonII::MemAccessSize::ByteAccess:
372 if ((AlignMask &
Offset) != 0)
374 return HII->isValidOffset(
MI->getOpcode(),
Offset, HRI,
false);
379 switch (
MI->getOpcode()) {
383 case Hexagon::V6_vgathermh_pseudo:
384 case Hexagon::V6_vgathermw_pseudo:
385 case Hexagon::V6_vgathermhw_pseudo:
386 case Hexagon::V6_vgathermhq_pseudo:
387 case Hexagon::V6_vgathermwq_pseudo:
388 case Hexagon::V6_vgathermhwq_pseudo:
395unsigned HexagonOptAddrMode::getOffsetOpPosition(
MachineInstr *
MI) {
398 "Looking for an offset in non-BaseImmOffset addressing mode instruction");
401 switch (
MI->getOpcode()) {
405 case Hexagon::V6_vgathermh_pseudo:
406 case Hexagon::V6_vgathermw_pseudo:
407 case Hexagon::V6_vgathermhw_pseudo:
408 case Hexagon::V6_vgathermhq_pseudo:
409 case Hexagon::V6_vgathermwq_pseudo:
410 case Hexagon::V6_vgathermhwq_pseudo:
423 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
438 if (!OffsetOp.
isImm())
442 if (!isValidOffset(
MI, newOffset))
452 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
461 if (BaseReg == RR.
Reg)
462 LRExtRegRD = UA.
Addr->getReachingDef();
467 bool Changed =
false;
468 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
471 "Found a PhiRef node as a real reached use!!");
476 <<
">]: " << *
UseMI <<
"\n");
477 Changed |= updateAddUses(AddMI,
UseMI);
483 UseN.
Addr->linkToDef(UseN.
Id, LRExtRegDN);
492bool HexagonOptAddrMode::updateAddUses(
MachineInstr *AddMI,
504 MRI->clearKillFlags(NewReg);
509bool HexagonOptAddrMode::analyzeUses(
unsigned tfrDefR,
511 InstrEvalMap &InstrEvalResult,
513 bool KeepTfr =
false;
514 bool HasRepInstr =
false;
515 InstrEvalResult.clear();
517 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
518 bool CanBeReplaced =
false;
524 if (!hasRepForm(
MI, tfrDefR)) {
529 CanBeReplaced =
true;
530 }
else if (
MI.getOpcode() == Hexagon::S2_addasl_rrri) {
534 getAllRealUses(SN, AddaslUseList);
536 if (allValidCandidates(SN, AddaslUseList) &&
537 canRemoveAddasl(SN,
MI, AddaslUseList)) {
538 SizeInc += AddaslUseList.size();
540 CanBeReplaced =
true;
550 InstrEvalResult[&
MI] = CanBeReplaced;
551 HasRepInstr |= CanBeReplaced;
563 bool Changed =
false;
574 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
575 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
585 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
586 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
600 }
else if (ImmOpNum == 2) {
602 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
603 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
616 for (
unsigned i = OpStart; i < OpEnd; ++i)
624 bool Changed =
false;
625 unsigned OpStart = 0;
634 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
635 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
644 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
645 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
655 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
656 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
667 for (
unsigned i = OpStart; i < OpEnd; ++i)
674short HexagonOptAddrMode::getBaseWithLongOffset(
const MachineInstr &
MI)
const {
676 short TempOpCode = HII->changeAddrMode_io_rr(
MI);
677 return HII->changeAddrMode_rr_ur(TempOpCode);
679 return HII->changeAddrMode_rr_ur(
MI);
691 getAllRealUses(SA, UNodeList);
693 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
696 "Can't transform this 'AddAsl' instruction!");
703 <<
">]: " << *
UseMI <<
"\n");
709 short NewOpCode = getBaseWithLongOffset(*
UseMI);
710 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
738 for (
unsigned i = OpStart; i < OpEnd; ++i)
752 unsigned Changed =
false;
754 Changed = changeLoad(
UseMI, ImmOp, UseMOnum);
756 Changed = changeStore(
UseMI, ImmOp, UseMOnum);
758 Changed = changeAddAsl(UseN,
UseMI, ImmOp, UseMOnum);
767 bool Changed =
false;
769 for (
auto IA : BA.
Addr->members(*DFG)) {
775 if ((
MI->getOpcode() != Hexagon::A2_tfrsi ||
776 !
MI->getOperand(1).isGlobal()) &&
777 (
MI->getOpcode() != Hexagon::A2_addi ||
778 !
MI->getOperand(2).isImm() || HII->isConstExtended(*
MI)))
782 <<
"]: " << *
MI <<
"\n\t[InstrNode]: "
786 getAllRealUses(SA, UNodeList);
788 if (!allValidCandidates(SA, UNodeList))
801 if (
MI->getOpcode() == Hexagon::A2_addi) {
802 Changed |= processAddUses(SA,
MI, UNodeList);
808 InstrEvalMap InstrEvalResult;
812 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
817 bool KeepTfr =
false;
819 LLVM_DEBUG(
dbgs() <<
"\t[Total reached uses] : " << UNodeList.size()
822 for (
auto I = UNodeList.rbegin(), E = UNodeList.rend();
I != E; ++
I) {
825 "Found a PhiRef node as a real reached use!!");
830 <<
">]: " << *
UseMI <<
"\n");
834 for (
unsigned j = 0;
j < NumOperands - 1; ++
j) {
836 if (
op.isReg() &&
op.isUse() && DefR ==
op.getReg())
845 bool Xformed =
false;
846 if (UseMOnum >= 0 && InstrEvalResult[
UseMI])
847 Xformed = xformUseMI(
MI,
UseMI, UseN, UseMOnum);
865 <<
": too many basic blocks\n");
869 bool Changed =
false;
872 HII = HST.getInstrInfo();
873 HRI = HST.getRegisterInfo();
874 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
875 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
893 Changed |= processBlock(BA);
896 MI->eraseFromParent();
913 return new HexagonOptAddrMode();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
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
cl::opt< unsigned > RDFFuncBlockLimit
#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...
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
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.
#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