Skip to content

[llvm-exegesis] Machine Verification error for lea with 32-bit registers operands for address #132826

@boomanaiden154

Description

@boomanaiden154

Putting the following instruction into llvm-exegesis through a snippets file:

	leal	-32(%eax,%eax), %eax            # encoding: [0x67,0x8d,0x44,0x00,0xe0]

will result in a machine verification failure.:

*** Bad machine code: Illegal physical register for instruction ***
- function:    func0
- basic block: %bb.0  (0x5555fa9ba8e8)
- instruction: $eax = LEA64_32r $eax, 2, $ecx, 0, $noreg
- operand 1:   $eax
$eax is not a GR64 register.

*** Bad machine code: Illegal physical register for instruction ***
- function:    func0
- basic block: %bb.0  (0x5555fa9ba8e8)
- instruction: $eax = LEA64_32r $eax, 2, $ecx, 0, $noreg
- operand 3:   $ecx
$ecx is not a GR64_NOSP register.
LLVM ERROR: Found 2 machine code errors.

It seems LLVM does not acknowledge that an lea instruction in 64-bit mode can accept 32-bit registers in the address argument assuming an address-size prefix (0x67) is added to the instruction (despite generating this code, most likely due to #122102).

Opening up this issue mainly to discuss how we should go about fixing it. The below patch works, but causes some test failures, mostly in llvm-exegesis.

diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td
index 53a6b7c4c4c9..db1f9aa68c48 100644
--- a/llvm/lib/Target/X86/X86InstrOperands.td
+++ b/llvm/lib/Target/X86/X86InstrOperands.td
@@ -479,7 +479,7 @@ def lea64_16mem : Operand<i16> {
 
 def lea64_32mem : Operand<i32> {
   let PrintMethod = "printMemReference";
-  let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG);
+  let MIOperandInfo = (ops GR32_GR64, i8imm, GR32_GR64_NOSP, i32imm, SEGMENT_REG);
   let ParserMatchClass = X86MemAsmOperand;
 }
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.td b/llvm/lib/Target/X86/X86RegisterInfo.td
index 48459b3aca50..12a60b881b09 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.td
+++ b/llvm/lib/Target/X86/X86RegisterInfo.td
@@ -849,6 +849,9 @@ def TILEPAIR : RegisterClass<"X86", [untyped], 512, (add TPAIRS)> {let Size = 16
 // Register categories.
 //
 
+def GR32_GR64 : RegisterCategory<[GR32, GR64]>;
+def GR32_GR64_NOSP : RegisterCategory<[GR32_NOSP, GR64_NOSP]>;
+
 // The TILE and VK*PAIR registers may not be "fixed", but we don't want them
 // anyway.
 def FixedRegisters : RegisterCategory<[DEBUG_REG, CONTROL_REG, CCR, FPCCR,

Not sure if there's a better way of doing this.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions