MC: Stop restarting layout on every relaxation.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 25 Mar 2010 19:35:56 +0000 (19:35 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 25 Mar 2010 19:35:56 +0000 (19:35 +0000)
 - Still O(N^2), just a faster form, and now its the MCAsmLayout's fault.

On the .s I am tuning against (combine.s from 403.gcc):
--
ddunbar@lordcrumb:MC$ diff stats-before.txt stats-after.txt
5,10c5,10
<    1728 assembler - Number of assembler layout and relaxation steps
<    7707 assembler - Number of emitted assembler fragments
<  120588 assembler - Number of emitted object file bytes
2233448 assembler - Number of evaluated fixups
<    1727 assembler - Number of relaxed instructions
6723845 mcexpr    - Number of MCExpr evaluations
---
>      3 assembler - Number of assembler layout and relaxation steps
>   7707 assembler - Number of emitted assembler fragments
> 120588 assembler - Number of emitted object file bytes
>  14796 assembler - Number of evaluated fixups
>   1727 assembler - Number of relaxed instructions
>  67889 mcexpr    - Number of MCExpr evaluations
--
Feel free to LOL at the -before numbers, if you like.

I am a little surprised we make more than 2 relaxation passes. It's pretty
trivial for us to do relaxation out-of-order if that would give a speedup.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99543 91177308-0d34-0410-b5e6-96231b3b80d8

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

index f7f32aed6ff8ddcdb819679092cf07cd2860e48d..ebf0520d091f0cdf0e1f493b079b057943644091 100644 (file)
@@ -33,6 +33,11 @@ public:
   /// Get the assembler object this is a layout for.
   MCAssembler &getAssembler() const { return Assembler; }
 
+  /// \brief Update the layout because a fragment has been resized. The
+  /// fragments size should have already been updated, the \arg SlideAmount is
+  /// the delta from the old size.
+  void UpdateForSlide(MCFragment *F, int SlideAmount);
+
   /// @name Fragment Layout Data
   /// @{
 
index bdcc1bf4c14b7ae7d954c9b37b6d3ece20a23199..031ca18d7480485344be48358b7a947b1a3d5ac2 100644 (file)
@@ -580,6 +580,8 @@ struct IndirectSymbolData {
 };
 
 class MCAssembler {
+  friend class MCAsmLayout;
+
 public:
   typedef iplist<MCSectionData> SectionDataListType;
   typedef iplist<MCSymbolData> SymbolDataListType;
index c3e2ca830de4e48386289c18109bdf5d11e1c789..79a8436bc24cca20ae6a91c5d943b458294d6c9f 100644 (file)
@@ -45,6 +45,39 @@ STATISTIC(ObjectBytes, "Number of emitted object file bytes");
 
 /* *** */
 
+void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) {
+  // We shouldn't have to do anything special to support negative slides, and it
+  // is a perfectly valid thing to do as long as other parts of the system are
+  // can guarantee convergence.
+  assert(SlideAmount >= 0 && "Negative slides not yet supported");
+
+  // Update the layout by simply recomputing the layout for the entire
+  // file. This is trivially correct, but very slow.
+  //
+  // FIXME-PERF: This is O(N^2), but will be eliminated once we get smarter.
+
+  // Layout the concrete sections and fragments.
+  MCAssembler &Asm = getAssembler();
+  uint64_t Address = 0;
+  for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
+    // Skip virtual sections.
+    if (Asm.getBackend().isVirtualSection(it->getSection()))
+      continue;
+
+    // Layout the section fragments and its size.
+    Address = Asm.LayoutSection(*it, *this, Address);
+  }
+
+  // Layout the virtual sections.
+  for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) {
+    if (!Asm.getBackend().isVirtualSection(it->getSection()))
+      continue;
+
+    // Layout the section fragments and its size.
+    Address = Asm.LayoutSection(*it, *this, Address);
+  }
+}
+
 uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
   assert(F->getParent() && "Missing section()!");
   return getSectionAddress(F->getParent()) + getFragmentOffset(F);
@@ -716,6 +749,7 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
   }
 
   // Scan for fragments that need relaxation.
+  bool WasRelaxed = false;
   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     MCSectionData &SD = *it;
 
@@ -747,6 +781,7 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
       VecOS.flush();
 
       // Update the instruction fragment.
+      int SlideAmount = Code.size() - IF->getInstSize();
       IF->setInst(Relaxed);
       IF->getCode() = Code;
       IF->getFixups().clear();
@@ -756,15 +791,13 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) {
                                              F.getKind()));
       }
 
-      // Restart layout.
-      //
-      // FIXME-PERF: This is O(N^2), but will be eliminated once we have a
-      // smart MCAsmLayout object.
-      return true;
+      // Update the layout, and remember that we relaxed.
+      Layout.UpdateForSlide(IF, SlideAmount);
+      WasRelaxed = true;
     }
   }
 
-  return false;
+  return WasRelaxed;
 }
 
 void MCAssembler::FinishLayout(MCAsmLayout &Layout) {