13 #define DEBUG_TYPE "opt-addr-mode"
68 return "Optimize addressing mode of load/store";
87 std::map<RegisterRef, std::map<NodeId, NodeId>> RDefMap;
94 bool analyzeUses(
unsigned DefR,
const NodeList &UNodeList,
95 InstrEvalMap &InstrEvalResult,
short &SizeInc);
116 "Optimize addressing mode",
false,
false)
122 bool HexagonOptAddrMode::hasRepForm(
MachineInstr &
MI,
unsigned TfrDefR) {
136 return (HII->getBaseWithLongOffset(MI) >= 0);
139 return (HII->getAbsoluteForm(MI) >= 0);
167 if (OffsetReg == RR.
Reg) {
169 OffsetRegRD = UA.Addr->getReachingDef();
173 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
177 RDefMap[OffsetRR][IA.
Id] != OffsetRegRD)
190 getBaseWithLongOffset(UseMI) < 0)
207 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
211 const auto &ReachingDefs = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
212 if (ReachingDefs.size() > 1) {
214 dbgs() <<
"*** Multiple Reaching Defs found!!! ***\n";
215 for (
auto DI : ReachingDefs) {
218 dbgs() <<
"\t\t[Reaching Def]: "
233 RegisterRef DR = DFG->normalizeRef(DA.Addr->getRegRef(*DFG));
235 auto UseSet = LV->getAllReachedUses(DR, DA);
237 for (
auto UI : UseSet) {
241 dbgs() <<
"\t\t\t[Reached Use]: "
251 if (!phiUse.empty()) {
252 for (
auto I : phiUse) {
253 if (DR.
Reg !=
I.first)
255 auto phiUseSet =
I.second;
256 for (
auto phiUI : phiUseSet) {
258 UNodeList.push_back(phiUA);
263 UNodeList.push_back(UA);
268 bool HexagonOptAddrMode::analyzeUses(
unsigned tfrDefR,
270 InstrEvalMap &InstrEvalResult,
272 bool KeepTfr =
false;
273 bool HasRepInstr =
false;
274 InstrEvalResult.clear();
276 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
277 bool CanBeReplaced =
false;
283 if (!hasRepForm(MI, tfrDefR)) {
288 CanBeReplaced =
true;
289 }
else if (MI.
getOpcode() == Hexagon::S2_addasl_rrri) {
292 DEBUG(
dbgs() <<
"\nGetting ReachedUses for === " << MI <<
"\n");
293 getAllRealUses(SN, AddaslUseList);
295 if (allValidCandidates(SN, AddaslUseList) &&
296 canRemoveAddasl(SN, MI, AddaslUseList)) {
297 SizeInc += AddaslUseList.size();
299 CanBeReplaced =
true;
309 InstrEvalResult[&
MI] = CanBeReplaced;
310 HasRepInstr |= CanBeReplaced;
322 bool Changed =
false;
333 short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
334 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
343 short NewOpCode = HII->getAbsoluteForm(*OldMI);
344 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
356 DEBUG(
dbgs() <<
"[Changing]: " << *OldMI <<
"\n");
357 DEBUG(
dbgs() <<
"[TO]: " << MIB <<
"\n");
359 short NewOpCode = HII->xformRegToImmOffset(*OldMI);
360 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
367 DEBUG(
dbgs() <<
"[Changing]: " << *OldMI <<
"\n");
368 DEBUG(
dbgs() <<
"[TO]: " << MIB <<
"\n");
372 for (
unsigned i = OpStart;
i < OpEnd; ++
i)
380 bool Changed =
false;
390 short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
391 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
399 short NewOpCode = HII->getAbsoluteForm(*OldMI);
400 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
409 DEBUG(
dbgs() <<
"[Changing]: " << *OldMI <<
"\n");
410 DEBUG(
dbgs() <<
"[TO]: " << MIB <<
"\n");
412 short NewOpCode = HII->xformRegToImmOffset(*OldMI);
413 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
420 DEBUG(
dbgs() <<
"[Changing]: " << *OldMI <<
"\n");
421 DEBUG(
dbgs() <<
"[TO]: " << MIB <<
"\n");
424 for (
unsigned i = OpStart;
i < OpEnd; ++
i)
430 short HexagonOptAddrMode::getBaseWithLongOffset(
const MachineInstr &MI)
const {
432 short TempOpCode = HII->getBaseWithRegOffset(MI);
433 return HII->getBaseWithLongOffset(TempOpCode);
435 return HII->getBaseWithLongOffset(MI);
444 DEBUG(
dbgs() <<
"Processing addasl :" << *AddAslMI <<
"\n");
447 getAllRealUses(SA, UNodeList);
449 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
452 "Can't transform this 'AddAsl' instruction!");
459 <<
">]: " << *UseMI <<
"\n");
465 short NewOpCode = getBaseWithLongOffset(*UseMI);
466 assert(NewOpCode >= 0 &&
"Invalid New opcode\n");
475 if (UseMID.mayLoad()) {
483 }
else if (UseMID.mayStore()) {
494 for (
unsigned i = OpStart;
i < OpEnd; ++
i)
497 Deleted.insert(UseMI);
508 unsigned Changed =
false;
510 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
512 Changed = changeStore(UseMI, ImmOp, UseMOnum);
513 else if (UseMI->
getOpcode() == Hexagon::S2_addasl_rrri)
514 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
517 Deleted.insert(UseMI);
523 bool Changed =
false;
531 if (MI->
getOpcode() != Hexagon::A2_tfrsi ||
535 DEBUG(
dbgs() <<
"[Analyzing A2_tfrsi]: " << *MI <<
"\n");
540 getAllRealUses(SA, UNodeList);
542 if (!allValidCandidates(SA, UNodeList))
547 InstrEvalMap InstrEvalResult;
551 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
556 bool KeepTfr =
false;
558 DEBUG(
dbgs() <<
"\t[Total reached uses] : " << UNodeList.size() <<
"\n");
559 DEBUG(
dbgs() <<
"\t[Processing Reached Uses] ===\n");
560 for (
auto I = UNodeList.rbegin(),
E = UNodeList.rend();
I !=
E; ++
I) {
563 "Found a PhiRef node as a real reached use!!");
568 <<
">]: " << *UseMI <<
"\n");
572 for (
unsigned j = 0; j < NumOperands - 1; ++j) {
577 assert(UseMOnum >= 0 &&
"Invalid reached use!");
579 if (InstrEvalResult[UseMI])
581 Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
594 RRs.insert(RA.Addr->getRegRef(*DFG));
596 for (
auto &R : RDefMap) {
597 if (!RRs.count(R.first))
605 for (
auto &R : RDefMap) {
606 auto F = DefM.find(R.first.Reg);
607 if (
F == DefM.end() ||
F->second.empty())
609 R.second[IA.
Id] =
F->second.top()->Id;
614 bool Changed =
false;
615 auto BA = DFG->getFunc().
Addr->findBlock(B, *DFG);
616 DFG->markBlock(BA.
Id, DefM);
620 DFG->pushDefs(IA, DefM);
625 Changed |= constructDefMap(
I->getBlock());
627 DFG->releaseBlock(BA.
Id, DefM);
632 bool Changed =
false;
635 HII = HST.getInstrInfo();
636 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
637 MDT = &getAnalysis<MachineDominatorTree>();
649 constructDefMap(&DFG->getMF().front());
653 DEBUG(
dbgs() <<
"==== [RefMap#]=====:\n "
657 Changed |= processBlock(BA);
659 for (
auto MI : Deleted)
677 return new HexagonOptAddrMode();
NodeList members(const DataFlowGraph &G) const
const GlobalValue * getGlobal() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
uint16_t getFlags() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Implements a dense probed hash-table based set.
bool mayStore() const
Return true if this instruction could possibly modify memory.
Describe properties that are true of each instruction in the target description file.
opt Optimize addressing mode
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
MachineInstrBundleIterator< MachineInstr > iterator
iterator_range< mop_iterator > operands()
opt Optimize addressing false
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
std::vector< NodeAddr< NodeBase * > > NodeList
unsigned getNumOperands() const
Access to explicit operands of the instruction.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
std::map< RegisterId, NodeRefSet > RefMap
Base class for the actual dominator tree node.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
NodeList members_if(Predicate P, const DataFlowGraph &G) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
unsigned getTargetFlags() const
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineInstrBuilder & UseMI
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
Return the offset from the symbol in this operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
MachineOperand class - Representation of each machine instruction operand.
bool mayLoad() const
Return true if this instruction could possibly read memory.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::unordered_map< RegisterId, DefStack > DefStackMap
std::set< NodeId > NodeSet
RegisterRef getRegRef(const DataFlowGraph &G) const
void setPreservesAll()
Set by analyses that do not transform their input at all.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void initializeHexagonOptAddrModePass(PassRegistry &)
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Representation of each machine instruction.
NodeAddr< NodeBase * > getOwner(const DataFlowGraph &G)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
void build(unsigned Options=BuildOptions::None)
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineInstr * getCode() const
INITIALIZE_PASS_BEGIN(HexagonOptAddrMode,"opt-amode","Optimize addressing mode", false, false) INITIALIZE_PASS_END(HexagonOptAddrMode
FunctionPass * createHexagonOptAddrMode()
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
std::set< RegisterRef > RegisterSet
static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode ""optimization"))
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...