[llvm] r219811 - [MC] Make bundle alignment mode setting idempotent and support nested bundles
Derek Schuff
dschuff at google.com
Wed Oct 15 10:10:05 PDT 2014
Author: dschuff
Date: Wed Oct 15 12:10:04 2014
New Revision: 219811
URL: http://llvm.org/viewvc/llvm-project?rev=219811&view=rev
Log:
[MC] Make bundle alignment mode setting idempotent and support nested bundles
Summary:
Currently an error is thrown if bundle alignment mode is set more than once
per module (either via the API or the .bundle_align_mode directive). This
change allows setting it multiple times as long as the alignment doesn't
change.
Also nested bundle_lock groups are currently not allowed. This change allows
them, with the effect that the group stays open until all nests are exited,
and if any of the bundle_lock directives has the align_to_end flag, the
group becomes align_to_end.
These changes make the bundle aligment simpler to use in the compiler, and
also better match the corresponding support in GNU as.
Reviewers: jvoung, eliben
Differential Revision: http://reviews.llvm.org/D5801
Added:
llvm/trunk/test/MC/X86/AlignedBundling/nesting.s
Modified:
llvm/trunk/include/llvm/MC/MCAssembler.h
llvm/trunk/lib/MC/MCAssembler.cpp
llvm/trunk/lib/MC/MCELFStreamer.cpp
Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=219811&r1=219810&r2=219811&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Wed Oct 15 12:10:04 2014
@@ -594,7 +594,10 @@ private:
unsigned Alignment;
/// \brief Keeping track of bundle-locked state.
- BundleLockStateType BundleLockState;
+ BundleLockStateType BundleLockState;
+
+ /// \brief Current nesting depth of bundle_lock directives.
+ unsigned BundleLockNestingDepth;
/// \brief We've seen a bundle_lock directive but not its first instruction
/// yet.
@@ -666,9 +669,7 @@ public:
return BundleLockState;
}
- void setBundleLockState(BundleLockStateType NewState) {
- BundleLockState = NewState;
- }
+ void setBundleLockState(BundleLockStateType NewState);
bool isBundleGroupBeforeFirstInst() const {
return BundleGroupBeforeFirstInst;
Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=219811&r1=219810&r2=219811&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Wed Oct 15 12:10:04 2014
@@ -291,7 +291,9 @@ MCSectionData::MCSectionData(const MCSec
: Section(&_Section),
Ordinal(~UINT32_C(0)),
Alignment(1),
- BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false),
+ BundleLockState(NotBundleLocked),
+ BundleLockNestingDepth(0),
+ BundleGroupBeforeFirstInst(false),
HasInstructions(false)
{
if (A)
@@ -328,6 +330,25 @@ MCSectionData::getSubsectionInsertionPoi
return IP;
}
+void MCSectionData::setBundleLockState(BundleLockStateType NewState) {
+ if (NewState == NotBundleLocked) {
+ if (BundleLockNestingDepth == 0) {
+ report_fatal_error("Mismatched bundle_lock/unlock directives");
+ }
+ if (--BundleLockNestingDepth == 0) {
+ BundleLockState = NotBundleLocked;
+ }
+ return;
+ }
+
+ // If any of the directives is an align_to_end directive, the whole nested
+ // group is align_to_end. So don't downgrade from align_to_end to just locked.
+ if (BundleLockState != BundleLockedAlignToEnd) {
+ BundleLockState = NewState;
+ }
+ ++BundleLockNestingDepth;
+}
+
/* *** */
MCSymbolData::MCSymbolData() : Symbol(nullptr) {}
Modified: llvm/trunk/lib/MC/MCELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCELFStreamer.cpp?rev=219811&r1=219810&r2=219811&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCELFStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCELFStreamer.cpp Wed Oct 15 12:10:04 2014
@@ -453,11 +453,13 @@ void MCELFStreamer::EmitInstToData(const
} else {
DF = new MCDataFragment();
insert(DF);
- if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
- // If this is a new fragment created for a bundle-locked group, and the
- // group was marked as "align_to_end", set a flag in the fragment.
- DF->setAlignToBundleEnd(true);
- }
+ }
+ if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
+ // If this fragment is for a group marked "align_to_end", set a flag
+ // in the fragment. This can happen after the fragment has already been
+ // created if there are nested bundle_align groups and an inner one
+ // is the one marked align_to_end.
+ DF->setAlignToBundleEnd(true);
}
// We're now emitting an instruction in a bundle group, so this flag has
@@ -479,10 +481,11 @@ void MCELFStreamer::EmitInstToData(const
void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
assert(AlignPow2 <= 30 && "Invalid bundle alignment");
MCAssembler &Assembler = getAssembler();
- if (Assembler.getBundleAlignSize() == 0 && AlignPow2 > 0)
- Assembler.setBundleAlignSize(1 << AlignPow2);
+ if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 ||
+ Assembler.getBundleAlignSize() == 1U << AlignPow2))
+ Assembler.setBundleAlignSize(1U << AlignPow2);
else
- report_fatal_error(".bundle_align_mode should be only set once per file");
+ report_fatal_error(".bundle_align_mode cannot be changed once set");
}
void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
@@ -492,12 +495,12 @@ void MCELFStreamer::EmitBundleLock(bool
//
if (!getAssembler().isBundlingEnabled())
report_fatal_error(".bundle_lock forbidden when bundling is disabled");
- else if (SD->isBundleLocked())
- report_fatal_error("Nesting of .bundle_lock is forbidden");
+
+ if (!SD->isBundleLocked())
+ SD->setBundleGroupBeforeFirstInst(true);
SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd :
MCSectionData::BundleLocked);
- SD->setBundleGroupBeforeFirstInst(true);
}
void MCELFStreamer::EmitBundleUnlock() {
Added: llvm/trunk/test/MC/X86/AlignedBundling/nesting.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/AlignedBundling/nesting.s?rev=219811&view=auto
==============================================================================
--- llvm/trunk/test/MC/X86/AlignedBundling/nesting.s (added)
+++ llvm/trunk/test/MC/X86/AlignedBundling/nesting.s Wed Oct 15 12:10:04 2014
@@ -0,0 +1,67 @@
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \
+# RUN: | llvm-objdump -disassemble -no-show-raw-insn - | FileCheck %s
+
+# Will be bundle-aligning to 16 byte boundaries
+ .bundle_align_mode 4
+ .text
+# CHECK-LABEL: foo
+foo:
+# Test that bundle alignment mode can be set more than once.
+ .bundle_align_mode 4
+# Each of these callq instructions is 5 bytes long
+ callq bar
+ callq bar
+ .bundle_lock
+ .bundle_lock
+ callq bar
+ callq bar
+ .bundle_unlock
+ .bundle_unlock
+# CHECK: 10: callq
+# CHECK-NEXT: 15: callq
+
+ .p2align 4
+# CHECK-LABEL: bar
+bar:
+ callq foo
+ callq foo
+# Check that the callqs get bundled together, and that the whole group is
+# align_to_end
+ .bundle_lock
+ callq bar
+ .bundle_lock align_to_end
+ callq bar
+ .bundle_unlock
+ .bundle_unlock
+# CHECK: 36: callq
+# CHECK-NEXT: 3b: callq
+
+# CHECK-LABEL: baz
+baz:
+ callq foo
+ callq foo
+# Check that the callqs get bundled together, and that the whole group is
+# align_to_end (with the outer directive marked align_to_end)
+ .bundle_lock align_to_end
+ callq bar
+ .bundle_lock
+ callq bar
+ .bundle_unlock
+ .bundle_unlock
+# CHECK: 56: callq
+# CHECK-NEXT: 5b: callq
+
+# CHECK-LABEL: quux
+quux:
+ callq bar
+ callq bar
+ .bundle_lock
+ .bundle_lock
+ callq bar
+ .bundle_unlock
+ callq bar
+ .bundle_unlock
+# Check that the calls are bundled together when the second one is after the
+# inner nest is closed.
+# CHECK: 70: callq
+# CHECK-NEXT: 75: callq
More information about the llvm-commits
mailing list