[llvm] abfe556 - MC: Fix NOP insertion between fused instructions that breaks macro fusion (#155784)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 02:03:44 PDT 2025


Author: Aleksandr Popov
Date: 2025-08-28T11:03:41+02:00
New Revision: abfe556c46f7c055cacc79f3aa322bb2c05d92f5

URL: https://github.com/llvm/llvm-project/commit/abfe556c46f7c055cacc79f3aa322bb2c05d92f5
DIFF: https://github.com/llvm/llvm-project/commit/abfe556c46f7c055cacc79f3aa322bb2c05d92f5.diff

LOG: MC: Fix NOP insertion between fused instructions that breaks macro fusion (#155784)

In the
https://github.com/llvm/llvm-project/commit/39c8cfb70d203439e3296dfdfe3d41f1cb2ec551
patch, getOrCreateDataFragment was optimized by eagerly allocating an
empty fragment when adding a fragment with a variable-size tail. This
means that in this case the current MC fragment is no longer the one
where the instruction was inserted, and the check
`PendingBA && PendingBA->getNext() == OS.getCurrentFragment()` fails,
since CurrentFragment is now the empty fragment instead of the fragment
containing the instruction.

`PendingBA -> Fragment with a variable-size tail (contains previous
instruction) -> CurrentFragment (newly allocated empty fragment)`

This breaks the macro-fusion logic because it incorrectly assumes
another fragment has been inserted between the fused instructions.

Fixes https://github.com/llvm/llvm-project/issues/155045

#155316 Reland

Added: 
    

Modified: 
    llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
    llvm/test/MC/X86/align-branch-fused.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 56a4cc3d65c2e..865fc0ce8101b 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -485,7 +485,16 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
   if (!CanPadInst)
     return;
 
-  if (PendingBA && PendingBA->getNext() == OS.getCurrentFragment()) {
+  if (PendingBA) {
+    auto *NextFragment = PendingBA->getNext();
+    assert(NextFragment && "NextFragment should not be null");
+    if (NextFragment == OS.getCurrentFragment())
+      return;
+    // We eagerly create an empty fragment when inserting a fragment
+    // with a variable-size tail.
+    if (NextFragment->getNext() == OS.getCurrentFragment())
+      return;
+
     // Macro fusion actually happens and there is no other fragment inserted
     // after the previous instruction.
     //

diff  --git a/llvm/test/MC/X86/align-branch-fused.s b/llvm/test/MC/X86/align-branch-fused.s
index 7530967a890c6..5b4a144e30921 100644
--- a/llvm/test/MC/X86/align-branch-fused.s
+++ b/llvm/test/MC/X86/align-branch-fused.s
@@ -1,7 +1,10 @@
-# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=fused+jcc %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=fused+jcc foo.s | llvm-objdump -d --no-show-raw-insn - | FileCheck foo.s
+# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=fused+jcc -x86-pad-max-prefix-size=1 bar.s | llvm-objdump -d --no-show-raw-insn - | FileCheck bar.s
 
   # Exercise cases where fused instructions need to be aligned.
 
+#--- foo.s
   .text
   .globl  foo
 foo:
@@ -40,3 +43,18 @@ foo:
   cmp  %rax, %rbp
   jne foo
   int3
+
+# Exercise the case where fused instructions need to be aligned,
+# ensuring fusion is not broken by a NOP
+
+#--- bar.s
+  .text
+	.globl	bar
+bar:
+  .nops 27
+# CHECK:      20:       testq   %rcx, %rcx
+# CHECK:      23:       je
+	testq	%rcx, %rcx
+	je	.EXIT
+.EXIT:
+	ret


        


More information about the llvm-commits mailing list