llvm.org GIT mirror llvm / 6c1d497
Add the align_to_end option to .bundle_lock in the MC implementation of aligned bundling. The document describing this feature and the implementation has also been updated: https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/aligned-bundling-support-in-llvm git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171797 91177308-0d34-0410-b5e6-96231b3b80d8 Eli Bendersky 7 years ago
13 changed file(s) with 109 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
9999 void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
100100
101101 /// \brief Does this fragment have instructions emitted into it? By default
102 /// this is false, but specific fragment types may set it to true.
102 /// this is false, but specific fragment types may set it to true.
103103 virtual bool hasInstructions() const { return false; }
104
105 /// \brief Should this fragment be placed at the end of an aligned bundle?
106 virtual bool alignToBundleEnd() const { return false; }
104107
105108 /// \brief Get the padding size that must be inserted before this fragment.
106109 /// Used for bundling. By default, no padding is inserted.
164167 /// \brief Does this fragment contain encoded instructions anywhere in it?
165168 bool HasInstructions;
166169
170 /// \brief Should this fragment be aligned to the end of a bundle?
171 bool AlignToBundleEnd;
172
167173 SmallVector Contents;
168174
169175 /// Fixups - The list of fixups in this fragment.
171177 public:
172178 MCDataFragment(MCSectionData *SD = 0)
173179 : MCEncodedFragment(FT_Data, SD),
174 HasInstructions(false)
180 HasInstructions(false), AlignToBundleEnd(false)
175181 {
176182 }
177183
188194
189195 virtual bool hasInstructions() const { return HasInstructions; }
190196 virtual void setHasInstructions(bool V) { HasInstructions = V; }
197
198 virtual bool alignToBundleEnd() const { return AlignToBundleEnd; }
199 virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
191200
192201 fixup_iterator fixup_begin() { return Fixups.begin(); }
193202 const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
475484 typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
476485 typedef FragmentListType::reverse_iterator reverse_iterator;
477486
487 /// \brief Express the state of bundle locked groups while emitting code.
488 enum BundleLockStateType {
489 NotBundleLocked,
490 BundleLocked,
491 BundleLockedAlignToEnd
492 };
478493 private:
479494 FragmentListType Fragments;
480495 const MCSection *Section;
488503 /// Alignment - The maximum alignment seen in this section.
489504 unsigned Alignment;
490505
491 /// \brief We're currently inside a bundle-locked group.
492 bool BundleLocked;
506 /// \brief Keeping track of bundle-locked state.
507 BundleLockStateType BundleLockState;
493508
494509 /// \brief We've seen a bundle_lock directive but not its first instruction
495510 /// yet.
548563 bool empty() const { return Fragments.empty(); }
549564
550565 bool isBundleLocked() const {
551 return BundleLocked;
552 }
553
554 void setBundleLocked(bool IsLocked) {
555 BundleLocked = IsLocked;
566 return BundleLockState != NotBundleLocked;
567 }
568
569 BundleLockStateType getBundleLockState() const {
570 return BundleLockState;
571 }
572
573 void setBundleLockState(BundleLockStateType NewState) {
574 BundleLockState = NewState;
556575 }
557576
558577 bool isBundleGroupBeforeFirstInst() const {
8484 virtual void EmitInstToData(const MCInst &Inst);
8585
8686 virtual void EmitBundleAlignMode(unsigned AlignPow2);
87 virtual void EmitBundleLock();
87 virtual void EmitBundleLock(bool AlignToEnd);
8888 virtual void EmitBundleUnlock();
8989
9090 void fixSymbolsInTLSFixups(const MCExpr *expr);
8383 virtual void EmitInstToFragment(const MCInst &Inst);
8484
8585 virtual void EmitBundleAlignMode(unsigned AlignPow2);
86 virtual void EmitBundleLock();
86 virtual void EmitBundleLock(bool AlignToEnd);
8787 virtual void EmitBundleUnlock();
8888 virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
8989 virtual void EmitValueToAlignment(unsigned ByteAlignment,
561561 virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0;
562562
563563 /// \brief The following instructions are a bundle-locked group.
564 virtual void EmitBundleLock() = 0;
564 ///
565 /// \param AlignToEnd - If true, the bundle-locked group will be aligned to
566 /// the end of a bundle.
567 virtual void EmitBundleLock(bool AlignToEnd) = 0;
565568
566569 /// \brief Ends a bundle-locked group.
567570 virtual void EmitBundleUnlock() = 0;
259259 virtual void EmitInstruction(const MCInst &Inst);
260260
261261 virtual void EmitBundleAlignMode(unsigned AlignPow2);
262 virtual void EmitBundleLock();
262 virtual void EmitBundleLock(bool AlignToEnd);
263263 virtual void EmitBundleUnlock();
264264
265265 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
13691369 EmitEOL();
13701370 }
13711371
1372 void MCAsmStreamer::EmitBundleLock() {
1372 void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
13731373 OS << "\t.bundle_lock";
1374 if (AlignToEnd)
1375 OS << " align_to_end";
13741376 EmitEOL();
13751377 }
13761378
166166 "computeBundlePadding should only be called if bundling is enabled");
167167 uint64_t BundleMask = BundleSize - 1;
168168 uint64_t OffsetInBundle = FOffset & BundleMask;
169
170 // If the fragment would cross a bundle boundary, add enough padding until
171 // the end of the current bundle.
172 if (OffsetInBundle + FSize > BundleSize)
169 uint64_t EndOfFragment = OffsetInBundle + FSize;
170
171 // There are two kinds of bundling restrictions:
172 //
173 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will
174 // *end* on a bundle boundary.
175 // 2) Otherwise, check if the fragment would cross a bundle boundary. If it
176 // would, add padding until the end of the bundle so that the fragment
177 // will start in a new one.
178 if (F->alignToBundleEnd()) {
179 // Three possibilities here:
180 //
181 // A) The fragment just happens to end at a bundle boundary, so we're good.
182 // B) The fragment ends before the current bundle boundary: pad it just
183 // enough to reach the boundary.
184 // C) The fragment ends after the current bundle boundary: pad it until it
185 // reaches the end of the next bundle boundary.
186 //
187 // Note: this code could be made shorter with some modulo trickery, but it's
188 // intentionally kept in its more explicit form for simplicity.
189 if (EndOfFragment == BundleSize)
190 return 0;
191 else if (EndOfFragment < BundleSize)
192 return BundleSize - EndOfFragment;
193 else { // EndOfFragment > BundleSize
194 return 2 * BundleSize - EndOfFragment;
195 }
196 } else if (EndOfFragment > BundleSize)
173197 return BundleSize - OffsetInBundle;
174198 else
175199 return 0;
203227 : Section(&_Section),
204228 Ordinal(~UINT32_C(0)),
205229 Alignment(1),
206 BundleLocked(false), BundleGroupBeforeFirstInst(false),
230 BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false),
207231 HasInstructions(false)
208232 {
209233 if (A)
378378 MCSectionData *SD = getCurrentSectionData();
379379 if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
380380 DF = getOrCreateDataFragment();
381 else
381 else {
382382 DF = new MCDataFragment(SD);
383 if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
384 // If this is a new fragment created for a bundle-locked group, and the
385 // group was marked as "align_to_end", set a flag in the fragment.
386 DF->setAlignToBundleEnd(true);
387 }
388 }
383389
384390 // We're now emitting an instruction in a bundle group, so this flag has
385391 // to be turned off.
406412 report_fatal_error(".bundle_align_mode should be only set once per file");
407413 }
408414
409 void MCELFStreamer::EmitBundleLock() {
415 void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
410416 MCSectionData *SD = getCurrentSectionData();
411417
412418 // Sanity checks
416422 else if (SD->isBundleLocked())
417423 report_fatal_error("Nesting of .bundle_lock is forbidden");
418424
419 SD->setBundleLocked(true);
425 SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd :
426 MCSectionData::BundleLocked);
420427 SD->setBundleGroupBeforeFirstInst(true);
421428 }
422429
431438 else if (SD->isBundleGroupBeforeFirstInst())
432439 report_fatal_error("Empty bundle-locked group is forbidden");
433440
434 SD->setBundleLocked(false);
441 SD->setBundleLockState(MCSectionData::NotBundleLocked);
435442 }
436443
437444 void MCELFStreamer::FinishImpl() {
9595 virtual void EmitInstruction(const MCInst &Inst) {}
9696
9797 virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
98 virtual void EmitBundleLock() {}
98 virtual void EmitBundleLock(bool AlignToEnd) {}
9999 virtual void EmitBundleUnlock() {}
100100
101101 virtual void FinishImpl() {}
232232 llvm_unreachable(BundlingNotImplementedMsg);
233233 }
234234
235 void MCObjectStreamer::EmitBundleLock() {
235 void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) {
236236 llvm_unreachable(BundlingNotImplementedMsg);
237237 }
238238
24722472 }
24732473
24742474 /// ParseDirectiveBundleLock
2475 /// ::= {.bundle_lock}
2475 /// ::= {.bundle_lock} [align_to_end]
24762476 bool AsmParser::ParseDirectiveBundleLock() {
24772477 CheckForValidSection();
2478
2479 if (getLexer().isNot(AsmToken::EndOfStatement))
2480 return TokError("unexpected token in '.bundle_lock' directive");
2481 Lex();
2482
2483 getStreamer().EmitBundleLock();
2478 bool AlignToEnd = false;
2479
2480 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2481 StringRef Option;
2482 SMLoc Loc = getTok().getLoc();
2483 const char *kInvalidOptionError =
2484 "invalid option for '.bundle_lock' directive";
2485
2486 if (ParseIdentifier(Option))
2487 return Error(Loc, kInvalidOptionError);
2488
2489 if (Option != "align_to_end")
2490 return Error(Loc, kInvalidOptionError);
2491 else if (getLexer().isNot(AsmToken::EndOfStatement))
2492 return Error(Loc,
2493 "unexpected token after '.bundle_lock' directive option");
2494 AlignToEnd = true;
2495 }
2496
2497 Lex();
2498
2499 getStreamer().EmitBundleLock(AlignToEnd);
24842500 return false;
24852501 }
24862502
11 # RUN: | llvm-objdump -no-show-raw-insn -triple armv7 -disassemble - | FileCheck %s
22
33 # On ARM each instruction is 4 bytes long so padding for individual
4 # instructions should not be inserted. However, for bundle=locked groups
4 # instructions should not be inserted. However, for bundle-locked groups
55 # it can be.
66
77 .syntax unified
1313 jle .L_ELSE
1414 .bundle_unlock
1515 # CHECK: .bundle_unlock
16 .bundle_lock align_to_end
17 # CHECK: .bundle_lock align_to_end
18 add %rbx, %rdx
19 .bundle_unlock
1620
1721
765765 }
766766
767767 virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
768 virtual void EmitBundleLock() {}
768 virtual void EmitBundleLock(bool AlignToEnd) {}
769769 virtual void EmitBundleUnlock() {}
770770
771771 // Noop calls.