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);
120 "Optimize addressing mode",
false,
false)
126 bool HexagonOptAddrMode::hasRepForm(
MachineInstr &
MI,
unsigned TfrDefR) {
140 return (HII->changeAddrMode_rr_ur(MI) >= 0);
143 return (HII->changeAddrMode_io_abs(MI) >= 0);
171 if (OffsetReg == RR.
Reg) {
173 OffsetRegRD = UA.Addr->getReachingDef();
177 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
183 if ((DFG->IsDef(AA) && AA.
Id != OffsetRegRD) ||
197 getBaseWithLongOffset(UseMI) < 0)
214 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
218 const auto &
P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
221 dbgs() <<
"*** Unable to collect all reaching defs for use ***\n" 223 <<
"The program's complexity may exceed the limits.\n";
227 const auto &ReachingDefs =
P.first;
228 if (ReachingDefs.size() > 1) {
230 dbgs() <<
"*** Multiple Reaching Defs found!!! ***\n";
231 for (
auto DI : ReachingDefs) {
234 dbgs() <<
"\t\t[Reaching Def]: " 249 RegisterRef DR = DFG->getPRI().normalize(DA.Addr->getRegRef(*DFG));
251 auto UseSet = LV->getAllReachedUses(DR, DA);
253 for (
auto UI : UseSet) {
257 dbgs() <<
"\t\t\t[Reached Use]: " 267 if (!phiUse.empty()) {
268 for (
auto I : phiUse) {
271 auto phiUseSet =
I.second;
272 for (
auto phiUI : phiUseSet) {
274 UNodeList.push_back(phiUA);
279 UNodeList.push_back(UA);
293 if (LRExtReg == RR.
Reg) {
295 LRExtRegRD = UA.Addr->getReachingDef();
299 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
307 if ((DFG->IsDef(AA) && AA.
Id != LRExtRegRD) ||
310 dbgs() <<
"isSafeToExtLR: Returning false; another reaching def\n");
325 unsigned AlignMask = 0;
326 switch (HII->getMemAccessSize(*MI)) {
343 if ((AlignMask & Offset) != 0)
353 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
371 if (!OffsetOp.
isImm())
375 if (!isValidOffset(MI, newOffset))
386 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
392 bool Changed =
false;
393 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
396 "Found a PhiRef node as a real reached use!!");
401 <<
">]: " << *UseMI <<
"\n");
402 Changed |= updateAddUses(AddMI, UseMI);
411 bool HexagonOptAddrMode::updateAddUses(
MachineInstr *AddMI,
415 unsigned newReg = AddRegOp.
getReg();
426 MRI->clearKillFlags(newReg);
431 bool HexagonOptAddrMode::analyzeUses(
unsigned tfrDefR,
433 InstrEvalMap &InstrEvalResult,
435 bool KeepTfr =
false;
436 bool HasRepInstr =
false;
437 InstrEvalResult.clear();
439 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
440 bool CanBeReplaced =
false;
446 if (!hasRepForm(MI, tfrDefR)) {
451 CanBeReplaced =
true;
452 }
else if (MI.
getOpcode() == Hexagon::S2_addasl_rrri) {
455 LLVM_DEBUG(
dbgs() <<
"\nGetting ReachedUses for === " << MI <<
"\n");
456 getAllRealUses(SN, AddaslUseList);
458 if (allValidCandidates(SN, AddaslUseList) &&
459 canRemoveAddasl(SN, MI, AddaslUseList)) {
460 SizeInc += AddaslUseList.size();
462 CanBeReplaced =
true;
472 InstrEvalResult[&
MI] = CanBeReplaced;
473 HasRepInstr |= CanBeReplaced;
485 bool Changed =
false;
496 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
497 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
507 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
508 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
522 }
else if (ImmOpNum == 2) {
524 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
525 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
538 for (
unsigned i = OpStart; i < OpEnd; ++i)
546 bool Changed =
false;
556 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
557 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
565 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
566 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
578 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
579 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
589 for (
unsigned i = OpStart; i < OpEnd; ++i)
595 short HexagonOptAddrMode::getBaseWithLongOffset(
const MachineInstr &MI)
const {
597 short TempOpCode = HII->changeAddrMode_io_rr(MI);
598 return HII->changeAddrMode_rr_ur(TempOpCode);
600 return HII->changeAddrMode_rr_ur(MI);
612 getAllRealUses(SA, UNodeList);
614 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
617 "Can't transform this 'AddAsl' instruction!");
624 <<
">]: " << *UseMI <<
"\n");
630 short NewOpCode = getBaseWithLongOffset(*UseMI);
631 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
659 for (
unsigned i = OpStart; i < OpEnd; ++i)
673 unsigned Changed =
false;
675 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
677 Changed = changeStore(UseMI, ImmOp, UseMOnum);
678 else if (UseMI->
getOpcode() == Hexagon::S2_addasl_rrri)
679 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
688 bool Changed =
false;
696 if ((MI->
getOpcode() != Hexagon::A2_tfrsi ||
703 <<
"]: " << *MI <<
"\n\t[InstrNode]: " 707 getAllRealUses(SA, UNodeList);
709 if (!allValidCandidates(SA, UNodeList))
722 if (MI->
getOpcode() == Hexagon::A2_addi) {
723 Changed |= processAddUses(SA, MI, UNodeList);
729 InstrEvalMap InstrEvalResult;
733 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
738 bool KeepTfr =
false;
740 LLVM_DEBUG(
dbgs() <<
"\t[Total reached uses] : " << UNodeList.size()
743 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
746 "Found a PhiRef node as a real reached use!!");
751 <<
">]: " << *UseMI <<
"\n");
755 for (
unsigned j = 0; j < NumOperands - 1; ++j) {
766 bool Xformed =
false;
767 if (UseMOnum >= 0 && InstrEvalResult[UseMI])
768 Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum);
782 bool Changed =
false;
785 HII = HST.getInstrInfo();
786 HRI = HST.getRegisterInfo();
787 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
788 MDT = &getAnalysis<MachineDominatorTree>();
807 Changed |= processBlock(BA);
827 return new HexagonOptAddrMode();
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
uint16_t getFlags() const
This class represents lattice values for constants.
Implements a dense probed hash-table based set.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
void setIsUndef(bool Val=true)
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool mayLoad() const
Return true if this instruction could possibly read memory.
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
amode Optimize addressing mode
INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode", false, false) INITIALIZE_PASS_END(HexagonOptAddrMode
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
unsigned getNumOperands() const
Retuns the total number of operands.
RegisterRef getRegRef(const DataFlowGraph &G) const
void setImplicit(bool Val=true)
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " "optimization"))
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
initializer< Ty > init(const Ty &Val)
MachineInstrBundleIterator< MachineInstr > iterator
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineInstrBuilder & UseMI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const GlobalValue * getGlobal() const
Represent the analysis usage information of a pass.
MachineInstr * getCode() const
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
NodeList members_if(Predicate P, const DataFlowGraph &G) const
NodeList members(const DataFlowGraph &G) const
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::map< RegisterId, NodeRefSet > RefMap
void setPreservesAll()
Set by analyses that do not transform their input at all.
bool mayStore() const
Return true if this instruction could possibly modify memory.
void initializeHexagonOptAddrModePass(PassRegistry &)
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
NodeId getReachingDef() const
NodeAddr< NodeBase * > getOwner(const DataFlowGraph &G)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int64_t getOffset() const
Return the offset from the symbol in this operand.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
void build(unsigned Options=BuildOptions::None)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionPass * createHexagonOptAddrMode()
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
const MachineOperand & getOperand(unsigned i) const
std::unordered_map< RegisterId, DefStack > DefStackMap
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...