aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-11-23 05:49:35 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-11-23 05:49:35 +0000
commit0e11dfc4a6f7e3a3d3bc0365e1da43bc2fa0aac2 (patch)
treedf4f6520b3356bdd23640994f46ee9626ea77e9d
parentcafe0b4e1fec183f26e0ae374c09bad77388820a (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.h11
-rw-r--r--lib/MC/MCAssembler.cpp103
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++);
}
}
}