[llvm] [X86][APX] Fix assembly printing for NF+ND shift-by-1 instructions (PR #181565)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 17 01:55:38 PST 2026
https://github.com/moleium updated https://github.com/llvm/llvm-project/pull/181565
>From 4e8367df204911bf2261e9e3d992ba84c548b0f9 Mon Sep 17 00:00:00 2001
From: moleium <molenoch at protonmail.com>
Date: Sun, 15 Feb 2026 22:09:43 +0300
Subject: [PATCH 1/4] [X86][APX] Fix assembly printing for NF+ND shift-by-1
instructions
---
.../X86/MCTargetDesc/X86ATTInstPrinter.cpp | 86 +++++++++++++++++++
.../X86/MCTargetDesc/X86ATTInstPrinter.h | 2 +
llvm/lib/Target/X86/X86InstrShiftRotate.td | 4 +-
3 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
index 564636959f00f..d40c803307be0 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
@@ -402,6 +402,92 @@ bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI,
return false;
}
+bool X86ATTInstPrinter::printShiftBy1NFNDInstr(const MCInst *MI,
+ uint64_t Address,
+ raw_ostream &OS) {
+ // Emit explicit $1 for shift-by-1 NF+ND to match binutils behavior.
+ const char *Mnemonic = nullptr;
+ const char *Suffix = nullptr;
+
+ switch (MI->getOpcode()) {
+ default:
+ return false;
+
+ case X86::SHL16r1_NF_ND:
+ Mnemonic = "shl";
+ Suffix = "w";
+ break;
+ case X86::SHL32r1_NF_ND:
+ Mnemonic = "shl";
+ Suffix = "l";
+ break;
+ case X86::SHL64r1_NF_ND:
+ Mnemonic = "shl";
+ Suffix = "q";
+ break;
+
+ case X86::SHR16r1_NF_ND:
+ Mnemonic = "shr";
+ Suffix = "w";
+ break;
+ case X86::SHR32r1_NF_ND:
+ Mnemonic = "shr";
+ Suffix = "l";
+ break;
+ case X86::SHR64r1_NF_ND:
+ Mnemonic = "shr";
+ Suffix = "q";
+ break;
+
+ case X86::SAR16r1_NF_ND:
+ Mnemonic = "sar";
+ Suffix = "w";
+ break;
+ case X86::SAR32r1_NF_ND:
+ Mnemonic = "sar";
+ Suffix = "l";
+ break;
+ case X86::SAR64r1_NF_ND:
+ Mnemonic = "sar";
+ Suffix = "q";
+ break;
+
+ case X86::ROL16r1_NF_ND:
+ Mnemonic = "rol";
+ Suffix = "w";
+ break;
+ case X86::ROL32r1_NF_ND:
+ Mnemonic = "rol";
+ Suffix = "l";
+ break;
+ case X86::ROL64r1_NF_ND:
+ Mnemonic = "rol";
+ Suffix = "q";
+ break;
+
+ case X86::ROR16r1_NF_ND:
+ Mnemonic = "ror";
+ Suffix = "w";
+ break;
+ case X86::ROR32r1_NF_ND:
+ Mnemonic = "ror";
+ Suffix = "l";
+ break;
+ case X86::ROR64r1_NF_ND:
+ Mnemonic = "ror";
+ Suffix = "q";
+ break;
+ }
+
+ // NDD operands are stored as (dst, src).
+ OS << '\t' << Mnemonic << Suffix << "\t$1, ";
+ printOperand(MI, 1, OS);
+ OS << ", ";
+ printOperand(MI, 0, OS);
+
+ return true;
+}
+
void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h
index 1452622ebcea8..9179f0704cc8f 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h
@@ -28,6 +28,8 @@ class X86ATTInstPrinter final : public X86InstPrinterCommon {
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &OS) override;
bool printVecCompareInstr(const MCInst *MI, raw_ostream &OS);
+ bool printShiftBy1NFNDInstr(const MCInst *MI, uint64_t Address,
+ raw_ostream &OS);
// Autogenerated by tblgen, returns true if we successfully printed an
// alias.
diff --git a/llvm/lib/Target/X86/X86InstrShiftRotate.td b/llvm/lib/Target/X86/X86InstrShiftRotate.td
index 2a5488847e648..9775e23a929d7 100644
--- a/llvm/lib/Target/X86/X86InstrShiftRotate.td
+++ b/llvm/lib/Target/X86/X86InstrShiftRotate.td
@@ -70,7 +70,7 @@ multiclass ShiftRotate<string m, Format RegMRM, Format MemMRM, SDPatternOperator
// GNU binutils distinguish them by adding an explicit $1 to asm string of 8r1_ND. But we haven't support
// constant immediate in asm string for X86 in TD. So we add DisassembleOnly for 8r1_ND for the time being.
let Predicates = [In64BitMode] in {
- def 8r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag, 1>, DisassembleOnly;
+ def 8r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi8, null_frag, 1>;
def 16r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi16, null_frag, 1>, PD;
def 32r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi32, null_frag, 1>;
def 64r1_ND : UnaryOpR_RF<0xD1, RegMRM, m, Xi64, null_frag, 1>;
@@ -181,7 +181,7 @@ multiclass ShiftRotate_NF<string m, Format RegMRM, Format MemMRM, SchedReadWrite
def 32r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi32>, NF;
def 64r1_NF : UnaryOpR_R<0xD1, RegMRM, m, Xi64>, NF;
- def 8r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi8, null_frag, 1>, EVEX_NF, DisassembleOnly;
+ def 8r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi8, null_frag, 1>, EVEX_NF;
def 16r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi16, null_frag, 1>, EVEX_NF, PD;
def 32r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi32, null_frag, 1>, EVEX_NF;
def 64r1_NF_ND : UnaryOpR_R<0xD1, RegMRM, m, Xi64, null_frag, 1>, EVEX_NF;
>From a1410cc5f72d25a44e17a81165c6f91f48d89258 Mon Sep 17 00:00:00 2001
From: moleium <molenoch at protonmail.com>
Date: Tue, 17 Feb 2026 12:32:59 +0300
Subject: [PATCH 2/4] Add 8 bit support and use char for suffix
---
.../X86/MCTargetDesc/X86ATTInstPrinter.cpp | 56 +++++++++++++------
1 file changed, 39 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
index d40c803307be0..c29a40bb7119d 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
@@ -85,7 +85,9 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address,
OS << "\tdata32";
}
// Try to print any aliases first.
- else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))
+ else if (!printShiftBy1NFNDInstr(MI, Address, OS) &&
+ !printAliasInstr(MI, Address, OS) &&
+ !printVecCompareInstr(MI, OS))
printInstruction(MI, Address, OS);
// Next always print the annotation.
@@ -407,75 +409,95 @@ bool X86ATTInstPrinter::printShiftBy1NFNDInstr(const MCInst *MI,
raw_ostream &OS) {
// Emit explicit $1 for shift-by-1 NF+ND to match binutils behavior.
const char *Mnemonic = nullptr;
- const char *Suffix = nullptr;
+ char Suffix = 0;
switch (MI->getOpcode()) {
default:
return false;
+ case X86::SHL8r1_NF_ND:
+ Mnemonic = "shl";
+ Suffix = 'b';
+ break;
case X86::SHL16r1_NF_ND:
Mnemonic = "shl";
- Suffix = "w";
+ Suffix = 'w';
break;
case X86::SHL32r1_NF_ND:
Mnemonic = "shl";
- Suffix = "l";
+ Suffix = 'l';
break;
case X86::SHL64r1_NF_ND:
Mnemonic = "shl";
- Suffix = "q";
+ Suffix = 'q';
break;
+ case X86::SHR8r1_NF_ND:
+ Mnemonic = "shr";
+ Suffix = 'b';
+ break;
case X86::SHR16r1_NF_ND:
Mnemonic = "shr";
- Suffix = "w";
+ Suffix = 'w';
break;
case X86::SHR32r1_NF_ND:
Mnemonic = "shr";
- Suffix = "l";
+ Suffix = 'l';
break;
case X86::SHR64r1_NF_ND:
Mnemonic = "shr";
- Suffix = "q";
+ Suffix = 'q';
break;
+ case X86::SAR8r1_NF_ND:
+ Mnemonic = "sar";
+ Suffix = 'b';
+ break;
case X86::SAR16r1_NF_ND:
Mnemonic = "sar";
- Suffix = "w";
+ Suffix = 'w';
break;
case X86::SAR32r1_NF_ND:
Mnemonic = "sar";
- Suffix = "l";
+ Suffix = 'l';
break;
case X86::SAR64r1_NF_ND:
Mnemonic = "sar";
- Suffix = "q";
+ Suffix = 'q';
break;
+ case X86::ROL8r1_NF_ND:
+ Mnemonic = "rol";
+ Suffix = 'b';
+ break;
case X86::ROL16r1_NF_ND:
Mnemonic = "rol";
- Suffix = "w";
+ Suffix = 'w';
break;
case X86::ROL32r1_NF_ND:
Mnemonic = "rol";
- Suffix = "l";
+ Suffix = 'l';
break;
case X86::ROL64r1_NF_ND:
Mnemonic = "rol";
- Suffix = "q";
+ Suffix = 'q';
break;
+ case X86::ROR8r1_NF_ND:
+ Mnemonic = "ror";
+ Suffix = 'b';
+ break;
case X86::ROR16r1_NF_ND:
Mnemonic = "ror";
- Suffix = "w";
+ Suffix = 'w';
break;
case X86::ROR32r1_NF_ND:
Mnemonic = "ror";
- Suffix = "l";
+ Suffix = 'l';
break;
case X86::ROR64r1_NF_ND:
Mnemonic = "ror";
- Suffix = "q";
+ Suffix = 'q';
break;
}
>From 26e46f65ec57a88a2115e79dfc382616679a973d Mon Sep 17 00:00:00 2001
From: moleium <molenoch at protonmail.com>
Date: Tue, 17 Feb 2026 12:52:47 +0300
Subject: [PATCH 3/4] Add tests for APX shift-by-1 NF+ND instructions
---
llvm/test/MC/X86/apx/shift-one-att.s | 81 ++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100644 llvm/test/MC/X86/apx/shift-one-att.s
diff --git a/llvm/test/MC/X86/apx/shift-one-att.s b/llvm/test/MC/X86/apx/shift-one-att.s
new file mode 100644
index 0000000000000..ee5f3b0b7720e
--- /dev/null
+++ b/llvm/test/MC/X86/apx/shift-one-att.s
@@ -0,0 +1,81 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
+
+# CHECK: {nf} shlb $1, %cl, %dl
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd0,0xe1]
+{nf} shlb $1, %cl, %dl
+
+# CHECK: {nf} shlw $1, %cx, %dx
+# CHECK: encoding: [0x62,0xf4,0x6d,0x1c,0xd1,0xe1]
+{nf} shlw $1, %cx, %dx
+
+# CHECK: {nf} shll $1, %ecx, %edx
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd1,0xe1]
+{nf} shll $1, %ecx, %edx
+
+# CHECK: {nf} shlq $1, %rcx, %rdx
+# CHECK: encoding: [0x62,0xf4,0xec,0x1c,0xd1,0xe1]
+{nf} shlq $1, %rcx, %rdx
+
+# CHECK: {nf} shrb $1, %cl, %dl
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd0,0xe9]
+{nf} shrb $1, %cl, %dl
+
+# CHECK: {nf} shrw $1, %cx, %dx
+# CHECK: encoding: [0x62,0xf4,0x6d,0x1c,0xd1,0xe9]
+{nf} shrw $1, %cx, %dx
+
+# CHECK: {nf} shrl $1, %ecx, %edx
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd1,0xe9]
+{nf} shrl $1, %ecx, %edx
+
+# CHECK: {nf} shrq $1, %rcx, %rdx
+# CHECK: encoding: [0x62,0xf4,0xec,0x1c,0xd1,0xe9]
+{nf} shrq $1, %rcx, %rdx
+
+# CHECK: {nf} sarb $1, %cl, %dl
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd0,0xf9]
+{nf} sarb $1, %cl, %dl
+
+# CHECK: {nf} sarw $1, %cx, %dx
+# CHECK: encoding: [0x62,0xf4,0x6d,0x1c,0xd1,0xf9]
+{nf} sarw $1, %cx, %dx
+
+# CHECK: {nf} sarl $1, %ecx, %edx
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd1,0xf9]
+{nf} sarl $1, %ecx, %edx
+
+# CHECK: {nf} sarq $1, %rcx, %rdx
+# CHECK: encoding: [0x62,0xf4,0xec,0x1c,0xd1,0xf9]
+{nf} sarq $1, %rcx, %rdx
+
+# CHECK: {nf} rolb $1, %cl, %dl
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd0,0xc1]
+{nf} rolb $1, %cl, %dl
+
+# CHECK: {nf} rolw $1, %cx, %dx
+# CHECK: encoding: [0x62,0xf4,0x6d,0x1c,0xd1,0xc1]
+{nf} rolw $1, %cx, %dx
+
+# CHECK: {nf} roll $1, %ecx, %edx
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd1,0xc1]
+{nf} roll $1, %ecx, %edx
+
+# CHECK: {nf} rolq $1, %rcx, %rdx
+# CHECK: encoding: [0x62,0xf4,0xec,0x1c,0xd1,0xc1]
+{nf} rolq $1, %rcx, %rdx
+
+# CHECK: {nf} rorb $1, %cl, %dl
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd0,0xc9]
+{nf} rorb $1, %cl, %dl
+
+# CHECK: {nf} rorw $1, %cx, %dx
+# CHECK: encoding: [0x62,0xf4,0x6d,0x1c,0xd1,0xc9]
+{nf} rorw $1, %cx, %dx
+
+# CHECK: {nf} rorl $1, %ecx, %edx
+# CHECK: encoding: [0x62,0xf4,0x6c,0x1c,0xd1,0xc9]
+{nf} rorl $1, %ecx, %edx
+
+# CHECK: {nf} rorq $1, %rcx, %rdx
+# CHECK: encoding: [0x62,0xf4,0xec,0x1c,0xd1,0xc9]
+{nf} rorq $1, %rcx, %rdx
>From 8ae9c4db77232f0b424f2d083ac019c116ed6f72 Mon Sep 17 00:00:00 2001
From: moleium <molenoch at protonmail.com>
Date: Tue, 17 Feb 2026 12:55:24 +0300
Subject: [PATCH 4/4] Fix clang-format
---
llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
index c29a40bb7119d..34c7e46c9b059 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
@@ -86,8 +86,7 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address,
}
// Try to print any aliases first.
else if (!printShiftBy1NFNDInstr(MI, Address, OS) &&
- !printAliasInstr(MI, Address, OS) &&
- !printVecCompareInstr(MI, OS))
+ !printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))
printInstruction(MI, Address, OS);
// Next always print the annotation.
More information about the llvm-commits
mailing list