From 2bf6afc277edb32b1d940def5b3eb0e0d32a22b9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 15 Dec 2010 08:45:53 +0000 Subject: [PATCH] Relax alignment fragments. 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 | 4 -- include/llvm/MC/MCAssembler.h | 25 +++++++----- lib/MC/MCAssembler.cpp | 55 +++++++++++++-------------- test/MC/MachO/relax-recompute-align.s | 10 ++--- 4 files changed, 46 insertions(+), 48 deletions(-) diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 64b0b4e026c..7ea0bac0f72 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -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; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index ea250045ad7..19d8ea5d095 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -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; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index f05f6acd632..0fbd77c7f12 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -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(F).getContents().size(); @@ -289,17 +280,8 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F, case MCFragment::FT_LEB: return cast(F).getContents().size(); - case MCFragment::FT_Align: { - const MCAlignFragment &AF = cast(F); - - uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment()); - - // Honor MaxBytesToEmit. - if (Size > AF.getMaxBytesToEmit()) - return 0; - - return Size; - } + case MCFragment::FT_Align: + return cast(F).getSize(); case MCFragment::FT_Org: return cast(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(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(it2)); + break; case MCFragment::FT_Inst: relaxedFrag = RelaxInstruction(Writer, Layout, *cast(it2)); @@ -809,7 +806,7 @@ void MCFragment::dump() { } OS << ""; + << " Offset:" << Offset << ">"; switch (getKind()) { case MCFragment::FT_Align: { diff --git a/test/MC/MachO/relax-recompute-align.s b/test/MC/MachO/relax-recompute-align.s index b9734cebf36..249402502f7 100644 --- a/test/MC/MachO/relax-recompute-align.s +++ b/test/MC/MachO/relax-recompute-align.s @@ -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) -- 2.34.1