-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Open
Description
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.