[ARM64,C++11] Clean up the ARM64 LOH collection pass.

Range'ify a bunch of loops, mainly. As a result, we have a variety
of objects via reference rather than by pointer, so propogate that
through the various helper functions where it makes sense.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206337 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach
2014-04-15 22:57:02 +00:00
parent d66d570796
commit 09256c5bb5

View File

@@ -173,7 +173,7 @@ struct ARM64CollectLOH : public MachineFunctionPass {
initializeARM64CollectLOHPass(*PassRegistry::getPassRegistry()); initializeARM64CollectLOHPass(*PassRegistry::getPassRegistry());
} }
virtual bool runOnMachineFunction(MachineFunction &Fn); virtual bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const { virtual const char *getPassName() const {
return "ARM64 Collect Linker Optimization Hint (LOH)"; return "ARM64 Collect Linker Optimization Hint (LOH)";
@@ -230,15 +230,14 @@ INITIALIZE_PASS_END(ARM64CollectLOH, "arm64-collect-loh",
/// \param nbRegs is used internally allocate some memory. It must be consistent /// \param nbRegs is used internally allocate some memory. It must be consistent
/// with the way sets is used. /// with the way sets is used.
static SetOfMachineInstr &getSet(BlockToSetOfInstrsPerColor &sets, static SetOfMachineInstr &getSet(BlockToSetOfInstrsPerColor &sets,
const MachineBasicBlock *MBB, unsigned reg, const MachineBasicBlock &MBB, unsigned reg,
unsigned nbRegs) { unsigned nbRegs) {
SetOfMachineInstr *result; SetOfMachineInstr *result;
BlockToSetOfInstrsPerColor::iterator it = sets.find(MBB); BlockToSetOfInstrsPerColor::iterator it = sets.find(&MBB);
if (it != sets.end()) { if (it != sets.end())
result = it->second; result = it->second;
} else { else
result = sets[MBB] = new SetOfMachineInstr[nbRegs]; result = sets[&MBB] = new SetOfMachineInstr[nbRegs];
}
return result[reg]; return result[reg];
} }
@@ -251,15 +250,15 @@ static SetOfMachineInstr &getSet(BlockToSetOfInstrsPerColor &sets,
/// "sets[reg]". /// "sets[reg]".
/// \pre set[reg] is valid. /// \pre set[reg] is valid.
static SetOfMachineInstr &getUses(InstrToInstrs *sets, unsigned reg, static SetOfMachineInstr &getUses(InstrToInstrs *sets, unsigned reg,
const MachineInstr *MI) { const MachineInstr &MI) {
return sets[reg][MI]; return sets[reg][&MI];
} }
/// Same as getUses but does not modify the input map: sets. /// Same as getUses but does not modify the input map: sets.
/// \return NULL if the couple (reg, MI) is not in sets. /// \return NULL if the couple (reg, MI) is not in sets.
static const SetOfMachineInstr *getUses(const InstrToInstrs *sets, unsigned reg, static const SetOfMachineInstr *getUses(const InstrToInstrs *sets, unsigned reg,
const MachineInstr *MI) { const MachineInstr &MI) {
InstrToInstrs::const_iterator Res = sets[reg].find(MI); InstrToInstrs::const_iterator Res = sets[reg].find(&MI);
if (Res != sets[reg].end()) if (Res != sets[reg].end())
return &(Res->second); return &(Res->second);
return NULL; return NULL;
@@ -276,41 +275,36 @@ static const SetOfMachineInstr *getUses(const InstrToInstrs *sets, unsigned reg,
/// definition. It also consider definitions of ADRP instructions as uses and /// definition. It also consider definitions of ADRP instructions as uses and
/// ignore other uses. The ADRPMode is used to collect the information for LHO /// ignore other uses. The ADRPMode is used to collect the information for LHO
/// that involve ADRP operation only. /// that involve ADRP operation only.
static void initReachingDef(MachineFunction *MF, static void initReachingDef(MachineFunction &MF,
InstrToInstrs *ColorOpToReachedUses, InstrToInstrs *ColorOpToReachedUses,
BlockToInstrPerColor &Gen, BlockToRegSet &Kill, BlockToInstrPerColor &Gen, BlockToRegSet &Kill,
BlockToSetOfInstrsPerColor &ReachableUses, BlockToSetOfInstrsPerColor &ReachableUses,
const MapRegToId &RegToId, const MapRegToId &RegToId,
const MachineInstr *DummyOp, bool ADRPMode) { const MachineInstr *DummyOp, bool ADRPMode) {
const TargetMachine &TM = MF->getTarget(); const TargetMachine &TM = MF.getTarget();
const TargetRegisterInfo *TRI = TM.getRegisterInfo(); const TargetRegisterInfo *TRI = TM.getRegisterInfo();
unsigned NbReg = RegToId.size(); unsigned NbReg = RegToId.size();
for (MachineFunction::const_iterator IMBB = MF->begin(), IMBBEnd = MF->end(); for (MachineBasicBlock &MBB : MF) {
IMBB != IMBBEnd; ++IMBB) { const MachineInstr **&BBGen = Gen[&MBB];
const MachineBasicBlock *MBB = &(*IMBB);
const MachineInstr **&BBGen = Gen[MBB];
BBGen = new const MachineInstr *[NbReg]; BBGen = new const MachineInstr *[NbReg];
memset(BBGen, 0, sizeof(const MachineInstr *) * NbReg); memset(BBGen, 0, sizeof(const MachineInstr *) * NbReg);
BitVector &BBKillSet = Kill[MBB]; BitVector &BBKillSet = Kill[&MBB];
BBKillSet.resize(NbReg); BBKillSet.resize(NbReg);
for (MachineBasicBlock::const_iterator II = MBB->begin(), IEnd = MBB->end(); for (const MachineInstr &MI : MBB) {
II != IEnd; ++II) { bool IsADRP = MI.getOpcode() == ARM64::ADRP;
bool IsADRP = II->getOpcode() == ARM64::ADRP;
// Process uses first. // Process uses first.
if (IsADRP || !ADRPMode) if (IsADRP || !ADRPMode)
for (MachineInstr::const_mop_iterator IO = II->operands_begin(), for (const MachineOperand &MO : MI.operands()) {
IOEnd = II->operands_end();
IO != IOEnd; ++IO) {
// Treat ADRP def as use, as the goal of the analysis is to find // Treat ADRP def as use, as the goal of the analysis is to find
// ADRP defs reached by other ADRP defs. // ADRP defs reached by other ADRP defs.
if (!IO->isReg() || (!ADRPMode && !IO->isUse()) || if (!MO.isReg() || (!ADRPMode && !MO.isUse()) ||
(ADRPMode && (!IsADRP || !IO->isDef()))) (ADRPMode && (!IsADRP || !MO.isDef())))
continue; continue;
unsigned CurReg = IO->getReg(); unsigned CurReg = MO.getReg();
MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg); MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg);
if (ItCurRegId == RegToId.end()) if (ItCurRegId == RegToId.end())
continue; continue;
@@ -318,20 +312,18 @@ static void initReachingDef(MachineFunction *MF,
// if CurReg has not been defined, this use is reachable. // if CurReg has not been defined, this use is reachable.
if (!BBGen[CurReg] && !BBKillSet.test(CurReg)) if (!BBGen[CurReg] && !BBKillSet.test(CurReg))
getSet(ReachableUses, MBB, CurReg, NbReg).insert(&(*II)); getSet(ReachableUses, MBB, CurReg, NbReg).insert(&MI);
// current basic block definition for this color, if any, is in Gen. // current basic block definition for this color, if any, is in Gen.
if (BBGen[CurReg]) if (BBGen[CurReg])
getUses(ColorOpToReachedUses, CurReg, BBGen[CurReg]).insert(&(*II)); getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(&MI);
} }
// Process clobbers. // Process clobbers.
for (MachineInstr::const_mop_iterator IO = II->operands_begin(), for (const MachineOperand &MO : MI.operands()) {
IOEnd = II->operands_end(); if (!MO.isRegMask())
IO != IOEnd; ++IO) {
if (!IO->isRegMask())
continue; continue;
// Clobbers kill the related colors. // Clobbers kill the related colors.
const uint32_t *PreservedRegs = IO->getRegMask(); const uint32_t *PreservedRegs = MO.getRegMask();
// Set generated regs. // Set generated regs.
for (const auto Entry : RegToId) { for (const auto Entry : RegToId) {
@@ -342,19 +334,17 @@ static void initReachingDef(MachineFunction *MF,
// Do not register clobbered definition for no ADRP. // Do not register clobbered definition for no ADRP.
// This definition is not used anyway (otherwise register // This definition is not used anyway (otherwise register
// allocation is wrong). // allocation is wrong).
BBGen[Reg] = ADRPMode ? II : NULL; BBGen[Reg] = ADRPMode ? &MI : NULL;
BBKillSet.set(Reg); BBKillSet.set(Reg);
} }
} }
} }
// Process defs // Process register defs.
for (MachineInstr::const_mop_iterator IO = II->operands_begin(), for (const MachineOperand &MO : MI.operands()) {
IOEnd = II->operands_end(); if (!MO.isReg() || !MO.isDef())
IO != IOEnd; ++IO) {
if (!IO->isReg() || !IO->isDef())
continue; continue;
unsigned CurReg = IO->getReg(); unsigned CurReg = MO.getReg();
MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg); MapRegToId::const_iterator ItCurRegId = RegToId.find(CurReg);
if (ItCurRegId == RegToId.end()) if (ItCurRegId == RegToId.end())
continue; continue;
@@ -365,19 +355,19 @@ static void initReachingDef(MachineFunction *MF,
"Sub-register of an " "Sub-register of an "
"involved register, not recorded as involved!"); "involved register, not recorded as involved!");
BBKillSet.set(ItRegId->second); BBKillSet.set(ItRegId->second);
BBGen[ItRegId->second] = &(*II); BBGen[ItRegId->second] = &MI;
} }
BBGen[ItCurRegId->second] = &(*II); BBGen[ItCurRegId->second] = &MI;
} }
} }
// If we restrict our analysis to basic block scope, conservatively add a // If we restrict our analysis to basic block scope, conservatively add a
// dummy // dummy
// use for each generated value. // use for each generated value.
if (!ADRPMode && DummyOp && !MBB->succ_empty()) if (!ADRPMode && DummyOp && !MBB.succ_empty())
for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg) for (unsigned CurReg = 0; CurReg < NbReg; ++CurReg)
if (BBGen[CurReg]) if (BBGen[CurReg])
getUses(ColorOpToReachedUses, CurReg, BBGen[CurReg]).insert(DummyOp); getUses(ColorOpToReachedUses, CurReg, *BBGen[CurReg]).insert(DummyOp);
} }
} }
@@ -390,7 +380,7 @@ static void initReachingDef(MachineFunction *MF,
/// op.reachedUses /// op.reachedUses
/// ///
/// Out[bb] = Gen[bb] U (In[bb] - Kill[bb]) /// Out[bb] = Gen[bb] U (In[bb] - Kill[bb])
static void reachingDefAlgorithm(MachineFunction *MF, static void reachingDefAlgorithm(MachineFunction &MF,
InstrToInstrs *ColorOpToReachedUses, InstrToInstrs *ColorOpToReachedUses,
BlockToSetOfInstrsPerColor &In, BlockToSetOfInstrsPerColor &In,
BlockToSetOfInstrsPerColor &Out, BlockToSetOfInstrsPerColor &Out,
@@ -400,10 +390,7 @@ static void reachingDefAlgorithm(MachineFunction *MF,
bool HasChanged; bool HasChanged;
do { do {
HasChanged = false; HasChanged = false;
for (MachineFunction::const_iterator IMBB = MF->begin(), for (MachineBasicBlock &MBB : MF) {
IMBBEnd = MF->end();
IMBB != IMBBEnd; ++IMBB) {
const MachineBasicBlock *MBB = &(*IMBB);
unsigned CurReg; unsigned CurReg;
for (CurReg = 0; CurReg < NbReg; ++CurReg) { for (CurReg = 0; CurReg < NbReg; ++CurReg) {
SetOfMachineInstr &BBInSet = getSet(In, MBB, CurReg, NbReg); SetOfMachineInstr &BBInSet = getSet(In, MBB, CurReg, NbReg);
@@ -412,24 +399,21 @@ static void reachingDefAlgorithm(MachineFunction *MF,
SetOfMachineInstr &BBOutSet = getSet(Out, MBB, CurReg, NbReg); SetOfMachineInstr &BBOutSet = getSet(Out, MBB, CurReg, NbReg);
unsigned Size = BBOutSet.size(); unsigned Size = BBOutSet.size();
// In[bb][color] = U Out[bb.predecessors][color] // In[bb][color] = U Out[bb.predecessors][color]
for (MachineBasicBlock::const_pred_iterator for (MachineBasicBlock *PredMBB : MBB.predecessors()) {
PredMBB = MBB->pred_begin(),
EndPredMBB = MBB->pred_end();
PredMBB != EndPredMBB; ++PredMBB) {
SetOfMachineInstr &PredOutSet = getSet(Out, *PredMBB, CurReg, NbReg); SetOfMachineInstr &PredOutSet = getSet(Out, *PredMBB, CurReg, NbReg);
BBInSet.insert(PredOutSet.begin(), PredOutSet.end()); BBInSet.insert(PredOutSet.begin(), PredOutSet.end());
} }
// insert reachableUses[bb][color] in each in[bb][color] op.reachedses // insert reachableUses[bb][color] in each in[bb][color] op.reachedses
for (const MachineInstr *MI: BBInSet) { for (const MachineInstr *MI : BBInSet) {
SetOfMachineInstr &OpReachedUses = SetOfMachineInstr &OpReachedUses =
getUses(ColorOpToReachedUses, CurReg, MI); getUses(ColorOpToReachedUses, CurReg, *MI);
OpReachedUses.insert(BBReachableUses.begin(), BBReachableUses.end()); OpReachedUses.insert(BBReachableUses.begin(), BBReachableUses.end());
} }
// Out[bb] = Gen[bb] U (In[bb] - Kill[bb]) // Out[bb] = Gen[bb] U (In[bb] - Kill[bb])
if (!Kill[MBB].test(CurReg)) if (!Kill[&MBB].test(CurReg))
BBOutSet.insert(BBInSet.begin(), BBInSet.end()); BBOutSet.insert(BBInSet.begin(), BBInSet.end());
if (Gen[MBB][CurReg]) if (Gen[&MBB][CurReg])
BBOutSet.insert(Gen[MBB][CurReg]); BBOutSet.insert(Gen[&MBB][CurReg]);
HasChanged |= BBOutSet.size() != Size; HasChanged |= BBOutSet.size() != Size;
} }
} }
@@ -442,21 +426,14 @@ static void finitReachingDef(BlockToSetOfInstrsPerColor &In,
BlockToSetOfInstrsPerColor &Out, BlockToSetOfInstrsPerColor &Out,
BlockToInstrPerColor &Gen, BlockToInstrPerColor &Gen,
BlockToSetOfInstrsPerColor &ReachableUses) { BlockToSetOfInstrsPerColor &ReachableUses) {
for (BlockToSetOfInstrsPerColor::const_iterator IT = Out.begin(), for (auto &IT : Out)
End = Out.end(); delete[] IT.second;
IT != End; ++IT) for (auto &IT : In)
delete[] IT->second; delete[] IT.second;
for (BlockToSetOfInstrsPerColor::const_iterator IT = In.begin(), for (auto &IT : ReachableUses)
End = In.end(); delete[] IT.second;
IT != End; ++IT) for (auto &IT : Gen)
delete[] IT->second; delete[] IT.second;
for (BlockToSetOfInstrsPerColor::const_iterator IT = ReachableUses.begin(),
End = ReachableUses.end();
IT != End; ++IT)
delete[] IT->second;
for (BlockToInstrPerColor::const_iterator IT = Gen.begin(), End = Gen.end();
IT != End; ++IT)
delete[] IT->second;
} }
/// Reaching definition algorithm. /// Reaching definition algorithm.
@@ -470,7 +447,7 @@ static void finitReachingDef(BlockToSetOfInstrsPerColor &In,
/// @p DummyOp. /// @p DummyOp.
/// \pre ColorOpToReachedUses is an array of at least number of registers of /// \pre ColorOpToReachedUses is an array of at least number of registers of
/// InstrToInstrs. /// InstrToInstrs.
static void reachingDef(MachineFunction *MF, static void reachingDef(MachineFunction &MF,
InstrToInstrs *ColorOpToReachedUses, InstrToInstrs *ColorOpToReachedUses,
const MapRegToId &RegToId, bool ADRPMode = false, const MapRegToId &RegToId, bool ADRPMode = false,
const MachineInstr *DummyOp = NULL) { const MachineInstr *DummyOp = NULL) {
@@ -511,18 +488,12 @@ static void printReachingDef(const InstrToInstrs *ColorOpToReachedUses,
continue; continue;
DEBUG(dbgs() << "*** Reg " << PrintReg(IdToReg[CurReg], TRI) << " ***\n"); DEBUG(dbgs() << "*** Reg " << PrintReg(IdToReg[CurReg], TRI) << " ***\n");
InstrToInstrs::const_iterator DefsIt = ColorOpToReachedUses[CurReg].begin(); for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) {
InstrToInstrs::const_iterator DefsItEnd =
ColorOpToReachedUses[CurReg].end();
for (; DefsIt != DefsItEnd; ++DefsIt) {
DEBUG(dbgs() << "Def:\n"); DEBUG(dbgs() << "Def:\n");
DEBUG(DefsIt->first->print(dbgs())); DEBUG(DefsIt.first->print(dbgs()));
DEBUG(dbgs() << "Reachable uses:\n"); DEBUG(dbgs() << "Reachable uses:\n");
for (SetOfMachineInstr::const_iterator UsesIt = DefsIt->second.begin(), for (const MachineInstr *MI : DefsIt.second)
UsesItEnd = DefsIt->second.end(); DEBUG(MI->print(dbgs()));
UsesIt != UsesItEnd; ++UsesIt) {
DEBUG((*UsesIt)->print(dbgs()));
}
} }
} }
} }
@@ -603,34 +574,29 @@ static void reachedUsesToDefs(InstrToInstrs &UseToReachingDefs,
if (ColorOpToReachedUses[CurReg].empty()) if (ColorOpToReachedUses[CurReg].empty())
continue; continue;
InstrToInstrs::const_iterator DefsIt = ColorOpToReachedUses[CurReg].begin(); for (const auto &DefsIt : ColorOpToReachedUses[CurReg]) {
InstrToInstrs::const_iterator DefsItEnd = for (const MachineInstr *MI : DefsIt.second) {
ColorOpToReachedUses[CurReg].end(); const MachineInstr *Def = DefsIt.first;
for (; DefsIt != DefsItEnd; ++DefsIt) {
for (SetOfMachineInstr::const_iterator UsesIt = DefsIt->second.begin(),
UsesItEnd = DefsIt->second.end();
UsesIt != UsesItEnd; ++UsesIt) {
const MachineInstr *Def = DefsIt->first;
MapRegToId::const_iterator It; MapRegToId::const_iterator It;
// if all the reaching defs are not adrp, this use will not be // if all the reaching defs are not adrp, this use will not be
// simplifiable. // simplifiable.
if ((ADRPMode && Def->getOpcode() != ARM64::ADRP) || if ((ADRPMode && Def->getOpcode() != ARM64::ADRP) ||
(!ADRPMode && !canDefBePartOfLOH(Def)) || (!ADRPMode && !canDefBePartOfLOH(Def)) ||
(!ADRPMode && isCandidateStore(*UsesIt) && (!ADRPMode && isCandidateStore(MI) &&
// store are LOH candidate iff the end of the chain is used as // store are LOH candidate iff the end of the chain is used as
// base. // base.
((It = RegToId.find((*UsesIt)->getOperand(1).getReg())) == EndIt || ((It = RegToId.find((MI)->getOperand(1).getReg())) == EndIt ||
It->second != CurReg))) { It->second != CurReg))) {
NotCandidate.insert(*UsesIt); NotCandidate.insert(MI);
continue; continue;
} }
// Do not consider self reaching as a simplifiable case for ADRP. // Do not consider self reaching as a simplifiable case for ADRP.
if (!ADRPMode || *UsesIt != DefsIt->first) { if (!ADRPMode || MI != DefsIt.first) {
UseToReachingDefs[*UsesIt].insert(DefsIt->first); UseToReachingDefs[MI].insert(DefsIt.first);
// If UsesIt has several reaching definitions, it is not // If UsesIt has several reaching definitions, it is not
// candidate for simplificaton in non-ADRPMode. // candidate for simplificaton in non-ADRPMode.
if (!ADRPMode && UseToReachingDefs[*UsesIt].size() > 1) if (!ADRPMode && UseToReachingDefs[MI].size() > 1)
NotCandidate.insert(*UsesIt); NotCandidate.insert(MI);
} }
} }
} }
@@ -747,8 +713,9 @@ static bool isCandidate(const MachineInstr *Instr,
if (!MDT->dominates(Def, Instr)) if (!MDT->dominates(Def, Instr))
return false; return false;
// Move one node up in the simple chain. // Move one node up in the simple chain.
if (UseToDefs.find(Def) == UseToDefs.end() if (UseToDefs.find(Def) ==
// The map may contain garbage we have to ignore. UseToDefs.end()
// The map may contain garbage we have to ignore.
|| ||
UseToDefs.find(Def)->second.empty()) UseToDefs.find(Def)->second.empty())
return false; return false;
@@ -764,7 +731,7 @@ static bool isCandidate(const MachineInstr *Instr,
return false; return false;
} }
static bool registerADRCandidate(const MachineInstr *Use, static bool registerADRCandidate(const MachineInstr &Use,
const InstrToInstrs &UseToDefs, const InstrToInstrs &UseToDefs,
const InstrToInstrs *DefsPerColorToUses, const InstrToInstrs *DefsPerColorToUses,
ARM64FunctionInfo &ARM64FI, ARM64FunctionInfo &ARM64FI,
@@ -773,38 +740,38 @@ static bool registerADRCandidate(const MachineInstr *Use,
// Look for opportunities to turn ADRP -> ADD or // Look for opportunities to turn ADRP -> ADD or
// ADRP -> LDR GOTPAGEOFF into ADR. // ADRP -> LDR GOTPAGEOFF into ADR.
// If ADRP has more than one use. Give up. // If ADRP has more than one use. Give up.
if (Use->getOpcode() != ARM64::ADDXri && if (Use.getOpcode() != ARM64::ADDXri &&
(Use->getOpcode() != ARM64::LDRXui || (Use.getOpcode() != ARM64::LDRXui ||
!(Use->getOperand(2).getTargetFlags() & ARM64II::MO_GOT))) !(Use.getOperand(2).getTargetFlags() & ARM64II::MO_GOT)))
return false; return false;
InstrToInstrs::const_iterator It = UseToDefs.find(Use); InstrToInstrs::const_iterator It = UseToDefs.find(&Use);
// The map may contain garbage that we need to ignore. // The map may contain garbage that we need to ignore.
if (It == UseToDefs.end() || It->second.empty()) if (It == UseToDefs.end() || It->second.empty())
return false; return false;
const MachineInstr *Def = *It->second.begin(); const MachineInstr &Def = **It->second.begin();
if (Def->getOpcode() != ARM64::ADRP) if (Def.getOpcode() != ARM64::ADRP)
return false; return false;
// Check the number of users of ADRP. // Check the number of users of ADRP.
const SetOfMachineInstr *Users = const SetOfMachineInstr *Users =
getUses(DefsPerColorToUses, getUses(DefsPerColorToUses,
RegToId.find(Def->getOperand(0).getReg())->second, Def); RegToId.find(Def.getOperand(0).getReg())->second, Def);
if (Users->size() > 1) { if (Users->size() > 1) {
++NumADRComplexCandidate; ++NumADRComplexCandidate;
return false; return false;
} }
++NumADRSimpleCandidate; ++NumADRSimpleCandidate;
assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Def)) && assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Def)) &&
"ADRP already involved in LOH."); "ADRP already involved in LOH.");
assert((!InvolvedInLOHs || InvolvedInLOHs->insert(Use)) && assert((!InvolvedInLOHs || InvolvedInLOHs->insert(&Use)) &&
"ADD already involved in LOH."); "ADD already involved in LOH.");
DEBUG(dbgs() << "Record AdrpAdd\n" << *Def << '\n' << *Use << '\n'); DEBUG(dbgs() << "Record AdrpAdd\n" << Def << '\n' << Use << '\n');
SmallVector<const MachineInstr *, 2> Args; SmallVector<const MachineInstr *, 2> Args;
Args.push_back(Def); Args.push_back(&Def);
Args.push_back(Use); Args.push_back(&Use);
ARM64FI.addLOHDirective(Use->getOpcode() == ARM64::ADDXri ? MCLOH_AdrpAdd ARM64FI.addLOHDirective(Use.getOpcode() == ARM64::ADDXri ? MCLOH_AdrpAdd
: MCLOH_AdrpLdrGot, : MCLOH_AdrpLdrGot,
Args); Args);
return true; return true;
} }
@@ -831,20 +798,18 @@ static void computeOthers(const InstrToInstrs &UseToDefs,
// to be changed. // to be changed.
SetOfMachineInstr PotentialCandidates; SetOfMachineInstr PotentialCandidates;
SetOfMachineInstr PotentialADROpportunities; SetOfMachineInstr PotentialADROpportunities;
for (InstrToInstrs::const_iterator UseIt = UseToDefs.begin(), for (auto &Use : UseToDefs) {
EndUseIt = UseToDefs.end();
UseIt != EndUseIt; ++UseIt) {
// If no definition is available, this is a non candidate. // If no definition is available, this is a non candidate.
if (UseIt->second.empty()) if (Use.second.empty())
continue; continue;
// Keep only instructions that are load or store and at the end of // Keep only instructions that are load or store and at the end of
// a ADRP -> ADD/LDR/Nothing chain. // a ADRP -> ADD/LDR/Nothing chain.
// We already filtered out the no-chain cases. // We already filtered out the no-chain cases.
if (!isCandidate(UseIt->first, UseToDefs, MDT)) { if (!isCandidate(Use.first, UseToDefs, MDT)) {
PotentialADROpportunities.insert(UseIt->first); PotentialADROpportunities.insert(Use.first);
continue; continue;
} }
PotentialCandidates.insert(UseIt->first); PotentialCandidates.insert(Use.first);
} }
// Make the following distinctions for statistics as the linker does // Make the following distinctions for statistics as the linker does
@@ -866,10 +831,7 @@ static void computeOthers(const InstrToInstrs &UseToDefs,
#ifdef DEBUG #ifdef DEBUG
SetOfMachineInstr DefsOfPotentialCandidates; SetOfMachineInstr DefsOfPotentialCandidates;
#endif #endif
for (CandidateIt = PotentialCandidates.begin(), for (const MachineInstr *Candidate : PotentialCandidates) {
EndCandidateIt = PotentialCandidates.end();
CandidateIt != EndCandidateIt; ++CandidateIt) {
const MachineInstr *Candidate = *CandidateIt;
// Get the definition of the candidate i.e., ADD or LDR. // Get the definition of the candidate i.e., ADD or LDR.
const MachineInstr *Def = *UseToDefs.find(Candidate)->second.begin(); const MachineInstr *Def = *UseToDefs.find(Candidate)->second.begin();
// Record the elements of the chain. // Record the elements of the chain.
@@ -880,20 +842,20 @@ static void computeOthers(const InstrToInstrs &UseToDefs,
// Check the number of users of this node. // Check the number of users of this node.
const SetOfMachineInstr *Users = const SetOfMachineInstr *Users =
getUses(DefsPerColorToUses, getUses(DefsPerColorToUses,
RegToId.find(Def->getOperand(0).getReg())->second, Def); RegToId.find(Def->getOperand(0).getReg())->second, *Def);
if (Users->size() > 1) { if (Users->size() > 1) {
#ifdef DEBUG #ifdef DEBUG
// if all the uses of this def are in potential candidate, this is // if all the uses of this def are in potential candidate, this is
// a complex candidate of level 2. // a complex candidate of level 2.
SetOfMachineInstr::const_iterator UseIt = Users->begin(); bool IsLevel2 = true;
SetOfMachineInstr::const_iterator EndUseIt = Users->end(); for (const MachineInstr *MI : *Users) {
for (; UseIt != EndUseIt; ++UseIt) { if (!PotentialCandidates.count(MI)) {
if (!PotentialCandidates.count(*UseIt)) {
++NumTooCplxLvl2; ++NumTooCplxLvl2;
IsLevel2 = false;
break; break;
} }
} }
if (UseIt == EndUseIt) if (IsLevel2)
++NumCplxLvl2; ++NumCplxLvl2;
#endif // DEBUG #endif // DEBUG
PotentialADROpportunities.insert(Def); PotentialADROpportunities.insert(Def);
@@ -908,7 +870,7 @@ static void computeOthers(const InstrToInstrs &UseToDefs,
// Check the number of users of the first node in the chain, i.e., ADRP // Check the number of users of the first node in the chain, i.e., ADRP
const SetOfMachineInstr *Users = const SetOfMachineInstr *Users =
getUses(DefsPerColorToUses, getUses(DefsPerColorToUses,
RegToId.find(Def->getOperand(0).getReg())->second, Def); RegToId.find(Def->getOperand(0).getReg())->second, *Def);
if (Users->size() > 1) { if (Users->size() > 1) {
#ifdef DEBUG #ifdef DEBUG
// if all the uses of this def are in the defs of the potential candidate, // if all the uses of this def are in the defs of the potential candidate,
@@ -1030,8 +992,8 @@ static void computeOthers(const InstrToInstrs &UseToDefs,
} }
// Now, we grabbed all the big patterns, check ADR opportunities. // Now, we grabbed all the big patterns, check ADR opportunities.
for (const MachineInstr *Candidate: PotentialADROpportunities) for (const MachineInstr *Candidate : PotentialADROpportunities)
registerADRCandidate(Candidate, UseToDefs, DefsPerColorToUses, ARM64FI, registerADRCandidate(*Candidate, UseToDefs, DefsPerColorToUses, ARM64FI,
InvolvedInLOHs, RegToId); InvolvedInLOHs, RegToId);
} }
@@ -1053,18 +1015,14 @@ static void collectInvolvedReg(MachineFunction &MF, MapRegToId &RegToId,
} }
DEBUG(dbgs() << "** Collect Involved Register\n"); DEBUG(dbgs() << "** Collect Involved Register\n");
for (MachineFunction::const_iterator IMBB = MF.begin(), IMBBEnd = MF.end(); for (const auto &MBB : MF) {
IMBB != IMBBEnd; ++IMBB) for (const MachineInstr &MI : MBB) {
for (MachineBasicBlock::const_iterator II = IMBB->begin(), if (!canDefBePartOfLOH(&MI))
IEnd = IMBB->end();
II != IEnd; ++II) {
if (!canDefBePartOfLOH(II))
continue; continue;
// Process defs // Process defs
for (MachineInstr::const_mop_iterator IO = II->operands_begin(), for (MachineInstr::const_mop_iterator IO = MI.operands_begin(),
IOEnd = II->operands_end(); IOEnd = MI.operands_end();
IO != IOEnd; ++IO) { IO != IOEnd; ++IO) {
if (!IO->isReg() || !IO->isDef()) if (!IO->isReg() || !IO->isDef())
continue; continue;
@@ -1079,21 +1037,22 @@ static void collectInvolvedReg(MachineFunction &MF, MapRegToId &RegToId,
} }
} }
} }
}
} }
bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &Fn) { bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &MF) {
const TargetMachine &TM = Fn.getTarget(); const TargetMachine &TM = MF.getTarget();
const TargetRegisterInfo *TRI = TM.getRegisterInfo(); const TargetRegisterInfo *TRI = TM.getRegisterInfo();
const MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>(); const MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>();
MapRegToId RegToId; MapRegToId RegToId;
MapIdToReg IdToReg; MapIdToReg IdToReg;
ARM64FunctionInfo *ARM64FI = Fn.getInfo<ARM64FunctionInfo>(); ARM64FunctionInfo *ARM64FI = MF.getInfo<ARM64FunctionInfo>();
assert(ARM64FI && "No MachineFunctionInfo for this function!"); assert(ARM64FI && "No MachineFunctionInfo for this function!");
DEBUG(dbgs() << "Looking for LOH in " << Fn.getName() << '\n'); DEBUG(dbgs() << "Looking for LOH in " << MF.getName() << '\n');
collectInvolvedReg(Fn, RegToId, IdToReg, TRI); collectInvolvedReg(MF, RegToId, IdToReg, TRI);
if (RegToId.empty()) if (RegToId.empty())
return false; return false;
@@ -1103,7 +1062,7 @@ bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &Fn) {
static_cast<const ARM64InstrInfo *>(TM.getInstrInfo()); static_cast<const ARM64InstrInfo *>(TM.getInstrInfo());
// For local analysis, create a dummy operation to record uses that are not // For local analysis, create a dummy operation to record uses that are not
// local. // local.
DummyOp = Fn.CreateMachineInstr(TII->get(ARM64::COPY), DebugLoc()); DummyOp = MF.CreateMachineInstr(TII->get(ARM64::COPY), DebugLoc());
} }
unsigned NbReg = RegToId.size(); unsigned NbReg = RegToId.size();
@@ -1114,7 +1073,7 @@ bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &Fn) {
// Compute the reaching def in ADRP mode, meaning ADRP definitions // Compute the reaching def in ADRP mode, meaning ADRP definitions
// are first considered as uses. // are first considered as uses.
reachingDef(&Fn, ColorOpToReachedUses, RegToId, true, DummyOp); reachingDef(MF, ColorOpToReachedUses, RegToId, true, DummyOp);
DEBUG(dbgs() << "ADRP reaching defs\n"); DEBUG(dbgs() << "ADRP reaching defs\n");
DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg)); DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg));
@@ -1131,7 +1090,7 @@ bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &Fn) {
ColorOpToReachedUses = new InstrToInstrs[NbReg]; ColorOpToReachedUses = new InstrToInstrs[NbReg];
// first perform a regular reaching def analysis. // first perform a regular reaching def analysis.
reachingDef(&Fn, ColorOpToReachedUses, RegToId, false, DummyOp); reachingDef(MF, ColorOpToReachedUses, RegToId, false, DummyOp);
DEBUG(dbgs() << "All reaching defs\n"); DEBUG(dbgs() << "All reaching defs\n");
DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg)); DEBUG(printReachingDef(ColorOpToReachedUses, NbReg, TRI, IdToReg));
@@ -1145,7 +1104,7 @@ bool ARM64CollectLOH::runOnMachineFunction(MachineFunction &Fn) {
delete[] ColorOpToReachedUses; delete[] ColorOpToReachedUses;
if (BasicBlockScopeOnly) if (BasicBlockScopeOnly)
Fn.DeleteMachineInstr(DummyOp); MF.DeleteMachineInstr(DummyOp);
return Modified; return Modified;
} }