aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2013-02-05 17:55:27 +0000
committerDerek Schuff <dschuff@google.com>2013-02-05 17:55:27 +0000
commitf918d7fd7393049bc87bc03fda2d2cd3cec1dacb (patch)
tree1a4d4eb30a7e87383e67c3e47147fec66c04044c
parenta499d2bcef0c1001c60d752d356e50eed2402ca8 (diff)
downloadexternal_llvm-f918d7fd7393049bc87bc03fda2d2cd3cec1dacb.zip
external_llvm-f918d7fd7393049bc87bc03fda2d2cd3cec1dacb.tar.gz
external_llvm-f918d7fd7393049bc87bc03fda2d2cd3cec1dacb.tar.bz2
[MC] Bundle alignment: Invalidate relaxed fragments
Currently, when a fragment is relaxed, its size is modified, but its offset is not (it gets laid out as a side effect of checking whether it needs relaxation), then all subsequent fragments are invalidated because their offsets need to change. When bundling is enabled, relaxed fragments need to get laid out again, because the increase in size may push it over a bundle boundary. So instead of only invalidating subsequent fragments, also invalidate the fragment that gets relaxed, which causes it to get laid out again. This patch also fixes some trailing whitespace and fixes the bundling-related debug output of MCFragments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174401 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAsmLayout.h7
-rw-r--r--lib/MC/MCAssembler.cpp15
-rw-r--r--test/MC/X86/AlignedBundling/relax-at-bundle-end.s16
3 files changed, 28 insertions, 10 deletions
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h
index 8cb4601..3058b7b 100644
--- a/include/llvm/MC/MCAsmLayout.h
+++ b/include/llvm/MC/MCAsmLayout.h
@@ -60,9 +60,10 @@ public:
/// Get the assembler object this is a layout for.
MCAssembler &getAssembler() const { return Assembler; }
- /// \brief Invalidate the fragments after F because it has been resized.
- /// The fragment's size should have already been updated.
- void invalidateFragmentsAfter(MCFragment *F);
+ /// \brief Invalidate the fragments starting with F because it has been
+ /// resized. The fragment's size should have already been updated, but
+ /// its bundle padding will be recomputed.
+ void invalidateFragmentsFrom(MCFragment *F);
/// \brief Perform layout for a single fragment, assuming that the previous
/// fragment has already been laid out correctly, and the parent section has
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 498fbf7..fd281e6 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -82,14 +82,15 @@ bool MCAsmLayout::isFragmentValid(const MCFragment *F) const {
return F->getLayoutOrder() <= LastValid->getLayoutOrder();
}
-void MCAsmLayout::invalidateFragmentsAfter(MCFragment *F) {
+void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) {
// If this fragment wasn't already valid, we don't need to do anything.
if (!isFragmentValid(F))
return;
- // Otherwise, reset the last valid fragment to this fragment.
+ // Otherwise, reset the last valid fragment to the previous fragment
+ // (if this is the first fragment, it will be NULL).
const MCSectionData &SD = *F->getParent();
- LastValidFragment[&SD] = F;
+ LastValidFragment[&SD] = F->getPrevNode();
}
void MCAsmLayout::ensureValid(const MCFragment *F) const {
@@ -165,14 +166,14 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
uint64_t MCAsmLayout::computeBundlePadding(const MCFragment *F,
uint64_t FOffset, uint64_t FSize) {
uint64_t BundleSize = Assembler.getBundleAlignSize();
- assert(BundleSize > 0 &&
+ assert(BundleSize > 0 &&
"computeBundlePadding should only be called if bundling is enabled");
uint64_t BundleMask = BundleSize - 1;
uint64_t OffsetInBundle = FOffset & BundleMask;
uint64_t EndOfFragment = OffsetInBundle + FSize;
// There are two kinds of bundling restrictions:
- //
+ //
// 1) For alignToBundleEnd(), add padding to ensure that the fragment will
// *end* on a bundle boundary.
// 2) Otherwise, check if the fragment would cross a bundle boundary. If it
@@ -939,7 +940,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) {
FirstRelaxedFragment = I;
}
if (FirstRelaxedFragment) {
- Layout.invalidateFragmentsAfter(FirstRelaxedFragment);
+ Layout.invalidateFragmentsFrom(FirstRelaxedFragment);
return true;
}
return false;
@@ -999,7 +1000,7 @@ void MCFragment::dump() {
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
<< " Offset:" << Offset
<< " HasInstructions:" << hasInstructions()
- << " BundlePadding:" << getBundlePadding() << ">";
+ << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">";
switch (getKind()) {
case MCFragment::FT_Align: {
diff --git a/test/MC/X86/AlignedBundling/relax-at-bundle-end.s b/test/MC/X86/AlignedBundling/relax-at-bundle-end.s
new file mode 100644
index 0000000..ab4affb
--- /dev/null
+++ b/test/MC/X86/AlignedBundling/relax-at-bundle-end.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \
+# RUN: | llvm-objdump -disassemble -no-show-raw-insn - | FileCheck %s
+
+# Test that an instruction near a bundle end gets properly padded
+# after it is relaxed.
+.text
+foo:
+ .bundle_align_mode 5
+ .rept 29
+ push %rax
+ .endr
+# CHECK: 1c: push
+# CHECK: 1d: nop
+# CHECK: 20: jne
+ jne 0x100
+