[PATCH] D34393: Adding code padding for performance stability - infrastructure

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 20 08:39:52 PDT 2017


Should we expose this to the .s?

That would make it easy to test codegen because you would just need to
check for things like .pad_bb_begin.

It would make it easier to test the layout as you could use a simple .s
file for that.

Cheers,
Rafael

Omer Paparo Bivas via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> writes:

> opaparo created this revision.
> Herald added subscribers: javed.absar, mgorny.
>
> Implementation of padding code with nop instructions in key places that will cause performance improvement.
> The implementation is such that the adding of the nops is done in the Assembler after the layout is done and all IPs and alignments are known.
> The patch is the result of this RFC: http://lists.llvm.org/pipermail/llvm-dev/2016-November/107223.html
> This is the first patch of the implemented solution, and contains only the infrastructure needed for this change (this by itself is a NFC).
>
>
> Repository:
>   rL LLVM
>
> https://reviews.llvm.org/D34393
>
> Files:
>   include/llvm/MC/MCAsmBackend.h
>   include/llvm/MC/MCAssembler.h
>   include/llvm/MC/MCCodePadder.h
>   include/llvm/MC/MCFragment.h
>   include/llvm/MC/MCObjectStreamer.h
>   include/llvm/MC/MCStreamer.h
>   include\llvm\MC\MCCodePadder.h
>   lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>   lib/MC/CMakeLists.txt
>   lib/MC/MCAsmBackend.cpp
>   lib/MC/MCAssembler.cpp
>   lib/MC/MCCodePadder.cpp
>   lib/MC/MCFragment.cpp
>   lib/MC/MCObjectStreamer.cpp
>   lib\MC\MCCodePadder.cpp
>   test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll
>
> Index: test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll
> ===================================================================
> --- test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll
> +++ test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll
> @@ -36,7 +36,9 @@
>  ; HOTNESS-NOT: Executing Pass
>  ; HOTNESS: block-frequency: empty_func
>  ; HOTNESS-NOT: Executing Pass
> -; HOTNESS: Executing Pass 'AArch64 Assembly Printer'
> +; HOTNESS: Executing Pass 'MachineDominator Tree Construction'
> +; HOTNESS-NEXT: Executing Pass 'Machine Natural Loop Construction'
> +; HOTNESS-NEXT: Executing Pass 'AArch64 Assembly Printer'
>  
>  ; HOTNESS: arm64-summary-remarks.ll:5:0: 1 instructions in function (hotness: 33)
>  
> @@ -45,6 +47,8 @@
>  ; NO_HOTNESS-NEXT:  Freeing Pass 'Implement the 'patchable-function' attribute'
>  ; NO_HOTNESS-NEXT: Executing Pass 'Lazy Machine Block Frequency Analysis'
>  ; NO_HOTNESS-NEXT: Executing Pass 'Machine Optimization Remark Emitter'
> +; NO_HOTNESS-NEXT: Executing Pass 'MachineDominator Tree Construction'
> +; NO_HOTNESS-NEXT: Executing Pass 'Machine Natural Loop Construction'
>  ; NO_HOTNESS-NEXT: Executing Pass 'AArch64 Assembly Printer'
>  
>  ; NO_HOTNESS: arm64-summary-remarks.ll:5:0: 1 instructions in function{{$}}
> Index: lib/MC/MCObjectStreamer.cpp
> ===================================================================
> --- lib/MC/MCObjectStreamer.cpp
> +++ lib/MC/MCObjectStreamer.cpp
> @@ -111,6 +111,16 @@
>    return F;
>  }
>  
> +MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() {
> +  MCPaddingFragment *F =
> +      dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment());
> +  if (!F) {
> +    F = new MCPaddingFragment();
> +    insert(F);
> +  }
> +  return F;
> +}
> +
>  void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
>    Assembler->registerSymbol(Sym);
>  }
> @@ -244,6 +254,13 @@
>  
>  void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
>                                         const MCSubtargetInfo &STI, bool) {
> +  getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst);
> +  EmitInstructionImpl(Inst, STI);
> +  getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst);
> +}
> +
> +void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
> +                                           const MCSubtargetInfo &STI) {
>    MCStreamer::EmitInstruction(Inst, STI);
>  
>    MCSection *Sec = getCurrentSectionOnly();
> @@ -461,6 +478,21 @@
>    insert(new MCOrgFragment(*Offset, Value, Loc));
>  }
>  
> +void MCObjectStreamer::EmitCodePaddingFunctionStart(const TargetMachine &TM,
> +                                                    const MachineFunction &MF,
> +                                                    const MachineLoopInfo &LI) {
> +  getAssembler().getBackend().handleCodePaddingFunctionStart(MF, this, TM, LI);
> +}
> +
> +void MCObjectStreamer::EmitCodePaddingFunctionEnd(const MachineFunction &MF) {
> +  getAssembler().getBackend().handleCodePaddingFunctionEnd(MF);
> +}
> +
> +void MCObjectStreamer::EmitCodePaddingBasicBlockStart(
> +    const MachineBasicBlock &MBB) {
> +  getAssembler().getBackend().handleCodePaddingBasicBlockStart(MBB);
> +}
> +
>  // Associate DTPRel32 fixup with data and resize data area
>  void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
>    MCDataFragment *DF = getOrCreateDataFragment();
> Index: lib/MC/MCFragment.cpp
> ===================================================================
> --- lib/MC/MCFragment.cpp
> +++ lib/MC/MCFragment.cpp
> @@ -278,6 +278,9 @@
>      case FT_LEB:
>        delete cast<MCLEBFragment>(this);
>        return;
> +    case FT_Padding:
> +      delete cast<MCPaddingFragment>(this);
> +      return;
>      case FT_SafeSEH:
>        delete cast<MCSafeSEHFragment>(this);
>        return;
> @@ -322,6 +325,7 @@
>    case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
>    case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
>    case MCFragment::FT_LEB:   OS << "MCLEBFragment"; break;
> +  case MCFragment::FT_Padding: OS << "MCPaddingFragment"; break;
>    case MCFragment::FT_SafeSEH:    OS << "MCSafeSEHFragment"; break;
>    case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
>    case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
> @@ -417,6 +421,19 @@
>      OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
>      break;
>    }
> +  case MCFragment::FT_Padding: {
> +    const MCPaddingFragment *F = cast<MCPaddingFragment>(this);
> +    OS << "\n       ";
> +    OS << " PaddingPoliciesMask:" << F->getPaddingPoliciesMask()
> +       << " IsInsertionPoint:" << F->isInsertionPoint()
> +       << " Size:" << F->getSize();
> +    OS << "\n       ";
> +    OS << " Inst:";
> +    F->getInst().dump_pretty(OS);
> +    OS << " InstSize:" << F->getInstSize();
> +    OS << "\n       ";
> +    break;
> +  }
>    case MCFragment::FT_SafeSEH: {
>      const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(this);
>      OS << "\n       ";
> Index: lib/MC/MCCodePadder.cpp
> ===================================================================
> --- lib/MC/MCCodePadder.cpp
> +++ lib/MC/MCCodePadder.cpp
> @@ -0,0 +1,420 @@
> +//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/MC/MCAsmLayout.h"
> +#include "llvm/MC/MCCodePadder.h"
> +#include "llvm/MC/MCObjectStreamer.h"
> +#include <algorithm>
> +#include <limits>
> +#include <numeric>
> +
> +using namespace llvm;
> +
> +//---------------------------------------------------------------------------
> +// MCCodePadder
> +//
> +
> +MCCodePadder::~MCCodePadder() {
> +  for (auto *Policy : PaddingPolicies)
> +    delete Policy;
> +}
> +
> +bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) {
> +  assert(Policy && "Policy must be valid");
> +  return PaddingPolicies.insert(Policy).second;
> +}
> +
> +void MCCodePadder::unsealSection(MCSection *Sec) {
> +  // remove Sec's fragment from FragmentToJurisdiction
> +  for (auto It1 = FragmentToJurisdiction.begin();
> +       It1 != FragmentToJurisdiction.end();) {
> +    if (It1->first->getParent() == Sec)
> +      It1 = FragmentToJurisdiction.erase(It1);
> +    else
> +      ++It1;
> +  }
> +  // remove Sec's fragment from FragmentToMaxWindowSize
> +  for (auto It2 = FragmentToMaxWindowSize.begin();
> +       It2 != FragmentToMaxWindowSize.end();) {
> +    if (It2->first->getParent() == Sec)
> +      It2 = FragmentToMaxWindowSize.erase(It2);
> +    else
> +      ++It2;
> +  }
> +  SealedSections.erase(Sec);
> +}
> +
> +void MCCodePadder::handleFunctionStart(const MachineFunction &MF,
> +                                       MCObjectStreamer *OS,
> +                                       const TargetMachine &TM,
> +                                       const MachineLoopInfo &LI) {
> +  assert(OS != nullptr && "OS must be valid");
> +  // If a section was previously marked as sealed, we did not expect it to
> +  // change. If a function is being written to it, its changing. If we don't do
> +  // anything, some of the data we've got will be out of date (e.g. the
> +  // jurisdiction in FragmentToJurisdiction), so we must reset all of that out
> +  // of date data.
> +  if (SealedSections.find(OS->getCurrentSectionOnly()) != SealedSections.end())
> +    unsealSection(OS->getCurrentSectionOnly());
> +  this->OS = OS;
> +  this->LI = &LI;
> +}
> +
> +void MCCodePadder::handleFunctionEnd(const MachineFunction &MF) {
> +  this->OS = nullptr;
> +  this->LI = nullptr;
> +}
> +
> +void MCCodePadder::handleBasicBlockStart(const MachineBasicBlock &MBB) {
> +  assert(OS != nullptr &&
> +         "A call to handleFunctionStart with valid parameters must be made "
> +         "before a call to handleBasicBlockStart");
> +  assert(
> +      SealedSections.find(OS->getCurrentSectionOnly()) ==
> +          SealedSections.end() &&
> +      "Can't call handleBasicBlockStart after fragments creation is finished");
> +
> +  bool InsertionPoint = requiresInsertionPoint(MBB);
> +  assert((!InsertionPoint ||
> +          OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
> +         "Cannot insert padding nops right after an alignment fragment as it "
> +         "will ruin the alignment");
> +
> +  uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
> +  if (ArePoliciesActive) {
> +    PoliciesMask = std::accumulate(
> +        PaddingPolicies.begin(), PaddingPolicies.end(),
> +        MCPaddingFragment::PFK_None,
> +        [&MBB](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
> +          return Policy->requiresPaddingFragment(MBB)
> +                     ? (Mask | Policy->getKindMask())
> +                     : Mask;
> +        });
> +  }
> +
> +  if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) {
> +    MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment();
> +    if (InsertionPoint)
> +      PaddingFragment->setAsInsertionPoint();
> +    PaddingFragment->setPaddingPoliciesMask(
> +        PaddingFragment->getPaddingPoliciesMask() | PoliciesMask);
> +  }
> +}
> +
> +void MCCodePadder::handleInstructionBegin(const MCInst &Inst) {
> +  if (!OS)
> +    return; // instruction was emitted outside a function
> +  assert(
> +      SealedSections.find(OS->getCurrentSectionOnly()) ==
> +          SealedSections.end() &&
> +      "Can't call handleInstructionBegin after fragments creation is finished");
> +
> +  assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
> +                                               "instruction while still "
> +                                               "handling another instruction");
> +
> +  bool InsertionPoint = requiresInsertionPoint(Inst);
> +  assert((!InsertionPoint ||
> +          OS->getCurrentFragment()->getKind() != MCFragment::FT_Align) &&
> +         "Cannot insert padding nops right after an alignment fragment as it "
> +         "will ruin the alignment");
> +
> +  uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
> +  if (ArePoliciesActive) {
> +    PoliciesMask = std::accumulate(
> +        PaddingPolicies.begin(), PaddingPolicies.end(),
> +        MCPaddingFragment::PFK_None,
> +        [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
> +          return Policy->requiresPaddingFragment(Inst)
> +                     ? (Mask | Policy->getKindMask())
> +                     : Mask;
> +        });
> +  }
> +  MCFragment *CurrFragment = OS->getCurrentFragment();
> +  // CurrFragment can be a previously created MCPaddingFragment. If so, let's
> +  // update it with the information we have, such as the instruction that it
> +  // should point to.
> +  bool needToUpdateCurrFragment =
> +      CurrFragment != nullptr &&
> +      CurrFragment->getKind() == MCFragment::FT_Padding;
> +  if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None ||
> +      needToUpdateCurrFragment) {
> +    // temporarily holding the fragment as CurrHandledInstFragment, to be
> +    // updated after the instruction will be written
> +    CurrHandledInstFragment = OS->getOrCreatePaddingFragment();
> +    if (InsertionPoint)
> +      CurrHandledInstFragment->setAsInsertionPoint();
> +    CurrHandledInstFragment->setPaddingPoliciesMask(
> +        CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask);
> +  }
> +}
> +
> +void MCCodePadder::handleInstructionEnd(const MCInst &Inst) {
> +  if (!OS)
> +    return; // instruction was emitted outside a function
> +  assert(
> +      SealedSections.find(OS->getCurrentSectionOnly()) ==
> +          SealedSections.end() &&
> +      "Can't call handleInstructionEnd after fragments creation is finished");
> +  if (CurrHandledInstFragment == nullptr)
> +    return;
> +
> +  if (ArePoliciesActive) {
> +    MCFragment *InstFragment = OS->getCurrentFragment();
> +    if (MCDataFragment *InstDataFragment =
> +            dyn_cast_or_null<MCDataFragment>(InstFragment))
> +      // Inst is a fixed size instruction and was encoded into a MCDataFragment.
> +      // Let the fragment hold it and its size. Its size is the current size of
> +      // the data fragment, as the padding fragment was inserted right before it
> +      // and nothing was written yet except Inst
> +      CurrHandledInstFragment->setInstAndInstSize(
> +          Inst, InstDataFragment->getContents().size());
> +    else if (MCRelaxableFragment *InstRelaxableFragment =
> +                 dyn_cast_or_null<MCRelaxableFragment>(InstFragment))
> +      // Inst may be relaxed and its size may vary.
> +      // Let the fragment hold the instruction and the MCRelaxableFragment
> +      // that's holding it.
> +      CurrHandledInstFragment->setInstAndInstFragment(Inst,
> +                                                      InstRelaxableFragment);
> +    else
> +      llvm_unreachable("After encoding an instruction current fragment must be "
> +                       "either a MCDataFragment or a MCRelaxableFragment");
> +  }
> +
> +  CurrHandledInstFragment = nullptr;
> +}
> +
> +MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment,
> +                                         MCAsmLayout &Layout) {
> +  std::unordered_map<MCPaddingFragment *, MCPFRange>::iterator
> +      JurisdictionLocation = FragmentToJurisdiction.find(Fragment);
> +  if (JurisdictionLocation != FragmentToJurisdiction.end())
> +    return JurisdictionLocation->second;
> +
> +  MCPFRange Jurisdiction;
> +
> +  // Forward scanning the fragments in this section, starting from the given
> +  // fragments, and adding relevant MCPaddingFragments to the Jurisdiction
> +  for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr;
> +       CurrFragment = CurrFragment->getNextNode()) {
> +
> +    MCPaddingFragment *CurrPaddingFragment =
> +        dyn_cast<MCPaddingFragment>(CurrFragment);
> +    if (CurrPaddingFragment == nullptr)
> +      continue;
> +
> +    if (CurrPaddingFragment != Fragment &&
> +        CurrPaddingFragment->isInsertionPoint())
> +      // Found next insertion point Fragment. From now on it's its jurisdiction.
> +      break;
> +    for (const auto *Policy : PaddingPolicies) {
> +      if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) {
> +        Jurisdiction.push_back(CurrPaddingFragment);
> +        break;
> +      }
> +    }
> +  }
> +
> +  auto InsertionResult =
> +      FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction));
> +  assert(InsertionResult.second &&
> +         "Insertion to FragmentToJurisdiction failed");
> +  return InsertionResult.first->second;
> +}
> +
> +uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment,
> +                                        MCAsmLayout &Layout) {
> +  std::unordered_map<MCPaddingFragment *, uint64_t>::iterator
> +      MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment);
> +  if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end())
> +    return MaxFragmentSizeLocation->second;
> +
> +  MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
> +  uint64_t JurisdictionMask = MCPaddingFragment::PFK_None;
> +  for (const auto *Protege : Jurisdiction)
> +    JurisdictionMask |= Protege->getPaddingPoliciesMask();
> +
> +  uint64_t MaxFragmentSize = UINT64_C(0);
> +  for (const auto *Policy : PaddingPolicies)
> +    if ((JurisdictionMask & Policy->getKindMask()) !=
> +        MCPaddingFragment::PFK_None)
> +      MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize());
> +
> +  auto InsertionResult =
> +      FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize));
> +  assert(InsertionResult.second &&
> +         "Insertion to FragmentToMaxWindowSize failed");
> +  return InsertionResult.first->second;
> +}
> +
> +bool MCCodePadder::relaxFragment(MCPaddingFragment *Fragment,
> +                                 MCAsmLayout &Layout) {
> +  SealedSections.insert(Fragment->getParent());
> +  if (!Fragment->isInsertionPoint())
> +    return false;
> +  uint64_t OldSize = Fragment->getSize();
> +
> +  uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout);
> +  if (MaxWindowSize == UINT64_C(0))
> +    return false;
> +  assert(isPowerOf2_64(MaxWindowSize) &&
> +         "MaxWindowSize must be an integer power of 2");
> +  uint64_t SectionAlignment = Fragment->getParent()->getAlignment();
> +  assert(isPowerOf2_64(SectionAlignment) &&
> +         "SectionAlignment must be an integer power of 2");
> +
> +  MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
> +  uint64_t OptimalSize = UINT64_C(0);
> +  double OptimalWeight = std::numeric_limits<double>::max();
> +  uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1);
> +  for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) {
> +    Fragment->setSize(Size);
> +    Layout.invalidateFragmentsFrom(Fragment);
> +    double SizeWeight = 0.0;
> +    // The section is guaranteed to be aligned to SectionAlignment, but that
> +    // doesn't guarantee the exact section offset w.r.t. the policies window
> +    // size.
> +    // As a concrete example, the section could be aligned to 16B, but a
> +    // policy's window size can be 32B. That means that the section actual start
> +    // address can either be 0mod32 or 16mod32. The said policy will act
> +    // differently for each case, so we need to take both into consideration.
> +    for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize;
> +         Offset += SectionAlignment) {
> +      double OffsetWeight = std::accumulate(
> +          PaddingPolicies.begin(), PaddingPolicies.end(), 0.0,
> +          [&Jurisdiction, &Offset, &Layout](
> +              double Weight, const MCCodePaddingPolicy *Policy) -> double {
> +            double PolicyWeight =
> +                Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout);
> +            assert(PolicyWeight >= 0.0 && "A penalty weight must be positive");
> +            return Weight + PolicyWeight;
> +          });
> +      SizeWeight = std::max(SizeWeight, OffsetWeight);
> +    }
> +    if (SizeWeight < OptimalWeight) {
> +      OptimalWeight = SizeWeight;
> +      OptimalSize = Size;
> +    }
> +    if (OptimalWeight == 0.0)
> +      break;
> +  }
> +
> +  Fragment->setSize(OptimalSize);
> +  Layout.invalidateFragmentsFrom(Fragment);
> +  return OldSize != OptimalSize;
> +}
> +
> +//---------------------------------------------------------------------------
> +// MCCodePaddingPolicy
> +//
> +
> +uint64_t MCCodePaddingPolicy::getNextFragmentOffset(const MCFragment *Fragment,
> +                                                    const MCAsmLayout &Layout) {
> +  assert(Fragment != nullptr && "Fragment cannot be null");
> +  MCFragment const *NextFragment = Fragment->getNextNode();
> +  return NextFragment == nullptr
> +             ? Layout.getSectionAddressSize(Fragment->getParent())
> +             : Layout.getFragmentOffset(NextFragment);
> +}
> +
> +uint64_t
> +MCCodePaddingPolicy::getFragmentInstByte(const MCPaddingFragment *Fragment,
> +                                         MCAsmLayout &Layout) const {
> +  uint64_t InstByte = getNextFragmentOffset(Fragment, Layout);
> +  if (InstByteIsLastByte)
> +    InstByte += Fragment->getInstSize() - UINT64_C(1);
> +  return InstByte;
> +}
> +
> +uint64_t
> +MCCodePaddingPolicy::computeWindowEndAddress(const MCPaddingFragment *Fragment,
> +                                             uint64_t Offset,
> +                                             MCAsmLayout &Layout) const {
> +  uint64_t InstByte = getFragmentInstByte(Fragment, Layout);
> +  return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset;
> +}
> +
> +double MCCodePaddingPolicy::computeRangePenaltyWeight(
> +    const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const {
> +
> +  SmallVector<MCPFRange, 8> Windows;
> +  SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end();
> +  for (const MCPaddingFragment *Fragment : Range) {
> +    if (!Fragment->hasPaddingPolicy(getKindMask()))
> +      continue;
> +    uint64_t FragmentWindowEndAddress =
> +        computeWindowEndAddress(Fragment, Offset, Layout);
> +    if (CurrWindowLocation == Windows.end() ||
> +        FragmentWindowEndAddress !=
> +            computeWindowEndAddress(*CurrWindowLocation->begin(), Offset,
> +                                    Layout)) {
> +      // next window is starting
> +      Windows.push_back(MCPFRange());
> +      CurrWindowLocation = Windows.end() - 1;
> +    }
> +    CurrWindowLocation->push_back(Fragment);
> +  }
> +
> +  if (Windows.empty())
> +    return 0.0;
> +
> +  double RangeWeight = 0.0;
> +  SmallVector<MCPFRange, 8>::iterator I = Windows.begin();
> +  RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout);
> +  ++I;
> +  RangeWeight += std::accumulate(
> +      I, Windows.end(), 0.0,
> +      [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double {
> +        return Weight += computeWindowPenaltyWeight(Window, Offset, Layout);
> +      });
> +  return RangeWeight;
> +}
> +
> +double MCCodePaddingPolicy::computeFirstWindowPenaltyWeight(
> +    const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const {
> +  if (Window.empty())
> +    return 0.0;
> +  uint64_t WindowEndAddress =
> +      computeWindowEndAddress(*Window.begin(), Offset, Layout);
> +
> +  MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the
> +								 // same window as the fragments in the given
> +								 // window but their penalty weight should not
> +								 // be added
> +  for (const MCFragment *Fragment = (*Window.begin())->getPrevNode();
> +       Fragment != nullptr; Fragment = Fragment->getPrevNode()) {
> +    const MCPaddingFragment *PaddingNopFragment =
> +        dyn_cast<MCPaddingFragment>(Fragment);
> +    if (PaddingNopFragment == nullptr ||
> +        !PaddingNopFragment->hasPaddingPolicy(getKindMask()))
> +      continue;
> +    if (WindowEndAddress !=
> +        computeWindowEndAddress(PaddingNopFragment, Offset, Layout))
> +      break;
> +
> +    FullWindowFirstPart.push_back(PaddingNopFragment);
> +  }
> +
> +  std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end());
> +  double FullWindowFirstPartWeight =
> +      computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout);
> +
> +  MCPFRange FullWindow(
> +      FullWindowFirstPart); // will hold all the fragments that are in the
> +                            // same window as the fragments in the given
> +                            // window, whether their weight should be added
> +                            // or not
> +  FullWindow.append(Window.begin(), Window.end());
> +  double FullWindowWeight =
> +      computeWindowPenaltyWeight(FullWindow, Offset, Layout);
> +
> +  assert(FullWindowWeight >= FullWindowFirstPartWeight &&
> +         "More fragments necessarily means bigger weight");
> +  return FullWindowWeight - FullWindowFirstPartWeight;
> +}
> Index: lib/MC/MCAssembler.cpp
> ===================================================================
> --- lib/MC/MCAssembler.cpp
> +++ lib/MC/MCAssembler.cpp
> @@ -68,6 +68,10 @@
>  STATISTIC(ObjectBytes, "Number of emitted object file bytes");
>  STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
>  STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
> +STATISTIC(PaddingFragmentsRelaxations,
> +          "Number of Padding Fragments relaxations");
> +STATISTIC(PaddingFragmentsBytes,
> +          "Total size of all padding from adding Fragments");
>  
>  } // end namespace stats
>  } // end anonymous namespace
> @@ -275,6 +279,9 @@
>    case MCFragment::FT_LEB:
>      return cast<MCLEBFragment>(F).getContents().size();
>  
> +  case MCFragment::FT_Padding:
> +    return cast<MCPaddingFragment>(F).getSize();
> +
>    case MCFragment::FT_SafeSEH:
>      return 4;
>  
> @@ -541,6 +548,13 @@
>      break;
>    }
>  
> +  case MCFragment::FT_Padding: {
> +    if (!Asm.getBackend().writeNopData(FragmentSize, OW))
> +      report_fatal_error("unable to write nop sequence of " +
> +                         Twine(FragmentSize) + " bytes");
> +    break;
> +  }
> +
>    case MCFragment::FT_SafeSEH: {
>      const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F);
>      OW->write32(SF.getSymbol()->getIndex());
> @@ -814,6 +828,19 @@
>    return true;
>  }
>  
> +bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
> +                                       MCPaddingFragment &PF) {
> +  uint64_t OldSize = PF.getSize();
> +  if (!getBackend().relaxFragment(&PF, Layout))
> +    return false;
> +  uint64_t NewSize = PF.getSize();
> +
> +  ++stats::PaddingFragmentsRelaxations;
> +  stats::PaddingFragmentsBytes += NewSize;
> +  stats::PaddingFragmentsBytes -= OldSize;
> +  return true;
> +}
> +
>  bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
>    uint64_t OldSize = LF.getContents().size();
>    int64_t Value;
> @@ -908,6 +935,11 @@
>      case MCFragment::FT_LEB:
>        RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
>        break;
> +
> +    case MCFragment::FT_Padding:
> +      RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I));
> +      break;
> +
>      case MCFragment::FT_CVInlineLines:
>        RelaxedFrag =
>            relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
> Index: lib/MC/MCAsmBackend.cpp
> ===================================================================
> --- lib/MC/MCAsmBackend.cpp
> +++ lib/MC/MCAsmBackend.cpp
> @@ -10,6 +10,7 @@
>  #include "llvm/MC/MCAsmBackend.h"
>  #include "llvm/ADT/None.h"
>  #include "llvm/ADT/STLExtras.h"
> +#include "llvm/MC/MCCodePadder.h"
>  #include "llvm/MC/MCFixupKindInfo.h"
>  #include <cassert>
>  #include <cstddef>
> @@ -17,10 +18,18 @@
>  
>  using namespace llvm;
>  
> -MCAsmBackend::MCAsmBackend() = default;
> +MCAsmBackend::MCAsmBackend() : CodePadder(nullptr) {}
>  
> -MCAsmBackend::~MCAsmBackend() = default;
> +MCAsmBackend::~MCAsmBackend() { delete CodePadder; }
>  
> +MCCodePadder *MCAsmBackend::getCodePadder() {
> +  if (CodePadder == nullptr)
> +    CodePadder = createCodePadder();
> +  return CodePadder;
> +}
> +
> +MCCodePadder *MCAsmBackend::createCodePadder() { return new MCCodePadder(); }
> +
>  Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
>    return None;
>  }
> @@ -59,3 +68,31 @@
>      return true;
>    return fixupNeedsRelaxation(Fixup, Value, DF, Layout);
>  }
> +
> +void MCAsmBackend::handleCodePaddingFunctionStart(const MachineFunction &MF,
> +                                                  MCObjectStreamer *OS,
> +                                                  const TargetMachine &TM,
> +                                                  const MachineLoopInfo &LI) {
> +  getCodePadder()->handleFunctionStart(MF, OS, TM, LI);
> +}
> +
> +void MCAsmBackend::handleCodePaddingFunctionEnd(const MachineFunction &MF) {
> +  getCodePadder()->handleFunctionEnd(MF);
> +}
> +
> +void MCAsmBackend::handleCodePaddingBasicBlockStart(
> +    const MachineBasicBlock &MBB) {
> +  getCodePadder()->handleBasicBlockStart(MBB);
> +}
> +
> +void MCAsmBackend::handleCodePaddingInstructionBegin(const MCInst &Inst) {
> +  getCodePadder()->handleInstructionBegin(Inst);
> +}
> +
> +void MCAsmBackend::handleCodePaddingInstructionEnd(const MCInst &Inst) {
> +  getCodePadder()->handleInstructionEnd(Inst);
> +}
> +
> +bool MCAsmBackend::relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout) {
> +  return getCodePadder()->relaxFragment(PF, Layout);
> +}
> \ No newline at end of file
> Index: lib/MC/CMakeLists.txt
> ===================================================================
> --- lib/MC/CMakeLists.txt
> +++ lib/MC/CMakeLists.txt
> @@ -10,6 +10,7 @@
>    MCAsmStreamer.cpp
>    MCAssembler.cpp
>    MCCodeEmitter.cpp
> +  MCCodePadder.cpp
>    MCCodeView.cpp
>    MCContext.cpp
>    MCDwarf.cpp
> Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> ===================================================================
> --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> @@ -221,8 +221,7 @@
>    AU.addRequired<MachineModuleInfo>();
>    AU.addRequired<MachineOptimizationRemarkEmitterPass>();
>    AU.addRequired<GCModuleInfo>();
> -  if (isVerbose())
> -    AU.addRequired<MachineLoopInfo>();
> +  AU.addRequired<MachineLoopInfo>();
>  }
>  
>  bool AsmPrinter::doInitialization(Module &M) {
> @@ -966,6 +965,7 @@
>  /// function.
>  void AsmPrinter::EmitFunctionBody() {
>    EmitFunctionHeader();
> +  OutStreamer->EmitCodePaddingFunctionStart(TM, *MF, *LI);
>  
>    // Emit target-specific gunk before the function body.
>    EmitFunctionBodyStart();
> @@ -1123,6 +1123,8 @@
>      HI.Handler->endFunction(MF);
>    }
>  
> +  OutStreamer->EmitCodePaddingFunctionEnd(*MF);
> +
>    if (isVerbose())
>      OutStreamer->GetCommentOS() << "-- End function\n";
>  
> @@ -1418,8 +1420,7 @@
>    }
>  
>    ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
> -  if (isVerbose())
> -    LI = &getAnalysis<MachineLoopInfo>();
> +  LI = &getAnalysis<MachineLoopInfo>();
>  
>    const TargetSubtargetInfo &STI = MF.getSubtarget();
>    EnablePrintSchedInfo = PrintSchedule.getNumOccurrences()
> @@ -2616,6 +2617,7 @@
>    // Emit an alignment directive for this block, if needed.
>    if (unsigned Align = MBB.getAlignment())
>      EmitAlignment(Align);
> +  OutStreamer->EmitCodePaddingBasicBlockStart(MBB);
>  
>    // If the block has its address taken, emit any labels that were used to
>    // reference the block.  It is possible that there is more than one label
> Index: include/llvm/MC/MCStreamer.h
> ===================================================================
> --- include/llvm/MC/MCStreamer.h
> +++ include/llvm/MC/MCStreamer.h
> @@ -35,6 +35,9 @@
>  
>  class AssemblerConstantPools;
>  class formatted_raw_ostream;
> +class MachineBasicBlock;
> +class MachineFunction;
> +class MachineLoopInfo;
>  class MCAsmBackend;
>  class MCCodeEmitter;
>  class MCContext;
> @@ -46,6 +49,7 @@
>  class MCSymbolRefExpr;
>  class MCSubtargetInfo;
>  class raw_ostream;
> +class TargetMachine;
>  class Twine;
>  
>  using MCSectionSubPair = std::pair<MCSection *, const MCExpr *>;
> @@ -705,6 +709,14 @@
>    virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
>                                   SMLoc Loc);
>  
> +  virtual void EmitCodePaddingFunctionStart(const TargetMachine &TM,
> +                                            const MachineFunction &MF,
> +                                            const MachineLoopInfo &LI) {}
> +
> +  virtual void EmitCodePaddingFunctionEnd(const MachineFunction &MF) {}
> +
> +  virtual void EmitCodePaddingBasicBlockStart(const MachineBasicBlock &MBB) {}
> +
>    /// @}
>  
>    /// \brief Switch to a new logical file.  This is used to implement the '.file
> Index: include/llvm/MC/MCObjectStreamer.h
> ===================================================================
> --- include/llvm/MC/MCObjectStreamer.h
> +++ include/llvm/MC/MCObjectStreamer.h
> @@ -16,6 +16,9 @@
>  #include "llvm/MC/MCStreamer.h"
>  
>  namespace llvm {
> +class MachineBasicBlock;
> +class MachineFunction;
> +class MachineLoopInfo;
>  class MCAssembler;
>  class MCCodeEmitter;
>  class MCSubtargetInfo;
> @@ -25,6 +28,7 @@
>  class MCAsmBackend;
>  class raw_ostream;
>  class raw_pwrite_stream;
> +class TargetMachine;
>  
>  /// \brief Streaming object file generation interface.
>  ///
> @@ -43,6 +47,7 @@
>    virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
>    void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
>    void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
> +  void EmitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
>  
>  protected:
>    MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
> @@ -71,6 +76,7 @@
>    /// Get a data fragment to write into, creating a new one if the current
>    /// fragment is not a data fragment.
>    MCDataFragment *getOrCreateDataFragment();
> +  MCPaddingFragment *getOrCreatePaddingFragment();
>  
>  protected:
>    bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
> @@ -116,6 +122,11 @@
>                           unsigned MaxBytesToEmit = 0) override;
>    void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
>                           SMLoc Loc) override;
> +  void EmitCodePaddingFunctionStart(const TargetMachine &TM,
> +                                    const MachineFunction &MF,
> +                                    const MachineLoopInfo &LI) override;
> +  void EmitCodePaddingFunctionEnd(const MachineFunction &MF) override;
> +  void EmitCodePaddingBasicBlockStart(const MachineBasicBlock &MBB) override;
>    void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
>                               unsigned Column, unsigned Flags,
>                               unsigned Isa, unsigned Discriminator,
> Index: include/llvm/MC/MCFragment.h
> ===================================================================
> --- include/llvm/MC/MCFragment.h
> +++ include/llvm/MC/MCFragment.h
> @@ -41,6 +41,7 @@
>      FT_Dwarf,
>      FT_DwarfFrame,
>      FT_LEB,
> +	FT_Padding,
>      FT_SafeSEH,
>      FT_CVInlineLines,
>      FT_CVDefRange,
> @@ -323,6 +324,93 @@
>    }
>  };
>  
> +class MCPaddingFragment : public MCFragment {
> +  /// A mask containing all the kinds relevant to this fragment. i.e. the i'th
> +  /// bit will be set iff kind i is relevant to this fragment.
> +  uint64_t PaddingPoliciesMask;
> +  /// A boolean indicating if this fragment will actually hold padding. If its
> +  /// value is false, then this fragment serves only as a placeholder,
> +  /// containing data to assist other insertion point in their decision making.
> +  bool IsInsertionPoint;
> +
> +  uint64_t Size;
> +
> +  typedef struct {
> +	bool IsInitialized;
> +    MCInst Inst;
> +    /// A boolean indicating whether the instruction pointed by this fragment is
> +    /// a fixed size instruction or a relaxable instruction held by a
> +    /// MCRelaxableFragment.
> +    bool IsImmutableSizedInst;
> +    union {
> +      /// If the instruction is a fixed size instruction, hold its size.
> +      size_t InstSize;
> +      /// Otherwise, hold a pointer to the MCRelaxableFragment holding it.
> +      MCRelaxableFragment *InstFragment;
> +    };
> +  } MCInstInfo;
> +  MCInstInfo InstInfo;
> +
> +public:
> +  static const uint64_t PFK_None = UINT64_C(0);
> +
> +  enum MCPaddingFragmentKind {
> +    // values 0-7 are reserved for future target independet values.
> +
> +    FirstTargetPerfNopFragmentKind = 8,
> +
> +    /// Limit range of target MCPerfNopFragment kinds to fit in uint64_t
> +    MaxTargetPerfNopFragmentKind = 63
> +  };
> +
> +  MCPaddingFragment(MCSection *Sec = nullptr)
> +      : MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None),
> +        IsInsertionPoint(false), Size(UINT64_C(0)),
> +        InstInfo({false, MCInst(), false, {0}}) {}
> +
> +  bool isInsertionPoint() const { return IsInsertionPoint; }
> +  void setAsInsertionPoint() { IsInsertionPoint = true; }
> +  uint64_t getPaddingPoliciesMask() const { return PaddingPoliciesMask; }
> +  void setPaddingPoliciesMask(uint64_t Value) { PaddingPoliciesMask = Value; }
> +  bool hasPaddingPolicy(uint64_t PolicyMask) const {
> +    assert(isPowerOf2_64(PolicyMask) &&
> +           "Policy mask must contain exactly one policy");
> +    return (getPaddingPoliciesMask() & PolicyMask) != PFK_None;
> +  }
> +  const MCInst &getInst() const {
> +    assert(isInstructionInitialized() && "Fragment has no instruction!");
> +    return InstInfo.Inst;
> +  }
> +  size_t getInstSize() const {
> +    assert(isInstructionInitialized() && "Fragment has no instruction!");
> +    if (InstInfo.IsImmutableSizedInst)
> +      return InstInfo.InstSize;
> +    assert(InstInfo.InstFragment != nullptr &&
> +           "Must have a valid InstFragment to retrieve InstSize from");
> +    return InstInfo.InstFragment->getContents().size();
> +  }
> +  void setInstAndInstSize(const MCInst &Inst, size_t InstSize) {
> +	InstInfo.IsInitialized = true;
> +    InstInfo.IsImmutableSizedInst = true;
> +    InstInfo.Inst = Inst;
> +    InstInfo.InstSize = InstSize;
> +  }
> +  void setInstAndInstFragment(const MCInst &Inst,
> +                              MCRelaxableFragment *InstFragment) {
> +    InstInfo.IsInitialized = true;
> +    InstInfo.IsImmutableSizedInst = false;
> +    InstInfo.Inst = Inst;
> +    InstInfo.InstFragment = InstFragment;
> +  }
> +  uint64_t getSize() const { return Size; }
> +  void setSize(uint64_t Value) { Size = Value; }
> +  bool isInstructionInitialized() const { return InstInfo.IsInitialized; }
> +
> +  static bool classof(const MCFragment *F) {
> +    return F->getKind() == MCFragment::FT_Padding;
> +  }
> +};
> +
>  class MCFillFragment : public MCFragment {
>    /// Value to use for filling bytes.
>    uint8_t Value;
> Index: include/llvm/MC/MCCodePadder.h
> ===================================================================
> --- include/llvm/MC/MCCodePadder.h
> +++ include/llvm/MC/MCCodePadder.h
> @@ -0,0 +1,246 @@
> +//===- llvm/MC/CodePadder.h - MC Code Padder --------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_MC_MCCODEPADDER_H
> +#define LLVM_MC_MCCODEPADDER_H
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include <unordered_map>
> +#include <unordered_set>
> +
> +namespace llvm {
> +
> +class MachineBasicBlock;
> +class MachineFunction;
> +class MachineLoopInfo;
> +class MCAsmLayout;
> +class MCCodePaddingPolicy;
> +class MCFragment;
> +class MCInst;
> +class MCObjectStreamer;
> +class MCPaddingFragment;
> +class MCSection;
> +class TargetMachine;
> +
> +typedef SmallVector<const MCPaddingFragment *, 8> MCPFRange;
> +
> +/// Target-independent base class incharge of all code padding decisions for a
> +/// target. During encoding it determines if and where MCPaddingFragments will
> +/// be located, as later on, when layout information is available, it determines
> +/// their sizes.
> +class MCCodePadder {
> +  MCCodePadder(const MCCodePadder &) = delete;
> +  void operator=(const MCCodePadder &) = delete;
> +
> +  /// All the supported MCCodePaddingPolicies.
> +  std::unordered_set<MCCodePaddingPolicy *> PaddingPolicies;
> +
> +  /// All the MCSections that are not expected to change, e.g. by adding or
> +  /// deleting MCFragments from them.
> +  std::unordered_set<MCSection *> SealedSections;
> +  /// Unseals a sealed section.
> +  void unsealSection(MCSection *Sec);
> +
> +  /// A pointer to the fragment of the instruction whose padding is currently
> +  /// done for.
> +  MCPaddingFragment *CurrHandledInstFragment;
> +
> +  /// A map holding the jurisdiction for each padding fragment. Key: padding
> +  /// fragment. Value: The fragment's jurisdiction. A jurisdiction is a vector
> +  /// of padding fragments whose conditions are being controlled by another
> +  /// fragment, the key fragment.
> +  std::unordered_map<MCPaddingFragment *, MCPFRange> FragmentToJurisdiction;
> +  MCPFRange &getJurisdiction(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
> +
> +  /// A map holding the maximal instruction window size relevant for a padding
> +  /// fragment.
> +  std::unordered_map<MCPaddingFragment *, uint64_t> FragmentToMaxWindowSize;
> +  uint64_t getMaxWindowSize(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
> +
> +protected:
> +  /// The current streamer, used to stream code padding.
> +  MCObjectStreamer *OS;
> +
> +  const MachineLoopInfo *LI;
> +
> +  /// Determines if the MCCodePaddingPolicies are active.
> +  bool ArePoliciesActive;
> +
> +  bool addPolicy(MCCodePaddingPolicy *Policy);
> +
> +  virtual bool requiresInsertionPoint(const MachineBasicBlock &MBB) {
> +    return false;
> +  }
> +
> +  virtual bool requiresInsertionPoint(const MCInst &Inst) { return false; }
> +
> +public:
> +  MCCodePadder()
> +      : CurrHandledInstFragment(nullptr), OS(nullptr), LI(nullptr),
> +        ArePoliciesActive(false) {}
> +  virtual ~MCCodePadder();
> +
> +  /// Handles all target related code padding when starting to write a new
> +  /// function to an object file.
> +  ///
> +  /// \param MF The function.
> +  /// \param OS The streamer used for writing the padding data and function.
> +  /// \param TM Target machine information.
> +  /// \param LI Loop info for the starting function.
> +  virtual void handleFunctionStart(const MachineFunction &MF,
> +                                   MCObjectStreamer *OS,
> +                                   const TargetMachine &TM,
> +                                   const MachineLoopInfo &LI);
> +  /// Handles all target related code padding cleanup when done writing a
> +  /// function to an object file.
> +  ///
> +  /// \param MF The function.
> +  virtual void handleFunctionEnd(const MachineFunction &MF);
> +  /// Handles all target related code padding when starting to write a new
> +  /// basic block to an object file.
> +  ///
> +  /// \param BB the basic block.
> +  virtual void handleBasicBlockStart(const MachineBasicBlock &MBB);
> +  /// Handles all target related code padding before writing a new instruction
> +  /// to an object file.
> +  ///
> +  /// \param Inst the instruction.
> +  void handleInstructionBegin(const MCInst &Inst);
> +  /// Handles all target related code padding after writing an instruction to an
> +  /// object file.
> +  ///
> +  /// \param Inst the instruction.
> +  void handleInstructionEnd(const MCInst &Inst);
> +
> +  /// Relaxes a fragment (changes the size of the padding) according to target
> +  /// requirements. The new size computation is done w.r.t a layout.
> +  ///
> +  /// \param Fragment The fragment to relax.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns true iff any relaxation occured.
> +  bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
> +};
> +
> +/// The base class for all padding policies, i.e. a rule or set of rules to pad
> +/// the generated code.
> +class MCCodePaddingPolicy {
> +  MCCodePaddingPolicy() = delete;
> +  MCCodePaddingPolicy(const MCCodePaddingPolicy &) = delete;
> +  void operator=(const MCCodePaddingPolicy &) = delete;
> +
> +protected:
> +  /// A mask holding the kind of this policy, i.e. only the i'th bit will be set
> +  /// where i is the kind number.
> +  const uint64_t KindMask;
> +  /// Instruction window size relevant to this policy.
> +  const uint64_t WindowSize;
> +  /// A boolean indicating which byte of the instruction determies its
> +  /// instruction window. If true - the last byte of the instructions, o.w. -
> +  /// the first byte of the instruction.
> +  const bool InstByteIsLastByte;
> +
> +  MCCodePaddingPolicy(uint64_t Kind, uint64_t WindowSize,
> +                      bool InstByteIsLastByte)
> +      : KindMask(UINT64_C(1) << Kind), WindowSize(WindowSize),
> +        InstByteIsLastByte(InstByteIsLastByte) {}
> +
> +  /// Computes and returns the offset of the consecutive fragment of a given
> +  /// fragment.
> +  ///
> +  /// \param Fragment The fragment whose consecutive offset will be computed.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns the offset of the consecutive fragment of \p Fragment.
> +  static uint64_t getNextFragmentOffset(const MCFragment *Fragment,
> +                                        const MCAsmLayout &Layout);
> +  /// Returns the instruction byte of an instruction pointed by a given
> +  /// MCPaddingFragment. An instruction byte is the address of the byte of an
> +  /// instruction which determines its instruction window.
> +  ///
> +  /// \param Fragment The fragment pointing to the instruction.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns the instruction byte of an instruction pointed by \p Fragment.
> +  uint64_t getFragmentInstByte(const MCPaddingFragment *Fragment,
> +                               MCAsmLayout &Layout) const;
> +  uint64_t computeWindowEndAddress(const MCPaddingFragment *Fragment,
> +                                   uint64_t Offset, MCAsmLayout &Layout) const;
> +
> +  /// Computes and returns the penalty weight of a first instruction window in a
> +  /// range. This requires a special function since the first window does not
> +  /// contain all the padding fragments in that window. It only contains all the
> +  /// padding fragments starting from the relevant insertion point.
> +  ///
> +  /// \param Window The first window.
> +  /// \param Offset The offset of the parent section relative to the beginning
> +  /// of the file, mod the window size.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns the penalty weight of a first instruction window in a range, \p
> +  /// Window.
> +  double computeFirstWindowPenaltyWeight(const MCPFRange &Window,
> +                                         uint64_t Offset,
> +                                         MCAsmLayout &Layout) const;
> +  /// Computes and returns the penalty caused by an instruction window.
> +  ///
> +  /// \param Window The instruction window.
> +  /// \param Offset The offset of the parent section relative to the beginning
> +  /// of the file, mod the window size.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns the penalty caused by \p Window.
> +  virtual double computeWindowPenaltyWeight(const MCPFRange &Window,
> +                                            uint64_t Offset,
> +                                            MCAsmLayout &Layout) const = 0;
> +
> +public:
> +  virtual ~MCCodePaddingPolicy() {}
> +
> +  /// Returns the kind mask of this policy -  A mask holding the kind of this
> +  /// policy, i.e. only the i'th bit will be set where i is the kind number.
> +  uint64_t getKindMask() const { return KindMask; }
> +  /// Returns the instruction window size relevant to this policy.
> +  uint64_t getWindowSize() const { return WindowSize; }
> +  /// Returns true if the last byte of an instruction determines its instruction
> +  /// window, or false if the first of an instruction determines it.
> +  bool isInstByteLastByte() const { return InstByteIsLastByte; }
> +
> +  /// Returns true iff this policy needs padding for a given basic block.
> +  ///
> +  /// \param MBB The given basic block.
> +  ///
> +  /// \returns true iff this policy needs padding for \p MBB.
> +  virtual bool requiresPaddingFragment(const MachineBasicBlock &MBB) const {
> +    return false;
> +  }
> +  /// Returns true iff this policy needs padding for a given instruction.
> +  ///
> +  /// \param Inst The given instruction.
> +  ///
> +  /// \returns true iff this policy needs padding for \p Inst.
> +  virtual bool requiresPaddingFragment(const MCInst &Inst) const {
> +    return false;
> +  }
> +  /// Computes and returns the penalty caused by a range of instruction windows.
> +  /// The weight is computed for each window separelty and then accumulated.
> +  ///
> +  /// \param Range The range.
> +  /// \param Offset The offset of the parent section relative to the beginning
> +  /// of the file, mod the window size.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns the penalty caused by \p Range.
> +  double computeRangePenaltyWeight(const MCPFRange &Range, uint64_t Offset,
> +                                   MCAsmLayout &Layout) const;
> +};
> +
> +} // namespace llvm
> +
> +#endif // LLVM_MC_MCCODEPADDER_H
> Index: include/llvm/MC/MCAssembler.h
> ===================================================================
> --- include/llvm/MC/MCAssembler.h
> +++ include/llvm/MC/MCAssembler.h
> @@ -183,6 +183,8 @@
>  
>    bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF);
>  
> +  bool relaxPaddingFragment(MCAsmLayout &Layout, MCPaddingFragment &PF);
> +
>    bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF);
>  
>    bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF);
> Index: include/llvm/MC/MCAsmBackend.h
> ===================================================================
> --- include/llvm/MC/MCAsmBackend.h
> +++ include/llvm/MC/MCAsmBackend.h
> @@ -19,22 +19,33 @@
>  
>  namespace llvm {
>  
> +class MachineBasicBlock;
> +class MachineFunction;
> +class MachineLoopInfo;
>  class MCAsmLayout;
>  class MCAssembler;
>  class MCCFIInstruction;
> +class MCCodePadder;
>  struct MCFixupKindInfo;
>  class MCFragment;
>  class MCInst;
> +class MCObjectStreamer;
>  class MCObjectWriter;
> +class MCPaddingFragment;
>  class MCRelaxableFragment;
>  class MCSubtargetInfo;
>  class MCValue;
>  class raw_pwrite_stream;
> +class TargetMachine;
>  
>  /// Generic interface to target specific assembler backends.
>  class MCAsmBackend {
> +  MCCodePadder *CodePadder;
> +  MCCodePadder *getCodePadder();
> +
>  protected: // Can only create subclasses.
>    MCAsmBackend();
> +  virtual MCCodePadder *createCodePadder();
>  
>  public:
>    MCAsmBackend(const MCAsmBackend &) = delete;
> @@ -134,6 +145,47 @@
>        generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
>      return 0;
>    }
> +
> +  /// Handles all target related code padding when starting to write a new
> +  /// function to an object file.
> +  ///
> +  /// \param MF The function.
> +  /// \param OS The streamer used for writing the padding data and function.
> +  /// \param TM Target machine information.
> +  /// \param LI Loop info for the starting function.
> +  void handleCodePaddingFunctionStart(const MachineFunction &MF,
> +                                      MCObjectStreamer *OS,
> +                                      const TargetMachine &TM,
> +                                      const MachineLoopInfo &LI);
> +  /// Handles all target related code padding cleanup when done writing a
> +  /// function to an object file.
> +  ///
> +  /// \param MF The function.
> +  void handleCodePaddingFunctionEnd(const MachineFunction &MF);
> +  /// Handles all target related code padding when starting to write a new
> +  /// basic block to an object file.
> +  ///
> +  /// \param BB the basic block.
> +  void handleCodePaddingBasicBlockStart(const MachineBasicBlock &MBB);
> +  /// Handles all target related code padding before writing a new instruction
> +  /// to an object file.
> +  ///
> +  /// \param Inst the instruction.
> +  void handleCodePaddingInstructionBegin(const MCInst &Inst);
> +  /// Handles all target related code padding after writing an instruction to an
> +  /// object file.
> +  ///
> +  /// \param Inst the instruction.
> +  void handleCodePaddingInstructionEnd(const MCInst &Inst);
> +
> +  /// Relaxes a fragment (changes the size of the padding) according to target
> +  /// requirements. The new size computation is done w.r.t a layout.
> +  ///
> +  /// \param Fragment The fragment to relax.
> +  /// \param Layout Code layout information.
> +  ///
> +  /// \returns true iff any relaxation occured.
> +  bool relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout);
>  };
>  
>  } // end namespace llvm
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list