[llvm] [X86][NFC] Share isDispOrCDisp8 between the encoder and CompressEVEX (PR #222591)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 03:35:48 PDT 2026
https://github.com/nishant-sachdeva-amd updated https://github.com/llvm/llvm-project/pull/222591
>From 84ee1c187c538d93eb06e228bebad26c1a816849 Mon Sep 17 00:00:00 2001
From: nsachdev <nishant.sachdeva at amd.com>
Date: Thu, 10 Sep 2026 15:47:25 +0530
Subject: [PATCH] [X86][NFC] Share isDispOrCDisp8 between the encoder and
CompressEVEX
The disp8 / compressed-disp8*N size rule was written twice: as a static
helper in X86MCCodeEmitter.cpp and re-inlined in the CompressEVEX size
veto (hasShorterEVEXViaCDisp8), kept in sync only by a comment. Hoist it
into X86II::isDispOrCDisp8 in X86BaseInfo.h (ImmOffset now optional) and
call it from both, so the size model cannot drift from what the encoder
emits. No functional change.
---
.../lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 28 ++++++++++++++++++
.../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 29 ++-----------------
llvm/lib/Target/X86/X86CompressEVEX.cpp | 19 ++----------
3 files changed, 32 insertions(+), 44 deletions(-)
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 8ed4da0e223a1..49cd0703b8024 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -1165,6 +1165,34 @@ inline int getMemoryOperandIdx(const MCInstrDesc &Desc) {
return MemRefIdx + getOperandBias(Desc);
}
+/// Return true if displacement \p Value fits one byte: a plain disp8, or a
+/// compressed disp8*N for a CDisp8-capable EVEX form (per \p TSFlags). On
+/// success, if \p ImmOffset is non-null it receives the offset to add to
+/// \p Value to leave just the encoded byte (see emitImmediate).
+inline bool isDispOrCDisp8(uint64_t TSFlags, int64_t Value,
+ int *ImmOffset = nullptr) {
+ bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;
+
+ unsigned CD8_Scale =
+ (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift;
+ CD8_Scale = CD8_Scale ? 1U << (CD8_Scale - 1) : 0U;
+ if (!HasEVEX || !CD8_Scale)
+ return isInt<8>(Value);
+
+ assert(isPowerOf2_32(CD8_Scale) && "Unexpected CD8 scale!");
+ if (Value & (CD8_Scale - 1)) // Unaligned offset
+ return false;
+
+ int64_t CDisp8 = Value / static_cast<int64_t>(CD8_Scale);
+ if (!isInt<8>(CDisp8))
+ return false;
+
+ // ImmOffset will be added to Value in emitImmediate leaving just CDisp8.
+ if (ImmOffset)
+ *ImmOffset = CDisp8 - Value;
+ return true;
+}
+
/// \returns true if the register is a XMM.
inline bool isXMMReg(MCRegister Reg) {
static_assert(X86::XMM15 - X86::XMM0 == 15,
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index d4e24f52bb895..ab535c81dbf42 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -410,31 +410,6 @@ static void emitConstant(uint64_t Val, unsigned Size,
}
}
-/// Determine if this immediate can fit in a disp8 or a compressed disp8 for
-/// EVEX instructions. \p will be set to the value to pass to the ImmOffset
-/// parameter of emitImmediate.
-static bool isDispOrCDisp8(uint64_t TSFlags, int Value, int &ImmOffset) {
- bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;
-
- unsigned CD8_Scale =
- (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift;
- CD8_Scale = CD8_Scale ? 1U << (CD8_Scale - 1) : 0U;
- if (!HasEVEX || !CD8_Scale)
- return isInt<8>(Value);
-
- assert(isPowerOf2_32(CD8_Scale) && "Unexpected CD8 scale!");
- if (Value & (CD8_Scale - 1)) // Unaligned offset
- return false;
-
- int CDisp8 = Value / static_cast<int>(CD8_Scale);
- if (!isInt<8>(CDisp8))
- return false;
-
- // ImmOffset will be added to Value in emitImmediate leaving just CDisp8.
- ImmOffset = CDisp8 - Value;
- return true;
-}
-
/// \returns the appropriate fixup kind to use for an immediate in an
/// instruction with the specified TSFlags.
static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
@@ -813,7 +788,7 @@ void X86MCCodeEmitter::emitMemModRMByte(
// can't use disp8 if the {disp32} pseudo prefix is present.
if (Disp.isImm() && AllowDisp8) {
int ImmOffset = 0;
- if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) {
+ if (X86II::isDispOrCDisp8(TSFlags, Disp.getImm(), &ImmOffset)) {
emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), CB);
emitImmediate(Disp, MI.getLoc(), FK_Data_1, false, StartByte, CB,
Fixups, ImmOffset);
@@ -855,7 +830,7 @@ void X86MCCodeEmitter::emitMemModRMByte(
// Emit no displacement ModR/M byte
emitByte(modRMByte(0, RegOpcodeField, 4), CB);
} else if (Disp.isImm() && AllowDisp8 &&
- isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) {
+ X86II::isDispOrCDisp8(TSFlags, Disp.getImm(), &ImmOffset)) {
// Displacement fits in a byte or matches an EVEX compressed disp8, use
// disp8 encoding. This also handles EBP/R13/R21/R29 base with 0
// displacement unless {disp32} pseudo prefix was used.
diff --git a/llvm/lib/Target/X86/X86CompressEVEX.cpp b/llvm/lib/Target/X86/X86CompressEVEX.cpp
index ffd67381b5b2c..098932bcad819 100644
--- a/llvm/lib/Target/X86/X86CompressEVEX.cpp
+++ b/llvm/lib/Target/X86/X86CompressEVEX.cpp
@@ -124,16 +124,8 @@ static bool usesExtendedRegister(const MachineInstr &MI) {
// a compressed disp8*N (1 byte) while the VEX/legacy twin would be forced to
// spend a full disp32 (4 bytes). In that window the EVEX encoding is strictly
// shorter overall, despite its 1-2 byte larger prefix, so compressing it to
-// VEX would grow code size. Mirrors isDispOrCDisp8 in X86MCCodeEmitter.cpp.
+// VEX would grow code size.
static bool hasShorterEVEXViaCDisp8(const MachineInstr &MI) {
- uint64_t TSFlags = MI.getDesc().TSFlags;
- unsigned CD8_Scale =
- (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift;
- CD8_Scale = CD8_Scale ? 1U << (CD8_Scale - 1) : 0U;
- // Without a CD8 scale > 1 there is no displacement advantage over VEX.
- if (CD8_Scale <= 1)
- return false;
-
int MemOpIdx = X86::getFirstAddrOperandIdx(MI);
if (MemOpIdx < 0)
return false;
@@ -145,14 +137,7 @@ static bool hasShorterEVEXViaCDisp8(const MachineInstr &MI) {
return false;
int64_t Val = Disp.getImm();
- // VEX can already use a disp8 in this range, so EVEX offers no saving.
- if (isInt<8>(Val))
- return false;
- // EVEX can use disp8*N only when the value is a multiple of N and the scaled
- // value fits in a signed byte.
- if (Val % static_cast<int64_t>(CD8_Scale) != 0)
- return false;
- return isInt<8>(Val / static_cast<int64_t>(CD8_Scale));
+ return X86II::isDispOrCDisp8(MI.getDesc().TSFlags, Val) && !isInt<8>(Val);
}
// Do any custom cleanup needed to finalize the conversion.
More information about the llvm-commits
mailing list