Skip to content

Commit cf05b6e

Browse files
[X86] Added support for 8 and 16bit LEA instructions (#122102)
1 parent a59b17c commit cf05b6e

File tree

7 files changed

+104
-22
lines changed

7 files changed

+104
-22
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,8 @@ namespace {
226226
bool selectLEAAddr(SDValue N, SDValue &Base,
227227
SDValue &Scale, SDValue &Index, SDValue &Disp,
228228
SDValue &Segment);
229-
bool selectLEA64_32Addr(SDValue N, SDValue &Base,
230-
SDValue &Scale, SDValue &Index, SDValue &Disp,
231-
SDValue &Segment);
229+
bool selectLEA64_Addr(SDValue N, SDValue &Base, SDValue &Scale,
230+
SDValue &Index, SDValue &Disp, SDValue &Segment);
232231
bool selectTLSADDRAddr(SDValue N, SDValue &Base,
233232
SDValue &Scale, SDValue &Index, SDValue &Disp,
234233
SDValue &Segment);
@@ -3058,36 +3057,46 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
30583057
return !TM.isLargeGlobalValue(GV);
30593058
}
30603059

3061-
bool X86DAGToDAGISel::selectLEA64_32Addr(SDValue N, SDValue &Base,
3062-
SDValue &Scale, SDValue &Index,
3063-
SDValue &Disp, SDValue &Segment) {
3060+
bool X86DAGToDAGISel::selectLEA64_Addr(SDValue N, SDValue &Base, SDValue &Scale,
3061+
SDValue &Index, SDValue &Disp,
3062+
SDValue &Segment) {
30643063
// Save the debug loc before calling selectLEAAddr, in case it invalidates N.
30653064
SDLoc DL(N);
30663065

30673066
if (!selectLEAAddr(N, Base, Scale, Index, Disp, Segment))
30683067
return false;
30693068

3069+
EVT BaseType = Base.getValueType();
3070+
unsigned SubReg;
3071+
if (BaseType == MVT::i8)
3072+
SubReg = X86::sub_8bit;
3073+
else if (BaseType == MVT::i16)
3074+
SubReg = X86::sub_16bit;
3075+
else
3076+
SubReg = X86::sub_32bit;
3077+
30703078
auto *RN = dyn_cast<RegisterSDNode>(Base);
30713079
if (RN && RN->getReg() == 0)
30723080
Base = CurDAG->getRegister(0, MVT::i64);
3073-
else if (Base.getValueType() == MVT::i32 && !isa<FrameIndexSDNode>(Base)) {
3081+
else if ((BaseType == MVT::i8 || BaseType == MVT::i16 ||
3082+
BaseType == MVT::i32) &&
3083+
!isa<FrameIndexSDNode>(Base)) {
30743084
// Base could already be %rip, particularly in the x32 ABI.
30753085
SDValue ImplDef = SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL,
30763086
MVT::i64), 0);
3077-
Base = CurDAG->getTargetInsertSubreg(X86::sub_32bit, DL, MVT::i64, ImplDef,
3078-
Base);
3087+
Base = CurDAG->getTargetInsertSubreg(SubReg, DL, MVT::i64, ImplDef, Base);
30793088
}
30803089

3090+
EVT IndexType = Index.getValueType();
30813091
RN = dyn_cast<RegisterSDNode>(Index);
30823092
if (RN && RN->getReg() == 0)
30833093
Index = CurDAG->getRegister(0, MVT::i64);
30843094
else {
3085-
assert(Index.getValueType() == MVT::i32 &&
3086-
"Expect to be extending 32-bit registers for use in LEA");
3095+
assert((IndexType == BaseType) &&
3096+
"Expect to be extending 8/16/32-bit registers for use in LEA");
30873097
SDValue ImplDef = SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL,
30883098
MVT::i64), 0);
3089-
Index = CurDAG->getTargetInsertSubreg(X86::sub_32bit, DL, MVT::i64, ImplDef,
3090-
Index);
3099+
Index = CurDAG->getTargetInsertSubreg(SubReg, DL, MVT::i64, ImplDef, Index);
30913100
}
30923101

30933102
return true;

llvm/lib/Target/X86/X86InstrArithmetic.td

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,25 @@ let SchedRW = [WriteLEA] in {
2525
[(set GR32:$dst, lea32addr:$src)]>,
2626
OpSize32, Requires<[Not64BitMode]>;
2727

28-
def LEA64_32r : I<0x8D, MRMSrcMem,
29-
(outs GR32:$dst), (ins lea64_32mem:$src),
28+
let Predicates = [HasNDD], isCodeGenOnly = 1 in {
29+
def LEA64_8r : I<0x8D, MRMSrcMem, (outs GR8:$dst), (ins lea64_8mem:$src),
30+
"lea{w}\t{$src|$dst}, {$dst|$src}",
31+
[(set GR8:$dst, lea64_iaddr:$src)]>,
32+
OpSize16,
33+
Requires<[In64BitMode]>;
34+
35+
def LEA64_16r : I<0x8D, MRMSrcMem, (outs GR16:$dst), (ins lea64_16mem:$src),
36+
"lea{w}\t{$src|$dst}, {$dst|$src}",
37+
[(set GR16:$dst, lea64_iaddr:$src)]>,
38+
OpSize16,
39+
Requires<[In64BitMode]>;
40+
}
41+
42+
def LEA64_32r : I<0x8D, MRMSrcMem, (outs GR32:$dst), (ins lea64_32mem:$src),
3043
"lea{l}\t{$src|$dst}, {$dst|$src}",
31-
[(set GR32:$dst, lea64_32addr:$src)]>,
32-
OpSize32, Requires<[In64BitMode]>;
44+
[(set GR32:$dst, lea64_iaddr:$src)]>,
45+
OpSize32,
46+
Requires<[In64BitMode]>;
3347

3448
let isReMaterializable = 1 in
3549
def LEA64r : RI<0x8D, MRMSrcMem, (outs GR64:$dst), (ins lea64mem:$src),

llvm/lib/Target/X86/X86InstrFragments.td

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,11 @@ def addr : ComplexPattern<iPTR, 5, "selectAddr">;
357357
def lea32addr : ComplexPattern<i32, 5, "selectLEAAddr",
358358
[add, sub, mul, X86mul_imm, shl, or, xor, frameindex],
359359
[]>;
360-
// In 64-bit mode 32-bit LEAs can use RIP-relative addressing.
361-
def lea64_32addr : ComplexPattern<i32, 5, "selectLEA64_32Addr",
362-
[add, sub, mul, X86mul_imm, shl, or, xor,
363-
frameindex, X86WrapperRIP],
364-
[]>;
360+
// In 64-bit mode 8/16/32-bit LEAs can use RIP-relative addressing.
361+
def lea64_iaddr : ComplexPattern<iAny, 5, "selectLEA64_Addr",
362+
[add, sub, mul, X86mul_imm, shl, or, xor,
363+
frameindex, X86WrapperRIP],
364+
[]>;
365365

366366
def tls32addr : ComplexPattern<i32, 5, "selectTLSADDRAddr",
367367
[tglobaltlsaddr], []>;

llvm/lib/Target/X86/X86InstrOperands.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,18 @@ def i64u8imm : Operand<i64> {
456456
let OperandType = "OPERAND_IMMEDIATE";
457457
}
458458

459+
def lea64_8mem : Operand<i8> {
460+
let PrintMethod = "printMemReference";
461+
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i8imm, SEGMENT_REG);
462+
let ParserMatchClass = X86MemAsmOperand;
463+
}
464+
465+
def lea64_16mem : Operand<i16> {
466+
let PrintMethod = "printMemReference";
467+
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i16imm, SEGMENT_REG);
468+
let ParserMatchClass = X86MemAsmOperand;
469+
}
470+
459471
def lea64_32mem : Operand<i32> {
460472
let PrintMethod = "printMemReference";
461473
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG);

llvm/test/CodeGen/X86/lea-16bit.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s --check-prefix=NO-NDD
3+
; RUN: llc < %s -mtriple=x86_64-linux -mattr=+ndd | FileCheck %s --check-prefix=NDD
4+
5+
define i16 @lea16bit(i16 %in) {
6+
; NO-NDD-LABEL: lea16bit:
7+
; NO-NDD: # %bb.0:
8+
; NO-NDD-NEXT: # kill: def $edi killed $edi def $rdi
9+
; NO-NDD-NEXT: leal 1(%rdi,%rdi), %eax
10+
; NO-NDD-NEXT: # kill: def $ax killed $ax killed $eax
11+
; NO-NDD-NEXT: retq
12+
;
13+
; NDD-LABEL: lea16bit:
14+
; NDD: # %bb.0:
15+
; NDD-NEXT: # kill: def $edi killed $edi def $rdi
16+
; NDD-NEXT: leaw 1(%rdi,%rdi), %ax
17+
; NDD-NEXT: retq
18+
%shl = shl i16 %in, 1
19+
%or = or i16 %shl, 1
20+
ret i16 %or
21+
}

llvm/test/CodeGen/X86/lea-8bit.ll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s --check-prefix=NO-NDD
3+
; RUN: llc < %s -mtriple=x86_64-linux -mattr=+ndd | FileCheck %s --check-prefix=NDD
4+
5+
define i8 @lea8bit(i8 %in) {
6+
; NO-NDD-LABEL: lea8bit:
7+
; NO-NDD: # %bb.0:
8+
; NO-NDD-NEXT: # kill: def $edi killed $edi def $rdi
9+
; NO-NDD-NEXT: leal (%rdi,%rdi), %eax
10+
; NO-NDD-NEXT: incb %al
11+
; NO-NDD-NEXT: # kill: def $al killed $al killed $eax
12+
; NO-NDD-NEXT: retq
13+
;
14+
; NDD-LABEL: lea8bit:
15+
; NDD: # %bb.0:
16+
; NDD-NEXT: # kill: def $edi killed $edi def $rdi
17+
; NDD-NEXT: leaw 1(%rdi,%rdi), %al
18+
; NDD-NEXT: retq
19+
%shl = shl i8 %in, 1
20+
%or = or i8 %shl, 1
21+
ret i8 %or
22+
}

llvm/utils/TableGen/X86RecognizableInstr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
10961096
TYPE("brtarget16", TYPE_REL)
10971097
TYPE("brtarget8", TYPE_REL)
10981098
TYPE("f80mem", TYPE_M)
1099+
TYPE("lea64_8mem", TYPE_M)
1100+
TYPE("lea64_16mem", TYPE_M)
10991101
TYPE("lea64_32mem", TYPE_M)
11001102
TYPE("lea64mem", TYPE_M)
11011103
TYPE("VR64", TYPE_MM64)
@@ -1364,6 +1366,8 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
13641366
ENCODING("i512mem_GR32", ENCODING_RM)
13651367
ENCODING("i512mem_GR64", ENCODING_RM)
13661368
ENCODING("f80mem", ENCODING_RM)
1369+
ENCODING("lea64_8mem", ENCODING_RM)
1370+
ENCODING("lea64_16mem", ENCODING_RM)
13671371
ENCODING("lea64_32mem", ENCODING_RM)
13681372
ENCODING("lea64mem", ENCODING_RM)
13691373
ENCODING("anymem", ENCODING_RM)

0 commit comments

Comments
 (0)