-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[X86] Added support for 8 and 16bit LEA instructions #122102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-x86 Author: None (JaydeepChauhan14) ChangesFull diff: https://github.com/llvm/llvm-project/pull/122102.diff 6 Files Affected:
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 9b340a778b36ad..7f33b40503c2c8 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -226,6 +226,8 @@ namespace {
bool selectLEAAddr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
+ bool selectLEA64_16Addr(SDValue N, SDValue &Base, SDValue &Scale,
+ SDValue &Index, SDValue &Disp, SDValue &Segment);
bool selectLEA64_32Addr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
@@ -3054,6 +3056,41 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
return !TM.isLargeGlobalValue(GV);
}
+bool X86DAGToDAGISel::selectLEA64_16Addr(SDValue N, SDValue &Base,
+ SDValue &Scale, SDValue &Index,
+ SDValue &Disp, SDValue &Segment) {
+ // Save the debug loc before calling selectLEAAddr, in case it invalidates N.
+ SDLoc DL(N);
+
+ if (!selectLEAAddr(N, Base, Scale, Index, Disp, Segment))
+ return false;
+
+ auto *RN = dyn_cast<RegisterSDNode>(Base);
+ if (RN && RN->getReg() == 0)
+ Base = CurDAG->getRegister(0, MVT::i64);
+ else if (Base.getValueType() == MVT::i16 && !isa<FrameIndexSDNode>(Base)) {
+ // Base could already be %rip, particularly in the x32 ABI.
+ SDValue ImplDef =
+ SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL, MVT::i64), 0);
+ Base = CurDAG->getTargetInsertSubreg(X86::sub_16bit, DL, MVT::i64, ImplDef,
+ Base);
+ }
+
+ RN = dyn_cast<RegisterSDNode>(Index);
+ if (RN && RN->getReg() == 0)
+ Index = CurDAG->getRegister(0, MVT::i64);
+ else {
+ assert(Index.getValueType() == MVT::i16 &&
+ "Expect to be extending 16-bit registers for use in LEA");
+ SDValue ImplDef =
+ SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL, MVT::i64), 0);
+ Index = CurDAG->getTargetInsertSubreg(X86::sub_16bit, DL, MVT::i64, ImplDef,
+ Index);
+ }
+
+ return true;
+}
+
bool X86DAGToDAGISel::selectLEA64_32Addr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index,
SDValue &Disp, SDValue &Segment) {
diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td
index 16ca2882a84daf..a72fc02e1ba523 100644
--- a/llvm/lib/Target/X86/X86InstrArithmetic.td
+++ b/llvm/lib/Target/X86/X86InstrArithmetic.td
@@ -25,6 +25,12 @@ let SchedRW = [WriteLEA] in {
[(set GR32:$dst, lea32addr:$src)]>,
OpSize32, Requires<[Not64BitMode]>;
+ def LEA64_16r : I<0x8D, MRMSrcMem, (outs GR16:$dst), (ins lea64_16mem:$src),
+ "lea{w}\t{$src|$dst}, {$dst|$src}",
+ [(set GR16:$dst, lea64_16addr:$src)]>,
+ OpSize16,
+ Requires<[In64BitMode]>;
+
def LEA64_32r : I<0x8D, MRMSrcMem,
(outs GR32:$dst), (ins lea64_32mem:$src),
"lea{l}\t{$src|$dst}, {$dst|$src}",
diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td
index ea7af893ce103f..ada4c29da4a97f 100644
--- a/llvm/lib/Target/X86/X86InstrFragments.td
+++ b/llvm/lib/Target/X86/X86InstrFragments.td
@@ -357,6 +357,11 @@ def addr : ComplexPattern<iPTR, 5, "selectAddr">;
def lea32addr : ComplexPattern<i32, 5, "selectLEAAddr",
[add, sub, mul, X86mul_imm, shl, or, xor, frameindex],
[]>;
+// In 64-bit mode 16-bit LEAs can use RIP-relative addressing.
+def lea64_16addr : ComplexPattern<i16, 5, "selectLEA64_16Addr",
+ [add, sub, mul, X86mul_imm, shl, or, xor,
+ frameindex, X86WrapperRIP],
+ []>;
// In 64-bit mode 32-bit LEAs can use RIP-relative addressing.
def lea64_32addr : ComplexPattern<i32, 5, "selectLEA64_32Addr",
[add, sub, mul, X86mul_imm, shl, or, xor,
diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td
index 2102cb4b6b5b73..4bf31c115e635e 100644
--- a/llvm/lib/Target/X86/X86InstrOperands.td
+++ b/llvm/lib/Target/X86/X86InstrOperands.td
@@ -461,6 +461,12 @@ def i64u8imm : Operand<i64> {
let OperandType = "OPERAND_IMMEDIATE";
}
+def lea64_16mem : Operand<i16> {
+ let PrintMethod = "printMemReference";
+ let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i16imm, SEGMENT_REG);
+ let ParserMatchClass = X86MemAsmOperand;
+}
+
def lea64_32mem : Operand<i32> {
let PrintMethod = "printMemReference";
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG);
diff --git a/llvm/test/CodeGen/X86/16bit-lea.ll b/llvm/test/CodeGen/X86/16bit-lea.ll
new file mode 100644
index 00000000000000..049b216c313fa8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/16bit-lea.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-linux -mattr=+ndd | FileCheck %s --check-prefixes=CHECK
+
+define dso_local signext range(i16 1, 0) i16 @lea16bit(i16 noundef signext %in) local_unnamed_addr #0 {
+; CHECK-LABEL: lea16bit:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: leaw 1(%rdi,%rdi), %ax
+; CHECK-NEXT: retq
+entry:
+ %shl = shl i16 %in, 1
+ %or = or disjoint i16 %shl, 1
+ ret i16 %or
+}
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index c6cd3da13646a6..af16b3782195b0 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -1096,6 +1096,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("brtarget16", TYPE_REL)
TYPE("brtarget8", TYPE_REL)
TYPE("f80mem", TYPE_M)
+ TYPE("lea64_16mem", TYPE_M)
TYPE("lea64_32mem", TYPE_M)
TYPE("lea64mem", TYPE_M)
TYPE("VR64", TYPE_MM64)
@@ -1367,6 +1368,7 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
ENCODING("i512mem_GR32", ENCODING_RM)
ENCODING("i512mem_GR64", ENCODING_RM)
ENCODING("f80mem", ENCODING_RM)
+ ENCODING("lea64_16mem", ENCODING_RM)
ENCODING("lea64_32mem", ENCODING_RM)
ENCODING("lea64mem", ENCODING_RM)
ENCODING("anymem", ENCODING_RM)
|
@llvm/pr-subscribers-tablegen Author: None (JaydeepChauhan14) ChangesFull diff: https://github.com/llvm/llvm-project/pull/122102.diff 6 Files Affected:
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 9b340a778b36ad..7f33b40503c2c8 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -226,6 +226,8 @@ namespace {
bool selectLEAAddr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
+ bool selectLEA64_16Addr(SDValue N, SDValue &Base, SDValue &Scale,
+ SDValue &Index, SDValue &Disp, SDValue &Segment);
bool selectLEA64_32Addr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
@@ -3054,6 +3056,41 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
return !TM.isLargeGlobalValue(GV);
}
+bool X86DAGToDAGISel::selectLEA64_16Addr(SDValue N, SDValue &Base,
+ SDValue &Scale, SDValue &Index,
+ SDValue &Disp, SDValue &Segment) {
+ // Save the debug loc before calling selectLEAAddr, in case it invalidates N.
+ SDLoc DL(N);
+
+ if (!selectLEAAddr(N, Base, Scale, Index, Disp, Segment))
+ return false;
+
+ auto *RN = dyn_cast<RegisterSDNode>(Base);
+ if (RN && RN->getReg() == 0)
+ Base = CurDAG->getRegister(0, MVT::i64);
+ else if (Base.getValueType() == MVT::i16 && !isa<FrameIndexSDNode>(Base)) {
+ // Base could already be %rip, particularly in the x32 ABI.
+ SDValue ImplDef =
+ SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL, MVT::i64), 0);
+ Base = CurDAG->getTargetInsertSubreg(X86::sub_16bit, DL, MVT::i64, ImplDef,
+ Base);
+ }
+
+ RN = dyn_cast<RegisterSDNode>(Index);
+ if (RN && RN->getReg() == 0)
+ Index = CurDAG->getRegister(0, MVT::i64);
+ else {
+ assert(Index.getValueType() == MVT::i16 &&
+ "Expect to be extending 16-bit registers for use in LEA");
+ SDValue ImplDef =
+ SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, DL, MVT::i64), 0);
+ Index = CurDAG->getTargetInsertSubreg(X86::sub_16bit, DL, MVT::i64, ImplDef,
+ Index);
+ }
+
+ return true;
+}
+
bool X86DAGToDAGISel::selectLEA64_32Addr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index,
SDValue &Disp, SDValue &Segment) {
diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td
index 16ca2882a84daf..a72fc02e1ba523 100644
--- a/llvm/lib/Target/X86/X86InstrArithmetic.td
+++ b/llvm/lib/Target/X86/X86InstrArithmetic.td
@@ -25,6 +25,12 @@ let SchedRW = [WriteLEA] in {
[(set GR32:$dst, lea32addr:$src)]>,
OpSize32, Requires<[Not64BitMode]>;
+ def LEA64_16r : I<0x8D, MRMSrcMem, (outs GR16:$dst), (ins lea64_16mem:$src),
+ "lea{w}\t{$src|$dst}, {$dst|$src}",
+ [(set GR16:$dst, lea64_16addr:$src)]>,
+ OpSize16,
+ Requires<[In64BitMode]>;
+
def LEA64_32r : I<0x8D, MRMSrcMem,
(outs GR32:$dst), (ins lea64_32mem:$src),
"lea{l}\t{$src|$dst}, {$dst|$src}",
diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td
index ea7af893ce103f..ada4c29da4a97f 100644
--- a/llvm/lib/Target/X86/X86InstrFragments.td
+++ b/llvm/lib/Target/X86/X86InstrFragments.td
@@ -357,6 +357,11 @@ def addr : ComplexPattern<iPTR, 5, "selectAddr">;
def lea32addr : ComplexPattern<i32, 5, "selectLEAAddr",
[add, sub, mul, X86mul_imm, shl, or, xor, frameindex],
[]>;
+// In 64-bit mode 16-bit LEAs can use RIP-relative addressing.
+def lea64_16addr : ComplexPattern<i16, 5, "selectLEA64_16Addr",
+ [add, sub, mul, X86mul_imm, shl, or, xor,
+ frameindex, X86WrapperRIP],
+ []>;
// In 64-bit mode 32-bit LEAs can use RIP-relative addressing.
def lea64_32addr : ComplexPattern<i32, 5, "selectLEA64_32Addr",
[add, sub, mul, X86mul_imm, shl, or, xor,
diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td
index 2102cb4b6b5b73..4bf31c115e635e 100644
--- a/llvm/lib/Target/X86/X86InstrOperands.td
+++ b/llvm/lib/Target/X86/X86InstrOperands.td
@@ -461,6 +461,12 @@ def i64u8imm : Operand<i64> {
let OperandType = "OPERAND_IMMEDIATE";
}
+def lea64_16mem : Operand<i16> {
+ let PrintMethod = "printMemReference";
+ let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i16imm, SEGMENT_REG);
+ let ParserMatchClass = X86MemAsmOperand;
+}
+
def lea64_32mem : Operand<i32> {
let PrintMethod = "printMemReference";
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG);
diff --git a/llvm/test/CodeGen/X86/16bit-lea.ll b/llvm/test/CodeGen/X86/16bit-lea.ll
new file mode 100644
index 00000000000000..049b216c313fa8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/16bit-lea.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-linux -mattr=+ndd | FileCheck %s --check-prefixes=CHECK
+
+define dso_local signext range(i16 1, 0) i16 @lea16bit(i16 noundef signext %in) local_unnamed_addr #0 {
+; CHECK-LABEL: lea16bit:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: leaw 1(%rdi,%rdi), %ax
+; CHECK-NEXT: retq
+entry:
+ %shl = shl i16 %in, 1
+ %or = or disjoint i16 %shl, 1
+ ret i16 %or
+}
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index c6cd3da13646a6..af16b3782195b0 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -1096,6 +1096,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("brtarget16", TYPE_REL)
TYPE("brtarget8", TYPE_REL)
TYPE("f80mem", TYPE_M)
+ TYPE("lea64_16mem", TYPE_M)
TYPE("lea64_32mem", TYPE_M)
TYPE("lea64mem", TYPE_M)
TYPE("VR64", TYPE_MM64)
@@ -1367,6 +1368,7 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
ENCODING("i512mem_GR32", ENCODING_RM)
ENCODING("i512mem_GR64", ENCODING_RM)
ENCODING("f80mem", ENCODING_RM)
+ ENCODING("lea64_16mem", ENCODING_RM)
ENCODING("lea64_32mem", ENCODING_RM)
ENCODING("lea64mem", ENCODING_RM)
ENCODING("anymem", ENCODING_RM)
|
@phoebewang, @e-kud please review. |
def LEA64_16r : I<0x8D, MRMSrcMem, (outs GR16:$dst), (ins lea64_16mem:$src), | ||
"lea{w}\t{$src|$dst}, {$dst|$src}", | ||
[(set GR16:$dst, lea64_16addr:$src)]>, | ||
OpSize16, | ||
Requires<[In64BitMode]>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible not to define a new LEA64_16r, but add a pattern for 16-bit with LEA64_32r? This should address the encoding size concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
The 8 and 16 bit LEA instruction support was added by PR llvm#122102, and we have to update creating index register negations accordingly. The issue is exposed with APX NDD instructions.
The 8 and 16 bit LEA instruction support was added by PR llvm#122102, and we have to update creating index register negations accordingly. The issue is exposed with APX NDD instructions.
The 8 and 16 bit LEA instruction support was added by PR #122102, and we have to update creating index register negations accordingly. The issue is exposed with APX NDD instructions.
The 8 and 16 bit LEA instruction support was added by PR llvm#122102, and we have to update creating index register negations accordingly. The issue is exposed with APX NDD instructions.
No description provided.