LLVM  8.0.1
MCCodePadder.cpp
Go to the documentation of this file.
1 //===- MCCodePadder.cpp - Target MC Code Padder ---------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/MC/MCAsmLayout.h"
11 #include "llvm/MC/MCCodePadder.h"
13 #include <algorithm>
14 #include <limits>
15 #include <numeric>
16 
17 using namespace llvm;
18 
19 //---------------------------------------------------------------------------
20 // MCCodePadder
21 //
22 
24  for (auto *Policy : CodePaddingPolicies)
25  delete Policy;
26 }
27 
29  assert(Policy && "Policy must be valid");
30  return CodePaddingPolicies.insert(Policy).second;
31 }
32 
35  assert(OS != nullptr && "OS must be valid");
36  assert(this->OS == nullptr && "Still handling another basic block");
37  this->OS = OS;
38 
39  ArePoliciesActive = usePoliciesForBasicBlock(Context);
40 
41  bool InsertionPoint = basicBlockRequiresInsertionPoint(Context);
42  assert((!InsertionPoint ||
44  "Cannot insert padding nops right after an alignment fragment as it "
45  "will ruin the alignment");
46 
47  uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
48  if (ArePoliciesActive) {
49  PoliciesMask = std::accumulate(
50  CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
52  [&Context](uint64_t Mask,
53  const MCCodePaddingPolicy *Policy) -> uint64_t {
54  return Policy->basicBlockRequiresPaddingFragment(Context)
55  ? (Mask | Policy->getKindMask())
56  : Mask;
57  });
58  }
59 
60  if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None) {
61  MCPaddingFragment *PaddingFragment = OS->getOrCreatePaddingFragment();
62  if (InsertionPoint)
63  PaddingFragment->setAsInsertionPoint();
64  PaddingFragment->setPaddingPoliciesMask(
65  PaddingFragment->getPaddingPoliciesMask() | PoliciesMask);
66  }
67 }
68 
70  assert(this->OS != nullptr && "Not handling a basic block");
71  OS = nullptr;
72 }
73 
75  if (!OS)
76  return; // instruction was emitted outside a function
77 
78  assert(CurrHandledInstFragment == nullptr && "Can't start handling an "
79  "instruction while still "
80  "handling another instruction");
81 
82  bool InsertionPoint = instructionRequiresInsertionPoint(Inst);
83  assert((!InsertionPoint ||
85  "Cannot insert padding nops right after an alignment fragment as it "
86  "will ruin the alignment");
87 
88  uint64_t PoliciesMask = MCPaddingFragment::PFK_None;
89  if (ArePoliciesActive) {
90  PoliciesMask = std::accumulate(
91  CodePaddingPolicies.begin(), CodePaddingPolicies.end(),
93  [&Inst](uint64_t Mask, const MCCodePaddingPolicy *Policy) -> uint64_t {
94  return Policy->instructionRequiresPaddingFragment(Inst)
95  ? (Mask | Policy->getKindMask())
96  : Mask;
97  });
98  }
99  MCFragment *CurrFragment = OS->getCurrentFragment();
100  // CurrFragment can be a previously created MCPaddingFragment. If so, let's
101  // update it with the information we have, such as the instruction that it
102  // should point to.
103  bool needToUpdateCurrFragment =
104  CurrFragment != nullptr &&
105  CurrFragment->getKind() == MCFragment::FT_Padding;
106  if (InsertionPoint || PoliciesMask != MCPaddingFragment::PFK_None ||
107  needToUpdateCurrFragment) {
108  // temporarily holding the fragment as CurrHandledInstFragment, to be
109  // updated after the instruction will be written
110  CurrHandledInstFragment = OS->getOrCreatePaddingFragment();
111  if (InsertionPoint)
112  CurrHandledInstFragment->setAsInsertionPoint();
113  CurrHandledInstFragment->setPaddingPoliciesMask(
114  CurrHandledInstFragment->getPaddingPoliciesMask() | PoliciesMask);
115  }
116 }
117 
119  if (!OS)
120  return; // instruction was emitted outside a function
121  if (CurrHandledInstFragment == nullptr)
122  return;
123 
124  MCFragment *InstFragment = OS->getCurrentFragment();
125  if (MCDataFragment *InstDataFragment =
126  dyn_cast_or_null<MCDataFragment>(InstFragment))
127  // Inst is a fixed size instruction and was encoded into a MCDataFragment.
128  // Let the fragment hold it and its size. Its size is the current size of
129  // the data fragment, as the padding fragment was inserted right before it
130  // and nothing was written yet except Inst
131  CurrHandledInstFragment->setInstAndInstSize(
132  Inst, InstDataFragment->getContents().size());
133  else if (MCRelaxableFragment *InstRelaxableFragment =
134  dyn_cast_or_null<MCRelaxableFragment>(InstFragment))
135  // Inst may be relaxed and its size may vary.
136  // Let the fragment hold the instruction and the MCRelaxableFragment
137  // that's holding it.
138  CurrHandledInstFragment->setInstAndInstFragment(Inst,
139  InstRelaxableFragment);
140  else
141  llvm_unreachable("After encoding an instruction current fragment must be "
142  "either a MCDataFragment or a MCRelaxableFragment");
143 
144  CurrHandledInstFragment = nullptr;
145 }
146 
147 MCPFRange &MCCodePadder::getJurisdiction(MCPaddingFragment *Fragment,
148  MCAsmLayout &Layout) {
149  auto JurisdictionLocation = FragmentToJurisdiction.find(Fragment);
150  if (JurisdictionLocation != FragmentToJurisdiction.end())
151  return JurisdictionLocation->second;
152 
153  MCPFRange Jurisdiction;
154 
155  // Forward scanning the fragments in this section, starting from the given
156  // fragments, and adding relevant MCPaddingFragments to the Jurisdiction
157  for (MCFragment *CurrFragment = Fragment; CurrFragment != nullptr;
158  CurrFragment = CurrFragment->getNextNode()) {
159 
160  MCPaddingFragment *CurrPaddingFragment =
161  dyn_cast<MCPaddingFragment>(CurrFragment);
162  if (CurrPaddingFragment == nullptr)
163  continue;
164 
165  if (CurrPaddingFragment != Fragment &&
166  CurrPaddingFragment->isInsertionPoint())
167  // Found next insertion point Fragment. From now on it's its jurisdiction.
168  break;
169  for (const auto *Policy : CodePaddingPolicies) {
170  if (CurrPaddingFragment->hasPaddingPolicy(Policy->getKindMask())) {
171  Jurisdiction.push_back(CurrPaddingFragment);
172  break;
173  }
174  }
175  }
176 
177  auto InsertionResult =
178  FragmentToJurisdiction.insert(std::make_pair(Fragment, Jurisdiction));
179  assert(InsertionResult.second &&
180  "Insertion to FragmentToJurisdiction failed");
181  return InsertionResult.first->second;
182 }
183 
184 uint64_t MCCodePadder::getMaxWindowSize(MCPaddingFragment *Fragment,
185  MCAsmLayout &Layout) {
186  auto MaxFragmentSizeLocation = FragmentToMaxWindowSize.find(Fragment);
187  if (MaxFragmentSizeLocation != FragmentToMaxWindowSize.end())
188  return MaxFragmentSizeLocation->second;
189 
190  MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
191  uint64_t JurisdictionMask = MCPaddingFragment::PFK_None;
192  for (const auto *Protege : Jurisdiction)
193  JurisdictionMask |= Protege->getPaddingPoliciesMask();
194 
195  uint64_t MaxFragmentSize = UINT64_C(0);
196  for (const auto *Policy : CodePaddingPolicies)
197  if ((JurisdictionMask & Policy->getKindMask()) !=
199  MaxFragmentSize = std::max(MaxFragmentSize, Policy->getWindowSize());
200 
201  auto InsertionResult =
202  FragmentToMaxWindowSize.insert(std::make_pair(Fragment, MaxFragmentSize));
203  assert(InsertionResult.second &&
204  "Insertion to FragmentToMaxWindowSize failed");
205  return InsertionResult.first->second;
206 }
207 
209  MCAsmLayout &Layout) {
210  if (!Fragment->isInsertionPoint())
211  return false;
212  uint64_t OldSize = Fragment->getSize();
213 
214  uint64_t MaxWindowSize = getMaxWindowSize(Fragment, Layout);
215  if (MaxWindowSize == UINT64_C(0))
216  return false;
217  assert(isPowerOf2_64(MaxWindowSize) &&
218  "MaxWindowSize must be an integer power of 2");
219  uint64_t SectionAlignment = Fragment->getParent()->getAlignment();
220  assert(isPowerOf2_64(SectionAlignment) &&
221  "SectionAlignment must be an integer power of 2");
222 
223  MCPFRange &Jurisdiction = getJurisdiction(Fragment, Layout);
224  uint64_t OptimalSize = UINT64_C(0);
225  double OptimalWeight = std::numeric_limits<double>::max();
226  uint64_t MaxFragmentSize = MaxWindowSize - UINT16_C(1);
227  for (uint64_t Size = UINT64_C(0); Size <= MaxFragmentSize; ++Size) {
228  Fragment->setSize(Size);
229  Layout.invalidateFragmentsFrom(Fragment);
230  double SizeWeight = 0.0;
231  // The section is guaranteed to be aligned to SectionAlignment, but that
232  // doesn't guarantee the exact section offset w.r.t. the policies window
233  // size.
234  // As a concrete example, the section could be aligned to 16B, but a
235  // policy's window size can be 32B. That means that the section actual start
236  // address can either be 0mod32 or 16mod32. The said policy will act
237  // differently for each case, so we need to take both into consideration.
238  for (uint64_t Offset = UINT64_C(0); Offset < MaxWindowSize;
239  Offset += SectionAlignment) {
240  double OffsetWeight = std::accumulate(
241  CodePaddingPolicies.begin(), CodePaddingPolicies.end(), 0.0,
242  [&Jurisdiction, &Offset, &Layout](
243  double Weight, const MCCodePaddingPolicy *Policy) -> double {
244  double PolicyWeight =
245  Policy->computeRangePenaltyWeight(Jurisdiction, Offset, Layout);
246  assert(PolicyWeight >= 0.0 && "A penalty weight must be positive");
247  return Weight + PolicyWeight;
248  });
249  SizeWeight = std::max(SizeWeight, OffsetWeight);
250  }
251  if (SizeWeight < OptimalWeight) {
252  OptimalWeight = SizeWeight;
253  OptimalSize = Size;
254  }
255  if (OptimalWeight == 0.0)
256  break;
257  }
258 
259  Fragment->setSize(OptimalSize);
260  Layout.invalidateFragmentsFrom(Fragment);
261  return OldSize != OptimalSize;
262 }
263 
264 //---------------------------------------------------------------------------
265 // MCCodePaddingPolicy
266 //
267 
269  const MCAsmLayout &Layout) {
270  assert(Fragment != nullptr && "Fragment cannot be null");
271  MCFragment const *NextFragment = Fragment->getNextNode();
272  return NextFragment == nullptr
273  ? Layout.getSectionAddressSize(Fragment->getParent())
274  : Layout.getFragmentOffset(NextFragment);
275 }
276 
277 uint64_t
279  MCAsmLayout &Layout) const {
280  uint64_t InstByte = getNextFragmentOffset(Fragment, Layout);
281  if (InstByteIsLastByte)
282  InstByte += Fragment->getInstSize() - UINT64_C(1);
283  return InstByte;
284 }
285 
286 uint64_t
288  uint64_t Offset,
289  MCAsmLayout &Layout) const {
290  uint64_t InstByte = getFragmentInstByte(Fragment, Layout);
291  return alignTo(InstByte + UINT64_C(1) + Offset, WindowSize) - Offset;
292 }
293 
295  const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const {
296 
298  SmallVector<MCPFRange, 8>::iterator CurrWindowLocation = Windows.end();
299  for (const MCPaddingFragment *Fragment : Range) {
300  if (!Fragment->hasPaddingPolicy(getKindMask()))
301  continue;
302  uint64_t FragmentWindowEndAddress =
303  computeWindowEndAddress(Fragment, Offset, Layout);
304  if (CurrWindowLocation == Windows.end() ||
305  FragmentWindowEndAddress !=
306  computeWindowEndAddress(*CurrWindowLocation->begin(), Offset,
307  Layout)) {
308  // next window is starting
309  Windows.push_back(MCPFRange());
310  CurrWindowLocation = Windows.end() - 1;
311  }
312  CurrWindowLocation->push_back(Fragment);
313  }
314 
315  if (Windows.empty())
316  return 0.0;
317 
318  double RangeWeight = 0.0;
320  RangeWeight += computeFirstWindowPenaltyWeight(*I, Offset, Layout);
321  ++I;
322  RangeWeight += std::accumulate(
323  I, Windows.end(), 0.0,
324  [this, &Layout, &Offset](double Weight, MCPFRange &Window) -> double {
325  return Weight += computeWindowPenaltyWeight(Window, Offset, Layout);
326  });
327  return RangeWeight;
328 }
329 
331  const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const {
332  if (Window.empty())
333  return 0.0;
334  uint64_t WindowEndAddress =
335  computeWindowEndAddress(*Window.begin(), Offset, Layout);
336 
337  MCPFRange FullWindowFirstPart; // will hold all the fragments that are in the
338  // same window as the fragments in the given
339  // window but their penalty weight should not
340  // be added
341  for (const MCFragment *Fragment = (*Window.begin())->getPrevNode();
342  Fragment != nullptr; Fragment = Fragment->getPrevNode()) {
343  const MCPaddingFragment *PaddingNopFragment =
344  dyn_cast<MCPaddingFragment>(Fragment);
345  if (PaddingNopFragment == nullptr ||
346  !PaddingNopFragment->hasPaddingPolicy(getKindMask()))
347  continue;
348  if (WindowEndAddress !=
349  computeWindowEndAddress(PaddingNopFragment, Offset, Layout))
350  break;
351 
352  FullWindowFirstPart.push_back(PaddingNopFragment);
353  }
354 
355  std::reverse(FullWindowFirstPart.begin(), FullWindowFirstPart.end());
356  double FullWindowFirstPartWeight =
357  computeWindowPenaltyWeight(FullWindowFirstPart, Offset, Layout);
358 
359  MCPFRange FullWindow(
360  FullWindowFirstPart); // will hold all the fragments that are in the
361  // same window as the fragments in the given
362  // window, whether their weight should be added
363  // or not
364  FullWindow.append(Window.begin(), Window.end());
365  double FullWindowWeight =
366  computeWindowPenaltyWeight(FullWindow, Offset, Layout);
367 
368  assert(FullWindowWeight >= FullWindowFirstPartWeight &&
369  "More fragments necessarily means bigger weight");
370  return FullWindowWeight - FullWindowFirstPartWeight;
371 }
Fragment for adding required padding.
Definition: MCFragment.h:341
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
LLVMContext & Context
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:289
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void handleBasicBlockStart(MCObjectStreamer *OS, const MCCodePaddingContext &Context)
Handles all target related code padding when starting to write a new basic block to an object file...
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
Definition: MCFragment.cpp:176
bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout)
Relaxes a fragment (changes the size of the padding) according to target requirements.
uint64_t getSize() const
Definition: MCFragment.h:419
FragmentType getKind() const
Definition: MCFragment.h:97
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:685
SmallVector< const MCPaddingFragment *, 8 > MCPFRange
Definition: MCCodePadder.h:25
bool hasPaddingPolicy(uint64_t PolicyMask) const
Definition: MCFragment.h:389
MCObjectStreamer * OS
The current streamer, used to stream code padding.
Definition: MCCodePadder.h:67
unsigned getAlignment() const
Definition: MCSection.h:121
uint64_t getFragmentInstByte(const MCPaddingFragment *Fragment, MCAsmLayout &Layout) const
Returns the instruction byte of an instruction pointed by a given MCPaddingFragment.
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:29
double computeRangePenaltyWeight(const MCPFRange &Range, uint64_t Offset, MCAsmLayout &Layout) const
Computes and returns the penalty caused by a range of instruction windows.
The base class for all padding policies, i.e.
Definition: MCCodePadder.h:127
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:267
virtual bool instructionRequiresInsertionPoint(const MCInst &Inst)
Definition: MCCodePadder.h:76
void setPaddingPoliciesMask(uint64_t Value)
Definition: MCFragment.h:388
static const uint64_t PFK_None
Definition: MCFragment.h:369
Streaming object file generation interface.
void setInstAndInstSize(const MCInst &Inst, size_t InstSize)
Definition: MCFragment.h:406
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Definition: MCFragment.h:271
uint64_t computeWindowEndAddress(const MCPaddingFragment *Fragment, uint64_t Offset, MCAsmLayout &Layout) const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
void invalidateFragmentsFrom(MCFragment *F)
Invalidate the fragments starting with F because it has been resized.
Definition: MCFragment.cpp:52
void handleInstructionBegin(const MCInst &Inst)
Handles all target related code padding before writing a new instruction to an object file...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:434
virtual bool basicBlockRequiresInsertionPoint(const MCCodePaddingContext &Context)
Definition: MCCodePadder.h:72
double computeFirstWindowPenaltyWeight(const MCPFRange &Window, uint64_t Offset, MCAsmLayout &Layout) const
Computes and returns the penalty weight of a first instruction window in a range. ...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
Definition: MCFragment.cpp:78
MCPaddingFragment * getOrCreatePaddingFragment()
bool addPolicy(MCCodePaddingPolicy *Policy)
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
virtual ~MCCodePadder()
uint64_t getPaddingPoliciesMask() const
Definition: MCFragment.h:387
MCSection * getParent() const
Definition: MCFragment.h:99
typename SuperClass::iterator iterator
Definition: SmallVector.h:327
void handleInstructionEnd(const MCInst &Inst)
Handles all target related code padding after writing an instruction to an object file...
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:394
void setSize(uint64_t Value)
Definition: MCFragment.h:420
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
void handleBasicBlockEnd(const MCCodePaddingContext &Context)
Handles all target related code padding when done writing a block to an object file.
size_t size() const
Definition: MCInst.h:193
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
size_t getInstSize() const
Definition: MCFragment.h:398
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
uint32_t Size
Definition: Profile.cpp:47
MCFragment * getCurrentFragment() const
Fragment for data and encoded instructions.
Definition: MCFragment.h:242
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isInsertionPoint() const
Definition: MCFragment.h:385
void setInstAndInstFragment(const MCInst &Inst, MCRelaxableFragment *InstFragment)
Definition: MCFragment.h:412
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
virtual bool usePoliciesForBasicBlock(const MCCodePaddingContext &Context)
Definition: MCCodePadder.h:80
for(unsigned i=Desc.getNumOperands(), e=OldMI.getNumOperands();i !=e;++i)
static uint64_t getNextFragmentOffset(const MCFragment *Fragment, const MCAsmLayout &Layout)
Computes and returns the offset of the consecutive fragment of a given fragment.