diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -195,7 +195,6 @@ bool relaxFragment(MCAsmLayout &Layout, MCFragment &F); bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); - bool relaxBoundaryAlign(MCAsmLayout &Layout, MCBoundaryAlignFragment &BF); bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); bool relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF); diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -528,9 +528,6 @@ bool Fused : 1; /// Flag to indicate whether NOPs should be emitted. bool EmitNops : 1; - /// The size of the fragment. The size is lazily set during relaxation, and - /// is not meaningful before that. - uint64_t Size = 0; public: MCBoundaryAlignFragment(Align AlignBoundary = Align(1), bool Fused = false, @@ -538,9 +535,6 @@ : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary), Fused(Fused), EmitNops(EmitNops) {} - uint64_t getSize() const { return Size; } - void setSize(uint64_t Value) { Size = Value; } - Align getAlignment() const { return AlignBoundary; } void setAlignment(Align Value) { AlignBoundary = Value; } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -285,6 +285,43 @@ return IsResolved; } +/// Check if the branch crosses the boundary. +/// +/// \param StartAddr start address of the fused/unfused branch. +/// \param Size size of the fused/unfused branch. +/// \param BoundaryAlignment alignment requirement of the branch. +/// \returns true if the branch cross the boundary. +static bool mayCrossBoundary(uint64_t StartAddr, uint64_t Size, + Align BoundaryAlignment) { + uint64_t EndAddr = StartAddr + Size; + return (StartAddr >> Log2(BoundaryAlignment)) != + ((EndAddr - 1) >> Log2(BoundaryAlignment)); +} + +/// Check if the branch is against the boundary. +/// +/// \param StartAddr start address of the fused/unfused branch. +/// \param Size size of the fused/unfused branch. +/// \param BoundaryAlignment alignment requirement of the branch. +/// \returns true if the branch is against the boundary. +static bool isAgainstBoundary(uint64_t StartAddr, uint64_t Size, + Align BoundaryAlignment) { + uint64_t EndAddr = StartAddr + Size; + return (EndAddr & (BoundaryAlignment.value() - 1)) == 0; +} + +/// Check if the branch needs padding. +/// +/// \param StartAddr start address of the fused/unfused branch. +/// \param Size size of the fused/unfused branch. +/// \param BoundaryAlignment alignment requirement of the branch. +/// \returns true if the branch needs padding. +static bool needPadding(uint64_t StartAddr, uint64_t Size, + Align BoundaryAlignment) { + return mayCrossBoundary(StartAddr, Size, BoundaryAlignment) || + isAgainstBoundary(StartAddr, Size, BoundaryAlignment); +} + uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const { assert(getBackendPtr() && "Requires assembler backend"); @@ -314,8 +351,26 @@ case MCFragment::FT_LEB: return cast(F).getContents().size(); - case MCFragment::FT_BoundaryAlign: - return cast(F).getSize(); + case MCFragment::FT_BoundaryAlign: { + const MCBoundaryAlignFragment &BF = cast(F); + // MCBoundaryAlignFragment that doesn't emit NOP should have 0 size. + if (!BF.canEmitNops()) + return 0; + + uint64_t AlignedOffset = Layout.getFragmentOffset(&BF); + uint64_t AlignedSize = 0; + const MCFragment *F = BF.getNextNode(); + // If the branch is unfused, it is emitted into one fragment, otherwise it + // is emitted into two fragments at most, the next + // MCBoundaryAlignFragment(if exists) also marks the end of the branch. + for (int I = 0, N = BF.isFused() ? 2 : 1; + I != N && !isa(F); ++I, F = F->getNextNode()) + AlignedSize += computeFragmentSize(Layout, *F); + Align BoundaryAlignment = BF.getAlignment(); + return needPadding(AlignedOffset, AlignedSize, BoundaryAlignment) + ? offsetToAlignment(AlignedOffset, BoundaryAlignment) + : 0U; + } case MCFragment::FT_SymbolId: return 4; @@ -957,72 +1012,6 @@ return OldSize != LF.getContents().size(); } -/// Check if the branch crosses the boundary. -/// -/// \param StartAddr start address of the fused/unfused branch. -/// \param Size size of the fused/unfused branch. -/// \param BoundaryAlignment alignment requirement of the branch. -/// \returns true if the branch cross the boundary. -static bool mayCrossBoundary(uint64_t StartAddr, uint64_t Size, - Align BoundaryAlignment) { - uint64_t EndAddr = StartAddr + Size; - return (StartAddr >> Log2(BoundaryAlignment)) != - ((EndAddr - 1) >> Log2(BoundaryAlignment)); -} - -/// Check if the branch is against the boundary. -/// -/// \param StartAddr start address of the fused/unfused branch. -/// \param Size size of the fused/unfused branch. -/// \param BoundaryAlignment alignment requirement of the branch. -/// \returns true if the branch is against the boundary. -static bool isAgainstBoundary(uint64_t StartAddr, uint64_t Size, - Align BoundaryAlignment) { - uint64_t EndAddr = StartAddr + Size; - return (EndAddr & (BoundaryAlignment.value() - 1)) == 0; -} - -/// Check if the branch needs padding. -/// -/// \param StartAddr start address of the fused/unfused branch. -/// \param Size size of the fused/unfused branch. -/// \param BoundaryAlignment alignment requirement of the branch. -/// \returns true if the branch needs padding. -static bool needPadding(uint64_t StartAddr, uint64_t Size, - Align BoundaryAlignment) { - return mayCrossBoundary(StartAddr, Size, BoundaryAlignment) || - isAgainstBoundary(StartAddr, Size, BoundaryAlignment); -} - -bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout, - MCBoundaryAlignFragment &BF) { - // The MCBoundaryAlignFragment that doesn't emit NOP should not be relaxed. - if (!BF.canEmitNops()) - return false; - - uint64_t AlignedOffset = Layout.getFragmentOffset(BF.getNextNode()); - uint64_t AlignedSize = 0; - const MCFragment *F = BF.getNextNode(); - // If the branch is unfused, it is emitted into one fragment, otherwise it is - // emitted into two fragments at most, the next MCBoundaryAlignFragment(if - // exists) also marks the end of the branch. - for (auto i = 0, N = BF.isFused() ? 2 : 1; - i != N && !isa(F); ++i, F = F->getNextNode()) { - AlignedSize += computeFragmentSize(Layout, *F); - } - uint64_t OldSize = BF.getSize(); - AlignedOffset -= OldSize; - Align BoundaryAlignment = BF.getAlignment(); - uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment) - ? offsetToAlignment(AlignedOffset, BoundaryAlignment) - : 0U; - if (NewSize == OldSize) - return false; - BF.setSize(NewSize); - Layout.invalidateFragmentsFrom(&BF); - return true; -} - bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF) { MCContext &Context = Layout.getAssembler().getContext(); @@ -1123,8 +1112,6 @@ cast(F)); case MCFragment::FT_LEB: return relaxLEB(Layout, cast(F)); - case MCFragment::FT_BoundaryAlign: - return relaxBoundaryAlign(Layout, cast(F)); case MCFragment::FT_CVInlineLines: return relaxCVInlineLineTable(Layout, cast(F)); case MCFragment::FT_CVDefRange: diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -431,8 +431,7 @@ else OS << " unfused branch)"; OS << "\n "; - OS << " BoundarySize:" << BF->getAlignment().value() - << " Size:" << BF->getSize(); + OS << " BoundarySize:" << BF->getAlignment().value(); break; } case MCFragment::FT_SymbolId: { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -442,7 +442,7 @@ if (!needAlign(OS)) return; // If the branch is emitted into a MCRelaxableFragment, we can determine the - // size of the branch easily in MCAssembler::relaxBoundaryAlign. When the + // size of the branch easily in during the process of layout. When the // branch is fused, the fused branch(macro fusion pair) must be emitted into // two fragments. Or when the branch is unfused, the branch must be emitted // into one fragment. The MCRelaxableFragment naturally marks the end of the