summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCCodePadder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCCodePadder.cpp')
-rw-r--r--llvm/lib/MC/MCCodePadder.cpp370
1 files changed, 0 insertions, 370 deletions
diff --git a/llvm/lib/MC/MCCodePadder.cpp b/llvm/lib/MC/MCCodePadder.cpp
deleted file mode 100644
index 27a62f95a52..00000000000
--- a/llvm/lib/MC/MCCodePadder.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-//===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#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 : CodePaddingPolicies)
- delete Policy;
-}
-
-bool MCCodePadder::addPolicy(MCCodePaddingPolicy *Policy) {
- assert(Policy && "Policy must be valid");
- return CodePaddingPolicies.insert(Policy).second;
-}
-
-void MCCodePadder::handleBasicBlockStart(MCObjectStreamer *OS,
- const MCCodePaddingContext &Context) {
- assert(OS != nullptr && "OS must be valid");
- assert(this->OS == nullptr && "Still handling another basic block");
- this->OS = OS;
-
- ArePoliciesActive = usePoliciesForBasicBlock(Context);
-
- bool InsertionPoint = basicBlockRequiresInsertionPoint(Context);
- 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(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Context](uint64_t Mask,
- const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->basicBlockRequiresPaddingFragment(Context)
- ? (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::handleBasicBlockEnd(const MCCodePaddingContext &Context) {
- assert(this->OS != nullptr && "Not handling a basic block");
- OS = nullptr;
-}
-
-void MCCodePadder::handleInstructionBegin(const MCInst &Inst) {
- if (!OS)
- return; // instruction was emitted outside a function
-
- assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
- "instruction while still "
- "handling another instruction");
-
- bool InsertionPoint = instructionRequiresInsertionPoint(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(
- CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
- MCPaddingFragment::PFK_None,
- [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
- return Policy->instructionRequiresPaddingFragment(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
- if (CurrHandledInstFragment == nullptr)
- return;
-
- 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) {
- auto 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 : CodePaddingPolicies) {
- 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) {
- auto 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 : CodePaddingPolicies)
- 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) {
- 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(
- CodePaddingPolicies.begin(), CodePaddingPolicies.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;
-}
OpenPOWER on IntegriCloud