[MC] Always encode instruction into SmallVector
authorAlexis Engelke <engelke@in.tum.de>
Fri, 10 Mar 2023 14:20:30 +0000 (15:20 +0100)
committerAlexis Engelke <engelke@in.tum.de>
Thu, 6 Apr 2023 14:21:49 +0000 (16:21 +0200)
All users of MCCodeEmitter::encodeInstruction use a raw_svector_ostream
to encode the instruction into a SmallVector. The raw_ostream however
incurs some overhead for the actual encoding.

This change allows an MCCodeEmitter to directly emit an instruction into
a SmallVector without using a raw_ostream and therefore allow for
performance improvments in encoding. A default path that uses existing
raw_ostream implementations is provided.

Reviewed By: MaskRay, Amir

Differential Revision: https://reviews.llvm.org/D145791

21 files changed:
bolt/include/bolt/Core/BinaryContext.h
bolt/lib/Core/BinaryContext.cpp
bolt/lib/Core/BinaryFunction.cpp
llvm/include/llvm/MC/MCCodeEmitter.h
llvm/include/llvm/MCA/CodeEmitter.h
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCAssembler.cpp
llvm/lib/MC/MCCodeEmitter.cpp
llvm/lib/MC/MCELFStreamer.cpp
llvm/lib/MC/MCMachOStreamer.cpp
llvm/lib/MC/MCObjectStreamer.cpp
llvm/lib/MC/MCSPIRVStreamer.cpp
llvm/lib/MC/MCWasmStreamer.cpp
llvm/lib/MC/MCWinCOFFStreamer.cpp
llvm/lib/MC/MCXCOFFStreamer.cpp
llvm/lib/MCA/CodeEmitter.cpp
llvm/lib/Target/AMDGPU/AMDGPUMCInstLower.cpp
llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
llvm/lib/Target/X86/X86MCInstLower.cpp
llvm/tools/llvm-exegesis/lib/LlvmState.cpp

index 26b8a64..7e2d4d6 100644 (file)
@@ -1227,8 +1227,7 @@ public:
       Emitter = this->MCE.get();
     SmallString<256> Code;
     SmallVector<MCFixup, 4> Fixups;
-    raw_svector_ostream VecOS(Code);
-    Emitter->encodeInstruction(Inst, VecOS, Fixups, *STI);
+    Emitter->encodeInstruction(Inst, Code, Fixups, *STI);
     return Code.size();
   }
 
index 09f59f7..6a9e35e 100644 (file)
@@ -2289,9 +2289,8 @@ bool BinaryContext::validateInstructionEncoding(
 
   SmallString<256> Code;
   SmallVector<MCFixup, 4> Fixups;
-  raw_svector_ostream VecOS(Code);
 
-  MCE->encodeInstruction(Inst, VecOS, Fixups, *STI);
+  MCE->encodeInstruction(Inst, Code, Fixups, *STI);
   auto OutputSequence = ArrayRef<uint8_t>((uint8_t *)Code.data(), Code.size());
   if (InputSequence != OutputSequence) {
     if (opts::Verbosity > 1) {
index 69ebd12..14a10be 100644 (file)
@@ -1536,8 +1536,7 @@ bool BinaryFunction::scanExternalRefs() {
     // Emit the instruction using temp emitter and generate relocations.
     SmallString<256> Code;
     SmallVector<MCFixup, 4> Fixups;
-    raw_svector_ostream VecOS(Code);
-    Emitter.MCE->encodeInstruction(Instruction, VecOS, Fixups, *BC.STI);
+    Emitter.MCE->encodeInstruction(Instruction, Code, Fixups, *BC.STI);
 
     // Create relocation for every fixup.
     for (const MCFixup &Fixup : Fixups) {
index 2794acc..9a36a51 100644 (file)
@@ -22,6 +22,13 @@ class MCCodeEmitter {
 protected: // Can only create subclasses.
   MCCodeEmitter();
 
+  /// EncodeInstruction - Encode the given \p Inst to bytes on the output stream
+  /// \p OS. Allows for an implementation of encodeInstruction that uses streams
+  /// instead of a SmallVector.
+  virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS,
+                                 SmallVectorImpl<MCFixup> &Fixups,
+                                 const MCSubtargetInfo &STI) const {}
+
 public:
   MCCodeEmitter(const MCCodeEmitter &) = delete;
   MCCodeEmitter &operator=(const MCCodeEmitter &) = delete;
@@ -36,11 +43,10 @@ public:
   /// \param OS output stream.
   virtual void emitPrefix(const MCInst &Inst, raw_ostream &OS,
                           const MCSubtargetInfo &STI) const {}
-  /// EncodeInstruction - Encode the given \p Inst to bytes on the output
-  /// stream \p OS.
-  virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS,
+  /// EncodeInstruction - Encode the given \p Inst to bytes and append to \p CB.
+  virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,
                                  SmallVectorImpl<MCFixup> &Fixups,
-                                 const MCSubtargetInfo &STI) const = 0;
+                                 const MCSubtargetInfo &STI) const;
 };
 
 } // end namespace llvm
index 502d812..431ceea 100644 (file)
@@ -23,7 +23,6 @@
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 namespace mca {
@@ -38,7 +37,6 @@ class CodeEmitter {
   const MCCodeEmitter &MCE;
 
   SmallString<256> Code;
-  raw_svector_ostream VecOS;
   ArrayRef<MCInst> Sequence;
 
   // An EncodingInfo pair stores <base, length> information.  Base (i.e. first)
@@ -53,8 +51,7 @@ class CodeEmitter {
 public:
   CodeEmitter(const MCSubtargetInfo &ST, const MCAsmBackend &AB,
               const MCCodeEmitter &CE, ArrayRef<MCInst> S)
-      : STI(ST), MAB(AB), MCE(CE), VecOS(Code), Sequence(S),
-        Encodings(S.size()) {}
+      : STI(ST), MAB(AB), MCE(CE), Sequence(S), Encodings(S.size()) {}
 
   StringRef getEncoding(unsigned MCID) {
     EncodingInfo EI = getOrCreateEncodingInfo(MCID);
index fa1ab27..c11d28b 100644 (file)
@@ -2218,13 +2218,12 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
   raw_ostream &OS = getCommentOS();
   SmallString<256> Code;
   SmallVector<MCFixup, 4> Fixups;
-  raw_svector_ostream VecOS(Code);
 
   // If we have no code emitter, don't emit code.
   if (!getAssembler().getEmitterPtr())
     return;
 
-  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   // If we are showing fixups, create symbolic markers in the encoded
   // representation. We do this by making a per-bit map to the fixup item index,
index a33d7ea..179fe23 100644 (file)
@@ -996,8 +996,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
   // probably do so more efficiently in many cases.
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, *F.getSubtargetInfo());
+  getEmitter().encodeInstruction(Relaxed, Code, Fixups, *F.getSubtargetInfo());
 
   // Update the fragment.
   F.setInst(Relaxed);
index 0d114f1..afbe31e 100644 (file)
@@ -7,9 +7,18 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
 MCCodeEmitter::MCCodeEmitter() = default;
 
 MCCodeEmitter::~MCCodeEmitter() = default;
+
+void MCCodeEmitter::encodeInstruction(const MCInst &Inst,
+                                      SmallVectorImpl<char> &CB,
+                                      SmallVectorImpl<MCFixup> &Fixups,
+                                      const MCSubtargetInfo &STI) const {
+  raw_svector_ostream OS(CB);
+  encodeInstruction(Inst, OS, Fixups, STI);
+}
index 380576f..8dd002f 100644 (file)
@@ -551,8 +551,7 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst,
   MCAssembler &Assembler = getAssembler();
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   for (auto &Fixup : Fixups)
     fixSymbolsInTLSFixups(Fixup.getValue());
index 699742f..986c0c2 100644 (file)
@@ -31,7 +31,6 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <vector>
 
@@ -486,8 +485,7 @@ void MCMachOStreamer::emitInstToData(const MCInst &Inst,
 
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   // Add the fixups and data.
   for (MCFixup &Fixup : Fixups) {
index ac90325..d609194 100644 (file)
@@ -471,8 +471,7 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
   insert(IF);
 
   SmallString<128> Code;
-  raw_svector_ostream VecOS(Code);
-  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
+  getAssembler().getEmitter().encodeInstruction(Inst, Code, IF->getFixups(),
                                                 STI);
   IF->getContents().append(Code.begin(), Code.end());
 }
index 863db7f..0bb73c7 100644 (file)
@@ -21,8 +21,7 @@ void MCSPIRVStreamer::emitInstToData(const MCInst &Inst,
   MCAssembler &Assembler = getAssembler();
   SmallVector<MCFixup, 0> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   // Append the encoded instruction to the current data fragment (or create a
   // new such fragment if the current fragment is not a data fragment).
index 823e98a..fbab72f 100644 (file)
@@ -196,8 +196,7 @@ void MCWasmStreamer::emitInstToData(const MCInst &Inst,
   MCAssembler &Assembler = getAssembler();
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   for (auto &Fixup : Fixups)
     fixSymbolsInTLSFixups(Fixup.getValue());
index dbbfcc5..c9a9681 100644 (file)
@@ -53,8 +53,7 @@ void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst,
 
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   // Add the fixups and data.
   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
index d8ac07b..d996dcf 100644 (file)
@@ -133,8 +133,7 @@ void MCXCOFFStreamer::emitInstToData(const MCInst &Inst,
   MCAssembler &Assembler = getAssembler();
   SmallVector<MCFixup, 4> Fixups;
   SmallString<256> Code;
-  raw_svector_ostream VecOS(Code);
-  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+  Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
   // Add the fixups and data.
   MCDataFragment *DF = getOrCreateDataFragment(&STI);
index 0ce17bd..b3936a9 100644 (file)
@@ -27,7 +27,7 @@ CodeEmitter::EncodingInfo CodeEmitter::getOrCreateEncodingInfo(unsigned MCID) {
     MAB.relaxInstruction(Relaxed, STI);
 
   EI.first = Code.size();
-  MCE.encodeInstruction(Relaxed, VecOS, Fixups, STI);
+  MCE.encodeInstruction(Relaxed, Code, Fixups, STI);
   EI.second = Code.size() - EI.first;
   return EI;
 }
index da75f57..9ecad3b 100644 (file)
@@ -285,11 +285,10 @@ void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) {
         (!STI.hasOffset3fBug() || !MI->isBranch())) {
       SmallVector<MCFixup, 4> Fixups;
       SmallVector<char, 16> CodeBytes;
-      raw_svector_ostream CodeStream(CodeBytes);
 
       std::unique_ptr<MCCodeEmitter> InstEmitter(createSIMCCodeEmitter(
           *STI.getInstrInfo(), OutContext));
-      InstEmitter->encodeInstruction(TmpInst, CodeStream, Fixups, STI);
+      InstEmitter->encodeInstruction(TmpInst, CodeBytes, Fixups, STI);
 
       assert(CodeBytes.size() == STI.getInstrInfo()->getInstSizeInBytes(*MI));
     }
@@ -308,10 +307,9 @@ void AMDGPUAsmPrinter::emitInstruction(const MachineInstr *MI) {
       // Disassemble instruction/operands to hex representation.
       SmallVector<MCFixup, 4> Fixups;
       SmallVector<char, 16> CodeBytes;
-      raw_svector_ostream CodeStream(CodeBytes);
 
       DumpCodeInstEmitter->encodeInstruction(
-          TmpInst, CodeStream, Fixups, MF->getSubtarget<MCSubtargetInfo>());
+          TmpInst, CodeBytes, Fixups, MF->getSubtarget<MCSubtargetInfo>());
       HexLines.resize(HexLines.size() + 1);
       std::string &HexLine = HexLines.back();
       raw_string_ostream HexStream(HexLine);
index 08ab3db..12c84ce 100644 (file)
@@ -51,8 +51,7 @@ class HexagonAsmBackend : public MCAsmBackend {
                           MCInst &HMB) const {
     SmallVector<MCFixup, 4> Fixups;
     SmallString<256> Code;
-    raw_svector_ostream VecOS(Code);
-    E.encodeInstruction(HMB, VecOS, Fixups, *RF.getSubtargetInfo());
+    E.encodeInstruction(HMB, Code, Fixups, *RF.getSubtargetInfo());
 
     // Update the fragment.
     RF.setInst(HMB);
index b50a40e..839e003 100644 (file)
@@ -844,8 +844,7 @@ bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF,
 
   SmallVector<MCFixup, 4> Fixups;
   SmallString<15> Code;
-  raw_svector_ostream VecOS(Code);
-  Emitter.encodeInstruction(Relaxed, VecOS, Fixups, *RF.getSubtargetInfo());
+  Emitter.encodeInstruction(Relaxed, Code, Fixups, *RF.getSubtargetInfo());
   const unsigned OldSize = RF.getContents().size();
   const unsigned NewSize = Code.size();
   assert(NewSize >= OldSize && "size decrease during relaxation?");
index 1b323d7..dbf64cc 100644 (file)
@@ -108,8 +108,7 @@ void X86AsmPrinter::StackMapShadowTracker::count(MCInst &Inst,
   if (InShadow) {
     SmallString<256> Code;
     SmallVector<MCFixup, 4> Fixups;
-    raw_svector_ostream VecOS(Code);
-    CodeEmitter->encodeInstruction(Inst, VecOS, Fixups, STI);
+    CodeEmitter->encodeInstruction(Inst, Code, Fixups, STI);
     CurrentShadowSize += Code.size();
     if (CurrentShadowSize >= RequiredShadowSize)
       InShadow = false; // The shadow is big enough. Stop counting.
@@ -1446,8 +1445,7 @@ void X86AsmPrinter::LowerPATCHABLE_OP(const MachineInstr &MI,
   SmallString<256> Code;
   if (!EmptyInst) {
     SmallVector<MCFixup, 4> Fixups;
-    raw_svector_ostream VecOS(Code);
-    CodeEmitter->encodeInstruction(MCI, VecOS, Fixups, getSubtargetInfo());
+    CodeEmitter->encodeInstruction(MCI, Code, Fixups, getSubtargetInfo());
   }
 
   if (Code.size() < MinSize) {
index 6c3d8ff..8aeea45 100644 (file)
@@ -14,7 +14,6 @@
 #include "llvm/MC/MCFixup.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/TargetParser/Host.h"
@@ -136,9 +135,8 @@ bool LLVMState::canAssemble(const MCInst &Inst) const {
           *TheTargetMachine->getMCInstrInfo(), Context));
   assert(CodeEmitter && "unable to create code emitter");
   SmallVector<char, 16> Tmp;
-  raw_svector_ostream OS(Tmp);
   SmallVector<MCFixup, 4> Fixups;
-  CodeEmitter->encodeInstruction(Inst, OS, Fixups,
+  CodeEmitter->encodeInstruction(Inst, Tmp, Fixups,
                                  *TheTargetMachine->getMCSubtargetInfo());
   return Tmp.size() > 0;
 }