Commit af57b139 authored by Shengchen Kan's avatar Shengchen Kan
Browse files

Temporarily Revert [X86] Not track size of the boudaryalign fragment during the layout

Summary: This reverts commit 2ac19feb.
This commit causes some test cases to run fail when branch is aligned.
parent ff9bc0c0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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; }

+70 −57
Original line number Diff line number Diff line
@@ -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:
+2 −1
Original line number Diff line number Diff line
@@ -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: {
+1 −1
Original line number Diff line number Diff line
@@ -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