Relax alignment fragments.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Dec 2010 08:45:53 +0000 (08:45 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Dec 2010 08:45:53 +0000 (08:45 +0000)
With this we don't need the EffectiveSize field anymore. Without that field
LayoutFragment only updates offsets and we don't need to invalidate the
current fragment when it is relaxed (only the ones following it).

This is also a very small improvement in the accuracy of the layout info as
we now use the after relaxation size immediately.

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

include/llvm/MC/MCAsmLayout.h
include/llvm/MC/MCAssembler.h
lib/MC/MCAssembler.cpp
test/MC/MachO/relax-recompute-align.s

index 64b0b4e026cfc32131d6f86b7d4ef78141401f52..7ea0bac0f72ee4d56ebaab95a486994655a34bcf 100644 (file)
@@ -76,10 +76,6 @@ public:
   /// @name Fragment Layout Data
   /// @{
 
-  /// \brief Get the effective size of the given fragment, as computed in the
-  /// current layout.
-  uint64_t getFragmentEffectiveSize(const MCFragment *F) const;
-
   /// \brief Get the offset of the given fragment inside its containing section.
   uint64_t getFragmentOffset(const MCFragment *F) const;
 
index ea250045ad73bcf43210ef84d43a5ae2e5ad1d8b..19d8ea5d095fee466372d98608aaad6de975d0f0 100644 (file)
@@ -75,10 +75,6 @@ private:
   /// initialized.
   uint64_t Offset;
 
-  /// EffectiveSize - The compute size of this section. This is ~0 until
-  /// initialized.
-  uint64_t EffectiveSize;
-
   /// LayoutOrder - The layout order of this fragment.
   unsigned LayoutOrder;
 
@@ -231,6 +227,9 @@ class MCAlignFragment : public MCFragment {
   /// cannot be satisfied in this width then this fragment is ignored.
   unsigned MaxBytesToEmit;
 
+  /// Size - The current estimate of the size.
+  unsigned Size;
+
   /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead
   /// of using the provided value. The exact interpretation of this flag is
   /// target dependent.
@@ -241,7 +240,7 @@ public:
                   unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
     : MCFragment(FT_Align, SD), Alignment(_Alignment),
       Value(_Value),ValueSize(_ValueSize),
-      MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {}
+      MaxBytesToEmit(_MaxBytesToEmit), Size(0), EmitNops(false) {}
 
   /// @name Accessors
   /// @{
@@ -252,6 +251,10 @@ public:
 
   unsigned getValueSize() const { return ValueSize; }
 
+  unsigned getSize() const { return Size; }
+
+  void setSize(unsigned Size_) { Size = Size_; }
+
   unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
 
   bool hasEmitNops() const { return EmitNops; }
@@ -704,11 +707,6 @@ private:
                                const MCInstFragment *IF,
                                const MCAsmLayout &Layout) const;
 
-  /// Compute the effective fragment size assuming it is layed out at the given
-  /// \arg SectionAddress and \arg FragmentOffset.
-  uint64_t ComputeFragmentSize(const MCFragment &F,
-                               uint64_t FragmentOffset) const;
-
   /// LayoutOnce - Perform one layout iteration and return true if any offsets
   /// were adjusted.
   bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout);
@@ -725,6 +723,9 @@ private:
   bool RelaxDwarfLineAddr(const MCObjectWriter &Writer, MCAsmLayout &Layout,
                          MCDwarfLineAddrFragment &DF);
 
+  bool RelaxAlignment(const MCObjectWriter &Writer, MCAsmLayout &Layout,
+                     MCAlignFragment &DF);
+
   /// FinishLayout - Finalize a layout, including fragment lowering.
   void FinishLayout(MCAsmLayout &Layout);
 
@@ -732,6 +733,10 @@ private:
                        MCFragment &F, const MCFixup &Fixup);
 
 public:
+  /// Compute the effective fragment size assuming it is layed out at the given
+  /// \arg SectionAddress and \arg FragmentOffset.
+  uint64_t ComputeFragmentSize(const MCFragment &F) const;
+
   /// Find the symbol which defines the atom containing the given symbol, or
   /// null if there is no such symbol.
   const MCSymbolData *getAtom(const MCSymbolData *Symbol) const;
index f05f6acd6324b7218ee93e3b66cea7c6d9e7a2a9..0fbd77c7f12853b98fd269557816d4f3f7ac91ec 100644 (file)
@@ -74,10 +74,9 @@ void MCAsmLayout::Invalidate(MCFragment *F) {
   if (!isFragmentUpToDate(F))
     return;
 
-  // Otherwise, reset the last valid fragment to the predecessor of the
-  // invalidated fragment.
+  // Otherwise, reset the last valid fragment to this fragment.
   const MCSectionData &SD = *F->getParent();
-  LastValidFragment[&SD] = F->getPrevNode();
+  LastValidFragment[&SD] = F;
 }
 
 void MCAsmLayout::EnsureValid(const MCFragment *F) const {
@@ -96,12 +95,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const {
   }
 }
 
-uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
-  EnsureValid(F);
-  assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
-  return F->EffectiveSize;
-}
-
 uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
   EnsureValid(F);
   assert(F->Offset != ~UINT64_C(0) && "Address not set!");
@@ -116,7 +109,7 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
 uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
   // The size is the last fragment's end offset.
   const MCFragment &F = SD->getFragmentList().back();
-  return getFragmentOffset(&F) + getFragmentEffectiveSize(&F);
+  return getFragmentOffset(&F) + getAssembler().ComputeFragmentSize(F);
 }
 
 uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
@@ -137,8 +130,7 @@ MCFragment::~MCFragment() {
 }
 
 MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
-  : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)),
-    EffectiveSize(~UINT64_C(0))
+  : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0))
 {
   if (Parent)
     Parent->getFragmentList().push_back(this);
@@ -276,8 +268,7 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
   return IsResolved;
 }
 
-uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
-                                          uint64_t FragmentOffset) const {
+uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F) const {
   switch (F.getKind()) {
   case MCFragment::FT_Data:
     return cast<MCDataFragment>(F).getContents().size();
@@ -289,17 +280,8 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
   case MCFragment::FT_LEB:
     return cast<MCLEBFragment>(F).getContents().size();
 
-  case MCFragment::FT_Align: {
-    const MCAlignFragment &AF = cast<MCAlignFragment>(F);
-
-    uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment());
-
-    // Honor MaxBytesToEmit.
-    if (Size > AF.getMaxBytesToEmit())
-      return 0;
-
-    return Size;
-  }
+  case MCFragment::FT_Align:
+    return cast<MCAlignFragment>(F).getSize();
 
   case MCFragment::FT_Org:
     return cast<MCOrgFragment>(F).getSize();
@@ -327,10 +309,9 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
   // Compute fragment offset and size.
   uint64_t Offset = 0;
   if (Prev)
-    Offset += Prev->Offset + Prev->EffectiveSize;
+    Offset += Prev->Offset + getAssembler().ComputeFragmentSize(*Prev);
 
   F->Offset = Offset;
-  F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
   LastValidFragment[F->getParent()] = F;
 }
 
@@ -343,7 +324,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
   ++stats::EmittedFragments;
 
   // FIXME: Embed in fragments instead?
-  uint64_t FragmentSize = Layout.getFragmentEffectiveSize(&F);
+  uint64_t FragmentSize = Asm.ComputeFragmentSize(F);
   switch (F.getKind()) {
   case MCFragment::FT_Align: {
     MCAlignFragment &AF = cast<MCAlignFragment>(F);
@@ -730,6 +711,18 @@ bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer,
   return OldSize != Data.size();
 }
 
+bool MCAssembler::RelaxAlignment(const MCObjectWriter &Writer,
+                                MCAsmLayout &Layout,
+                                MCAlignFragment &AF) {
+  unsigned Offset = Layout.getFragmentOffset(&AF);
+  unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
+  if (Size > AF.getMaxBytesToEmit())
+    Size = 0;
+  unsigned OldSize = AF.getSize();
+  AF.setSize(Size);
+  return OldSize != Size;
+}
+
 bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
                              MCAsmLayout &Layout) {
   ++stats::RelaxationSteps;
@@ -747,6 +740,10 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
       switch(it2->getKind()) {
       default:
         break;
+      case MCFragment::FT_Align:
+       relaxedFrag = RelaxAlignment(Writer, Layout,
+                                    *cast<MCAlignFragment>(it2));
+       break;
       case MCFragment::FT_Inst:
         relaxedFrag = RelaxInstruction(Writer, Layout,
                                        *cast<MCInstFragment>(it2));
@@ -809,7 +806,7 @@ void MCFragment::dump() {
   }
 
   OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
-     << " Offset:" << Offset << " EffectiveSize:" << EffectiveSize << ">";
+     << " Offset:" << Offset << ">";
 
   switch (getKind()) {
   case MCFragment::FT_Align: {
index b9734cebf36b6a3eb259875670d62a478d729c14..249402502f714787d8493731a3f639fcd60fdec6 100644 (file)
@@ -3,16 +3,16 @@
 // FIXME: This is a horrible way of checking the output, we need an llvm-mc
 // based 'otool'.
 
-// FIXME: PR8467.
-// There is an unnecessary relaxation here. After the first jmp slides,
-// the .align size could be recomputed so that the second jump will be in range
-// for a 1-byte jump. For performance reasons, this is not currently done.
+// This is a case where llvm-mc computes a better layout than Darwin 'as'. This
+// issue is that after the first jmp slides, the .align size must be
+// recomputed -- otherwise the second jump will appear to be out-of-range for a
+// 1-byte jump.
 
 // CHECK:  # Section 0
 // CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
 // CHECK:  ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
 // CHECK:  ('address', 0)
-// CHECK:  ('size', 322)
+// CHECK:  ('size', 306)
 // CHECK:  ('offset', 324)
 // CHECK:  ('alignment', 4)
 // CHECK:  ('reloc_offset', 0)