Reuse data fragments while lowering. Patch by David Meyer.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 23 Nov 2010 05:49:35 +0000 (05:49 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 23 Nov 2010 05:49:35 +0000 (05:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119999 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAsmLayout.h
lib/MC/MCAssembler.cpp

index b9565ba06197ac350d2007a50a59ed5558e9e40e..6feacf56e4d90a61b63de4b940b6316f6d107d48 100644 (file)
@@ -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();
index 9ca8928bcecf7c80e051659ca77bf658e536f78b..a38aa8d8e07bf4d9089b23744652603101182eb8 100644 (file)
@@ -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++);
     }
   }
 }