[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:33:45 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: nishant-sachdeva-amd

<details>
<summary>Changes</summary>

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.

Changes made here use AI model inputs

---
Full diff: https://github.com/llvm/llvm-project/pull/222591.diff


3 Files Affected:

- (modified) llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h (+28) 
- (modified) llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp (+2-27) 
- (modified) llvm/lib/Target/X86/X86CompressEVEX.cpp (+2-17) 


``````````diff
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.

``````````

</details>


https://github.com/llvm/llvm-project/pull/222591


More information about the llvm-commits mailing list