mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
[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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user