[llvm] [MC][ELF] Emit instructions directly into fragment (PR #94950)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 10 03:06:35 PDT 2024


https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/94950

Avoid needless copying of instructions and fixups and directly emit into the fragment small vectors

---

This slightly improves performance, but I'm not sure we want to merge this as-is:

- If we go larger changes in MCFragment and how we store contents, this would need another refactoring anyway.
- I also don't like that MCCompactEncodedInstFragment is not just an optimized DataFragment -- using an MCDataFragment instead caused test failures with wrong label positions. Given that NaCl is approximately dead, I wasn't motivated to investigate...
- I didn't test all backends locally, so I'm relying on the CI that. There might be bugs, because the start offset was previously always zero, but now it isn't.



>From 49f835cb844ef7b17b2dbe2fa300904bfe76f307 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Sat, 8 Jun 2024 13:56:31 +0200
Subject: [PATCH] [MC][ELF] Emit instructions directly into fragment

Avoid needless copying of instructions and fixups.
---
 llvm/lib/MC/MCELFStreamer.cpp    | 60 ++++++++++++++++++++++----------
 llvm/lib/MC/MCObjectStreamer.cpp |  6 ++--
 2 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index 23e926c3a9d14..61c842ce39f39 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -549,12 +549,6 @@ static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,
 void MCELFStreamer::emitInstToData(const MCInst &Inst,
                                    const MCSubtargetInfo &STI) {
   MCAssembler &Assembler = getAssembler();
-  SmallVector<MCFixup, 4> Fixups;
-  SmallString<256> Code;
-  Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
-
-  for (auto &Fixup : Fixups)
-    fixSymbolsInTLSFixups(Fixup.getValue());
 
   // There are several possibilities here:
   //
@@ -573,7 +567,16 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst,
   //   the group, though.
   MCDataFragment *DF;
 
+  // When bundling is enabled, we can't just append to the data fragment, as it
+  // might need to be a MCCompactEncodedInstFragment for zero fixups.
   if (Assembler.isBundlingEnabled()) {
+    SmallVector<MCFixup, 4> Fixups;
+    SmallString<256> Code;
+    Assembler.getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
+
+    for (auto &Fixup : Fixups)
+      fixSymbolsInTLSFixups(Fixup.getValue());
+
     MCSection &Sec = *getCurrentSectionOnly();
     if (Assembler.getRelaxAll() && isBundleLocked()) {
       // If the -mc-relax-all flag is used and we are bundle-locked, we re-use
@@ -596,6 +599,9 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst,
       // Optimize memory usage by emitting the instruction to a
       // MCCompactEncodedInstFragment when not in a bundle-locked group and
       // there are no fixups registered.
+      //
+      // Apparently, this is not just a performance optimization? Using an
+      // MCDataFragment at this point causes test failures.
       MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
       insert(CEIF);
       CEIF->getContents().append(Code.begin(), Code.end());
@@ -616,28 +622,44 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst,
     // We're now emitting an instruction in a bundle group, so this flag has
     // to be turned off.
     Sec.setBundleGroupBeforeFirstInst(false);
-  } else {
-    DF = getOrCreateDataFragment(&STI);
+
+    for (auto &Fixup : Fixups) {
+      Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
+      DF->getFixups().push_back(Fixup);
+    }
+
+    DF->setHasInstructions(STI);
+    if (!Fixups.empty() && Fixups.back().getTargetKind() ==
+                               getAssembler().getBackend().RelaxFixupKind)
+      DF->setLinkerRelaxable();
+
+    DF->getContents().append(Code.begin(), Code.end());
+
+    if (Assembler.getRelaxAll() && !isBundleLocked()) {
+      mergeFragment(getOrCreateDataFragment(&STI), DF);
+      delete DF;
+    }
+    return;
   }
 
-  // Add the fixups and data.
+  DF = getOrCreateDataFragment(&STI);
+
+  // Emit instruction directly into data fragment.
+  size_t FixupStartIndex = DF->getFixups().size();
+  size_t CodeOffset = DF->getContents().size();
+  Assembler.getEmitter().encodeInstruction(Inst, DF->getContents(),
+                                           DF->getFixups(), STI);
+
+  auto Fixups = MutableArrayRef(DF->getFixups()).slice(FixupStartIndex);
   for (auto &Fixup : Fixups) {
-    Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
-    DF->getFixups().push_back(Fixup);
+    Fixup.setOffset(Fixup.getOffset() + CodeOffset);
+    fixSymbolsInTLSFixups(Fixup.getValue());
   }
 
   DF->setHasInstructions(STI);
   if (!Fixups.empty() && Fixups.back().getTargetKind() ==
                              getAssembler().getBackend().RelaxFixupKind)
     DF->setLinkerRelaxable();
-  DF->getContents().append(Code.begin(), Code.end());
-
-  if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
-    if (!isBundleLocked()) {
-      mergeFragment(getOrCreateDataFragment(&STI), DF);
-      delete DF;
-    }
-  }
 }
 
 void MCELFStreamer::emitBundleAlignMode(Align Alignment) {
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 0ccade91677a4..6d18bd2995d9d 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -477,10 +477,8 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
   MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI);
   insert(IF);
 
-  SmallString<128> Code;
-  getAssembler().getEmitter().encodeInstruction(Inst, Code, IF->getFixups(),
-                                                STI);
-  IF->getContents().append(Code.begin(), Code.end());
+  getAssembler().getEmitter().encodeInstruction(Inst, IF->getContents(),
+                                                IF->getFixups(), STI);
 }
 
 #ifndef NDEBUG



More information about the llvm-commits mailing list