mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-12 18:33:22 +00:00
Layout each section independently. With the testcase in PR8711:
before: 4 assembler - Number of assembler layout and relaxation steps 78563 assembler - Number of emitted assembler fragments 8693904 assembler - Number of emitted object file bytes 271223 assembler - Number of evaluated fixups 330771677 assembler - Number of fragment layouts 5958 assembler - Number of relaxed instructions 2508361 mcexpr - Number of MCExpr evaluations real 0m26.123s user 0m25.694s sys 0m0.388s after: 4 assembler - Number of assembler layout and relaxation steps 78563 assembler - Number of emitted assembler fragments 8693904 assembler - Number of emitted object file bytes 271223 assembler - Number of evaluated fixups 231507 assembler - Number of fragment layouts 5958 assembler - Number of relaxed instructions 2508361 mcexpr - Number of MCExpr evaluations real 0m2.500s user 0m2.113s sys 0m0.273s And yes, the outputs are identical :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121207 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2bf315f087
commit
4f4363a490
@ -39,13 +39,12 @@ private:
|
|||||||
/// The last fragment which was layed out, or 0 if nothing has been layed
|
/// The last fragment which was layed out, or 0 if nothing has been layed
|
||||||
/// out. Fragments are always layed out in order, so all fragments with a
|
/// out. Fragments are always layed out in order, so all fragments with a
|
||||||
/// lower ordinal will be up to date.
|
/// lower ordinal will be up to date.
|
||||||
mutable MCFragment *LastValidFragment;
|
mutable DenseMap<const MCSectionData*, MCFragment *> LastValidFragment;
|
||||||
|
|
||||||
/// \brief Make sure that the layout for the given fragment is valid, lazily
|
/// \brief Make sure that the layout for the given fragment is valid, lazily
|
||||||
/// computing it if necessary.
|
/// computing it if necessary.
|
||||||
void EnsureValid(const MCFragment *F) const;
|
void EnsureValid(const MCFragment *F) const;
|
||||||
|
|
||||||
bool isSectionUpToDate(const MCSectionData *SD) const;
|
|
||||||
bool isFragmentUpToDate(const MCFragment *F) const;
|
bool isFragmentUpToDate(const MCFragment *F) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -58,9 +57,6 @@ public:
|
|||||||
/// fragments size should have already been updated.
|
/// fragments size should have already been updated.
|
||||||
void Invalidate(MCFragment *F);
|
void Invalidate(MCFragment *F);
|
||||||
|
|
||||||
/// \brief Perform a full layout.
|
|
||||||
void LayoutFile();
|
|
||||||
|
|
||||||
/// \brief Perform layout for a single fragment, assuming that the previous
|
/// \brief Perform layout for a single fragment, assuming that the previous
|
||||||
/// fragment has already been layed out correctly, and the parent section has
|
/// fragment has already been layed out correctly, and the parent section has
|
||||||
/// been initialized.
|
/// been initialized.
|
||||||
|
@ -78,8 +78,7 @@ private:
|
|||||||
/// initialized.
|
/// initialized.
|
||||||
uint64_t EffectiveSize;
|
uint64_t EffectiveSize;
|
||||||
|
|
||||||
/// LayoutOrder - The global layout order of this fragment. This is the index
|
/// LayoutOrder - The layout order of this fragment.
|
||||||
/// across all fragments in the file, not just within the section.
|
|
||||||
unsigned LayoutOrder;
|
unsigned LayoutOrder;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
@ -49,7 +49,7 @@ STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
|
|||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
MCAsmLayout::MCAsmLayout(MCAssembler &Asm)
|
MCAsmLayout::MCAsmLayout(MCAssembler &Asm)
|
||||||
: Assembler(Asm), LastValidFragment(0)
|
: Assembler(Asm), LastValidFragment()
|
||||||
{
|
{
|
||||||
// Compute the section layout order. Virtual sections must go last.
|
// Compute the section layout order. Virtual sections must go last.
|
||||||
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
|
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
|
||||||
@ -60,21 +60,13 @@ MCAsmLayout::MCAsmLayout(MCAssembler &Asm)
|
|||||||
SectionOrder.push_back(&*it);
|
SectionOrder.push_back(&*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCAsmLayout::isSectionUpToDate(const MCSectionData *SD) const {
|
|
||||||
// The first section is always up-to-date.
|
|
||||||
unsigned Index = SD->getLayoutOrder();
|
|
||||||
if (!Index)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Otherwise, sections are always implicitly computed when the preceeding
|
|
||||||
// fragment is layed out.
|
|
||||||
const MCSectionData *Prev = getSectionOrder()[Index - 1];
|
|
||||||
return isFragmentUpToDate(&(Prev->getFragmentList().back()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const {
|
bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const {
|
||||||
return (LastValidFragment &&
|
const MCSectionData &SD = *F->getParent();
|
||||||
F->getLayoutOrder() <= LastValidFragment->getLayoutOrder());
|
const MCFragment *LastValid = LastValidFragment.lookup(&SD);
|
||||||
|
if (!LastValid)
|
||||||
|
return false;
|
||||||
|
assert(LastValid->getParent() == F->getParent());
|
||||||
|
return F->getLayoutOrder() <= LastValid->getLayoutOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCAsmLayout::Invalidate(MCFragment *F) {
|
void MCAsmLayout::Invalidate(MCFragment *F) {
|
||||||
@ -84,31 +76,23 @@ void MCAsmLayout::Invalidate(MCFragment *F) {
|
|||||||
|
|
||||||
// Otherwise, reset the last valid fragment to the predecessor of the
|
// Otherwise, reset the last valid fragment to the predecessor of the
|
||||||
// invalidated fragment.
|
// invalidated fragment.
|
||||||
LastValidFragment = F->getPrevNode();
|
const MCSectionData &SD = *F->getParent();
|
||||||
if (!LastValidFragment) {
|
LastValidFragment[&SD] = F->getPrevNode();
|
||||||
unsigned Index = F->getParent()->getLayoutOrder();
|
|
||||||
if (Index != 0) {
|
|
||||||
MCSectionData *Prev = getSectionOrder()[Index - 1];
|
|
||||||
LastValidFragment = &(Prev->getFragmentList().back());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCAsmLayout::EnsureValid(const MCFragment *F) const {
|
void MCAsmLayout::EnsureValid(const MCFragment *F) const {
|
||||||
|
MCSectionData &SD = *F->getParent();
|
||||||
|
|
||||||
|
MCFragment *Cur = LastValidFragment[&SD];
|
||||||
|
if (!Cur)
|
||||||
|
Cur = &*SD.begin();
|
||||||
|
else
|
||||||
|
Cur = Cur->getNextNode();
|
||||||
|
|
||||||
// Advance the layout position until the fragment is up-to-date.
|
// Advance the layout position until the fragment is up-to-date.
|
||||||
while (!isFragmentUpToDate(F)) {
|
while (!isFragmentUpToDate(F)) {
|
||||||
// Advance to the next fragment.
|
|
||||||
MCFragment *Cur = LastValidFragment;
|
|
||||||
if (Cur)
|
|
||||||
Cur = Cur->getNextNode();
|
|
||||||
if (!Cur) {
|
|
||||||
unsigned NextIndex = 0;
|
|
||||||
if (LastValidFragment)
|
|
||||||
NextIndex = LastValidFragment->getParent()->getLayoutOrder() + 1;
|
|
||||||
Cur = SectionOrder[NextIndex]->begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
const_cast<MCAsmLayout*>(this)->LayoutFragment(Cur);
|
const_cast<MCAsmLayout*>(this)->LayoutFragment(Cur);
|
||||||
|
Cur = Cur->getNextNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,21 +295,11 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCAsmLayout::LayoutFile() {
|
|
||||||
// Initialize the first section and set the valid fragment layout point. All
|
|
||||||
// actual layout computations are done lazily.
|
|
||||||
LastValidFragment = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MCAsmLayout::LayoutFragment(MCFragment *F) {
|
void MCAsmLayout::LayoutFragment(MCFragment *F) {
|
||||||
MCFragment *Prev = F->getPrevNode();
|
MCFragment *Prev = F->getPrevNode();
|
||||||
|
|
||||||
// We should never try to recompute something which is up-to-date.
|
// We should never try to recompute something which is up-to-date.
|
||||||
assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!");
|
assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!");
|
||||||
// We should never try to compute the fragment layout if the section isn't
|
|
||||||
// up-to-date.
|
|
||||||
assert(isSectionUpToDate(F->getParent()) &&
|
|
||||||
"Attempt to compute fragment before it's section!");
|
|
||||||
// We should never try to compute the fragment layout if it's predecessor
|
// We should never try to compute the fragment layout if it's predecessor
|
||||||
// isn't up-to-date.
|
// isn't up-to-date.
|
||||||
assert((!Prev || isFragmentUpToDate(Prev)) &&
|
assert((!Prev || isFragmentUpToDate(Prev)) &&
|
||||||
@ -340,7 +314,7 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
|
|||||||
|
|
||||||
F->Offset = Offset;
|
F->Offset = Offset;
|
||||||
F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
|
F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
|
||||||
LastValidFragment = F;
|
LastValidFragment[F->getParent()] = F;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WriteFragmentData - Write the \arg F data to the output file.
|
/// WriteFragmentData - Write the \arg F data to the output file.
|
||||||
@ -541,11 +515,11 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assign layout order indices to sections and fragments.
|
// Assign layout order indices to sections and fragments.
|
||||||
unsigned FragmentIndex = 0;
|
|
||||||
for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) {
|
for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) {
|
||||||
MCSectionData *SD = Layout.getSectionOrder()[i];
|
MCSectionData *SD = Layout.getSectionOrder()[i];
|
||||||
SD->setLayoutOrder(i);
|
SD->setLayoutOrder(i);
|
||||||
|
|
||||||
|
unsigned FragmentIndex = 0;
|
||||||
for (MCSectionData::iterator it2 = SD->begin(),
|
for (MCSectionData::iterator it2 = SD->begin(),
|
||||||
ie2 = SD->end(); it2 != ie2; ++it2)
|
ie2 = SD->end(); it2 != ie2; ++it2)
|
||||||
it2->setLayoutOrder(FragmentIndex++);
|
it2->setLayoutOrder(FragmentIndex++);
|
||||||
@ -743,9 +717,6 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
|
|||||||
MCAsmLayout &Layout) {
|
MCAsmLayout &Layout) {
|
||||||
++stats::RelaxationSteps;
|
++stats::RelaxationSteps;
|
||||||
|
|
||||||
// Layout the sections in order.
|
|
||||||
Layout.LayoutFile();
|
|
||||||
|
|
||||||
// Scan for fragments that need relaxation.
|
// Scan for fragments that need relaxation.
|
||||||
bool WasRelaxed = false;
|
bool WasRelaxed = false;
|
||||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||||
@ -784,16 +755,10 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
|
void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
|
||||||
// Lower out any instruction fragments, to simplify the fixup application and
|
|
||||||
// output.
|
|
||||||
//
|
|
||||||
// FIXME-PERF: We don't have to do this, but the assumption is that it is
|
|
||||||
// cheap (we will mostly end up eliminating fragments and appending on to data
|
|
||||||
// fragments), so the extra complexity downstream isn't worth it. Evaluate
|
|
||||||
// this assumption.
|
|
||||||
|
|
||||||
// The layout is done. Mark every fragment as valid.
|
// The layout is done. Mark every fragment as valid.
|
||||||
Layout.getFragmentOffset(&*Layout.getSectionOrder().back()->rbegin());
|
for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
|
||||||
|
Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugging methods
|
// Debugging methods
|
||||||
|
Loading…
x
Reference in New Issue
Block a user