diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-11-23 05:49:35 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-11-23 05:49:35 +0000 |
commit | 0e11dfc4a6f7e3a3d3bc0365e1da43bc2fa0aac2 (patch) | |
tree | df4f6520b3356bdd23640994f46ee9626ea77e9d | |
parent | cafe0b4e1fec183f26e0ae374c09bad77388820a (diff) |
Reuse data fragments while lowering. Patch by David Meyer.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119999 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/MC/MCAsmLayout.h | 11 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 103 |
2 files changed, 86 insertions, 28 deletions
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index b9565ba061..6feacf56e4 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -59,8 +59,15 @@ public: /// the delta from the old size. void UpdateForSlide(MCFragment *F, int SlideAmount); - /// \brief Update the layout because a fragment has been replaced. - void FragmentReplaced(MCFragment *Src, MCFragment *Dst); + /// \brief Update the layout, replacing Src with Dst. The contents + /// of Src and Dst are not modified, and must be copied by the caller. + /// Src will be removed from the layout, but not deleted. + void ReplaceFragment(MCFragment *Src, MCFragment *Dst); + + /// \brief Update the layout to coalesce Src into Dst. The contents + /// of Src and Dst are not modified, and must be coalesced by the caller. + /// Src will be removed from the layout, but not deleted. + void CoalesceFragments(MCFragment *Src, MCFragment *Dst); /// \brief Perform a full layout. void LayoutFile(); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 9ca8928bce..a38aa8d8e0 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -113,12 +113,40 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const { } } -void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) { +void MCAsmLayout::ReplaceFragment(MCFragment *Src, MCFragment *Dst) { + MCSectionData *SD = Src->getParent(); + + // Insert Dst immediately before Src + SD->getFragmentList().insert(Src, Dst); + + // Set the data fragment's layout data. + Dst->setParent(Src->getParent()); + Dst->setAtom(Src->getAtom()); + Dst->setLayoutOrder(Src->getLayoutOrder()); + if (LastValidFragment == Src) LastValidFragment = Dst; Dst->Offset = Src->Offset; Dst->EffectiveSize = Src->EffectiveSize; + + // Remove Src, but don't delete it yet. + SD->getFragmentList().remove(Src); +} + +void MCAsmLayout::CoalesceFragments(MCFragment *Src, MCFragment *Dst) { + assert(Src->getPrevNode() == Dst); + + if (isFragmentUpToDate(Src)) { + if (LastValidFragment == Src) + LastValidFragment = Dst; + Dst->EffectiveSize += Src->EffectiveSize; + } else { + // We don't know the effective size of Src, so we have to invalidate Dst. + UpdateForSlide(Dst, 0); + } + // Remove Src, but don't delete it yet. + Src->getParent()->getFragmentList().remove(Src); } uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const { @@ -890,6 +918,22 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, return WasRelaxed; } +static void LowerInstFragment(MCInstFragment *IF, + MCDataFragment *DF) { + + uint64_t DataOffset = DF->getContents().size(); + + // Copy in the data + DF->getContents().append(IF->getCode().begin(), IF->getCode().end()); + + // Adjust the fixup offsets and add them to the data fragment. + for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i) { + MCFixup &F = IF->getFixups()[i]; + F.setOffset(DataOffset + F.getOffset()); + DF->getFixups().push_back(F); + } +} + void MCAssembler::FinishLayout(MCAsmLayout &Layout) { // Lower out any instruction fragments, to simplify the fixup application and // output. @@ -898,35 +942,42 @@ void MCAssembler::FinishLayout(MCAsmLayout &Layout) { // 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. - for (iterator it = begin(), ie = end(); it != ie; ++it) { - MCSectionData &SD = *it; + unsigned FragmentIndex = 0; + for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) { + MCSectionData &SD = *Layout.getSectionOrder()[i]; + MCDataFragment *CurDF = NULL; for (MCSectionData::iterator it2 = SD.begin(), ie2 = SD.end(); it2 != ie2; ++it2) { - MCInstFragment *IF = dyn_cast<MCInstFragment>(it2); - if (!IF) - continue; + switch (it2->getKind()) { + default: + CurDF = NULL; + break; + case MCFragment::FT_Data: + CurDF = cast<MCDataFragment>(it2); + break; + case MCFragment::FT_Inst: { + MCInstFragment *IF = cast<MCInstFragment>(it2); + // Use the existing data fragment if possible. + if (CurDF && CurDF->getAtom() == IF->getAtom()) { + Layout.CoalesceFragments(IF, CurDF); + } else { + // Otherwise, create a new data fragment. + CurDF = new MCDataFragment(); + Layout.ReplaceFragment(IF, CurDF); + } - // Create a new data fragment for the instruction. - // - // FIXME-PERF: Reuse previous data fragment if possible. - MCDataFragment *DF = new MCDataFragment(); - SD.getFragmentList().insert(it2, DF); - - // Update the data fragments layout data. - DF->setParent(IF->getParent()); - DF->setAtom(IF->getAtom()); - DF->setLayoutOrder(IF->getLayoutOrder()); - Layout.FragmentReplaced(IF, DF); - - // Copy in the data and the fixups. - DF->getContents().append(IF->getCode().begin(), IF->getCode().end()); - for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i) - DF->getFixups().push_back(IF->getFixups()[i]); - - // Delete the instruction fragment and update the iterator. - SD.getFragmentList().erase(IF); - it2 = DF; + // Lower the Instruction Fragment + LowerInstFragment(IF, CurDF); + + // Delete the instruction fragment and update the iterator. + delete IF; + it2 = CurDF; + break; + } + } + // Since we may have merged fragments, fix the layout order. + it2->setLayoutOrder(FragmentIndex++); } } } |