Loading llvm/include/llvm/MC/MCAssembler.h +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ private: 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); Loading llvm/include/llvm/MC/MCFragment.h +6 −0 Original line number Diff line number Diff line Loading @@ -528,6 +528,9 @@ class MCBoundaryAlignFragment : public MCFragment { 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, Loading @@ -535,6 +538,9 @@ public: : 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; } Loading llvm/lib/MC/MCAssembler.cpp +70 −57 Original line number Diff line number Diff line Loading @@ -285,43 +285,6 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, 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"); Loading Loading @@ -351,26 +314,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_LEB: return cast<MCLEBFragment>(F).getContents().size(); case MCFragment::FT_BoundaryAlign: { const MCBoundaryAlignFragment &BF = cast<MCBoundaryAlignFragment>(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<MCBoundaryAlignFragment>(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_BoundaryAlign: return cast<MCBoundaryAlignFragment>(F).getSize(); case MCFragment::FT_SymbolId: return 4; Loading Loading @@ -1012,6 +957,72 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { 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<MCBoundaryAlignFragment>(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(); Loading Loading @@ -1112,6 +1123,8 @@ bool MCAssembler::relaxFragment(MCAsmLayout &Layout, MCFragment &F) { cast<MCDwarfCallFrameFragment>(F)); case MCFragment::FT_LEB: return relaxLEB(Layout, cast<MCLEBFragment>(F)); case MCFragment::FT_BoundaryAlign: return relaxBoundaryAlign(Layout, cast<MCBoundaryAlignFragment>(F)); case MCFragment::FT_CVInlineLines: return relaxCVInlineLineTable(Layout, cast<MCCVInlineLineTableFragment>(F)); case MCFragment::FT_CVDefRange: Loading llvm/lib/MC/MCFragment.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -431,7 +431,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { else OS << " unfused branch)"; OS << "\n "; OS << " BoundarySize:" << BF->getAlignment().value(); OS << " BoundarySize:" << BF->getAlignment().value() << " Size:" << BF->getSize(); break; } case MCFragment::FT_SymbolId: { Loading llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -466,7 +466,7 @@ void X86AsmBackend::alignBranchesEnd(MCObjectStreamer &OS, const MCInst &Inst) { if (!needAlign(OS)) return; // If the branch is emitted into a MCRelaxableFragment, we can determine the // size of the branch easily in during the process of layout. When the // size of the branch easily in MCAssembler::relaxBoundaryAlign. 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 Loading Loading
llvm/include/llvm/MC/MCAssembler.h +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ private: 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); Loading
llvm/include/llvm/MC/MCFragment.h +6 −0 Original line number Diff line number Diff line Loading @@ -528,6 +528,9 @@ class MCBoundaryAlignFragment : public MCFragment { 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, Loading @@ -535,6 +538,9 @@ public: : 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; } Loading
llvm/lib/MC/MCAssembler.cpp +70 −57 Original line number Diff line number Diff line Loading @@ -285,43 +285,6 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, 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"); Loading Loading @@ -351,26 +314,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_LEB: return cast<MCLEBFragment>(F).getContents().size(); case MCFragment::FT_BoundaryAlign: { const MCBoundaryAlignFragment &BF = cast<MCBoundaryAlignFragment>(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<MCBoundaryAlignFragment>(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_BoundaryAlign: return cast<MCBoundaryAlignFragment>(F).getSize(); case MCFragment::FT_SymbolId: return 4; Loading Loading @@ -1012,6 +957,72 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { 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<MCBoundaryAlignFragment>(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(); Loading Loading @@ -1112,6 +1123,8 @@ bool MCAssembler::relaxFragment(MCAsmLayout &Layout, MCFragment &F) { cast<MCDwarfCallFrameFragment>(F)); case MCFragment::FT_LEB: return relaxLEB(Layout, cast<MCLEBFragment>(F)); case MCFragment::FT_BoundaryAlign: return relaxBoundaryAlign(Layout, cast<MCBoundaryAlignFragment>(F)); case MCFragment::FT_CVInlineLines: return relaxCVInlineLineTable(Layout, cast<MCCVInlineLineTableFragment>(F)); case MCFragment::FT_CVDefRange: Loading
llvm/lib/MC/MCFragment.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -431,7 +431,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { else OS << " unfused branch)"; OS << "\n "; OS << " BoundarySize:" << BF->getAlignment().value(); OS << " BoundarySize:" << BF->getAlignment().value() << " Size:" << BF->getSize(); break; } case MCFragment::FT_SymbolId: { Loading
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -466,7 +466,7 @@ void X86AsmBackend::alignBranchesEnd(MCObjectStreamer &OS, const MCInst &Inst) { if (!needAlign(OS)) return; // If the branch is emitted into a MCRelaxableFragment, we can determine the // size of the branch easily in during the process of layout. When the // size of the branch easily in MCAssembler::relaxBoundaryAlign. 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 Loading