MC: Add TargetAsmBackend::MayNeedRelaxation, for checking whether a particular instruction + fixups might need relaxation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99249 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index d7f1ace..d14122b 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -679,6 +679,10 @@
bool FixupNeedsRelaxation(const MCAsmFixup &Fixup, const MCFragment *DF,
const MCAsmLayout &Layout) const;
+ /// Check whether the given fragment needs relaxation.
+ bool FragmentNeedsRelaxation(const MCInstFragment *IF,
+ const MCAsmLayout &Layout) const;
+
/// LayoutSection - Assign offsets and sizes to the fragments in the section
/// \arg SD, and update the section size. The section file offset should
/// already have been computed.
diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h
index 16f33c3..f350ecc 100644
--- a/include/llvm/Target/TargetAsmBackend.h
+++ b/include/llvm/Target/TargetAsmBackend.h
@@ -19,6 +19,8 @@
class MCInstFragment;
class MCObjectWriter;
class MCSection;
+template<typename T>
+class SmallVectorImpl;
class Target;
class raw_ostream;
@@ -98,6 +100,15 @@
virtual void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &Fragment,
uint64_t Value) const = 0;
+ /// MayNeedRelaxation - Check whether the given instruction may need
+ /// relaxation.
+ ///
+ /// \arg Inst - The instruction to test.
+ /// \arg Fixups - The actual fixups this instruction encoded to, for potential
+ /// use by the target backend.
+ virtual bool MayNeedRelaxation(const MCInst &Inst,
+ const SmallVectorImpl<MCAsmFixup> &Fixups) const = 0;
+
/// RelaxInstruction - Relax the instruction in the given fragment to the next
/// wider instruction.
virtual void RelaxInstruction(const MCInstFragment *IF,
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 7672528..031820d 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -715,7 +715,7 @@
// Create a new data fragment for the instruction.
//
- // FIXME: Reuse previous data fragment if possible.
+ // FIXME-PERF: Reuse previous data fragment if possible.
MCDataFragment *DF = new MCDataFragment();
SD.getFragmentList().insert(it2, DF);
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index a52d962..2a1aa27 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -383,12 +383,19 @@
Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
VecOS.flush();
- // Add the fixups and data.
- MCDataFragment *DF = getOrCreateDataFragment();
+ // FIXME: Eliminate this copy.
+ SmallVector<MCAsmFixup, 4> AsmFixups;
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
- DF->addFixup(MCAsmFixup(DF->getContents().size()+F.getOffset(),
- *F.getValue(), F.getKind()));
+ AsmFixups.push_back(MCAsmFixup(F.getOffset(), *F.getValue(),
+ F.getKind()));
+ }
+
+ // Add the fixups and data.
+ MCDataFragment *DF = getOrCreateDataFragment();
+ for (unsigned i = 0, e = AsmFixups.size(); i != e; ++i) {
+ AsmFixups[i].Offset += DF->getContents().size();
+ DF->addFixup(AsmFixups[i]);
}
DF->getContents().append(Code.begin(), Code.end());
}
diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp
index 3e4e2b5..8e2928c 100644
--- a/lib/Target/X86/X86AsmBackend.cpp
+++ b/lib/Target/X86/X86AsmBackend.cpp
@@ -12,6 +12,7 @@
#include "X86FixupKinds.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MachObjectWriter.h"
@@ -52,6 +53,9 @@
DF.getContents()[Fixup.Offset + i] = uint8_t(Value >> (i * 8));
}
+ bool MayNeedRelaxation(const MCInst &Inst,
+ const SmallVectorImpl<MCAsmFixup> &Fixups) const;
+
void RelaxInstruction(const MCInstFragment *IF, MCInst &Res) const;
bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
@@ -82,6 +86,20 @@
}
}
+bool X86AsmBackend::MayNeedRelaxation(const MCInst &Inst,
+ const SmallVectorImpl<MCAsmFixup> &Fixups) const {
+ // Check for a 1byte pcrel fixup, and enforce that we would know how to relax
+ // this instruction.
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+ if (unsigned(Fixups[i].Kind) == X86::reloc_pcrel_1byte) {
+ assert(getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode());
+ return true;
+ }
+ }
+
+ return false;
+}
+
// FIXME: Can tblgen help at all here to verify there aren't other instructions
// we can relax?
void X86AsmBackend::RelaxInstruction(const MCInstFragment *IF,