forked from OSchip/llvm-project
Temporarily Revert [X86] Not track size of the boudaryalign fragment during the layout
Summary: This reverts commit 2ac19feb15
.
This commit causes some test cases to run fail when branch is aligned.
This commit is contained in:
parent
ff9bc0c091
commit
af57b139a0
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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…
Reference in New Issue