Skip to content

Commit

Permalink
[GlobalISel][X86] G_GEP selection support.
Browse files Browse the repository at this point in the history
Summary: [GlobalISel][X86] G_GEP selection support.

Reviewers: zvi, guyblank

Reviewed By: guyblank

Subscribers: dberris, rovka, llvm-commits, kristof.beyls

Differential Revision: https://reviews.llvm.org/D32396

llvm-svn: 302412
  • Loading branch information
Igor Breger committed May 8, 2017
1 parent 511f0b8 commit 810c625
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 10 deletions.
30 changes: 20 additions & 10 deletions llvm/lib/Target/X86/X86InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ class X86InstructionSelector : public InstructionSelector {
MachineFunction &MF) const;
bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectFrameIndex(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
Expand Down Expand Up @@ -235,7 +235,7 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
return true;
if (selectLoadStoreOp(I, MRI, MF))
return true;
if (selectFrameIndex(I, MRI, MF))
if (selectFrameIndexOrGep(I, MRI, MF))
return true;
if (selectConstant(I, MRI, MF))
return true;
Expand Down Expand Up @@ -427,27 +427,37 @@ bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}

bool X86InstructionSelector::selectFrameIndex(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
if (I.getOpcode() != TargetOpcode::G_FRAME_INDEX)
bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
unsigned Opc = I.getOpcode();

if (Opc != TargetOpcode::G_FRAME_INDEX && Opc != TargetOpcode::G_GEP)
return false;

const unsigned DefReg = I.getOperand(0).getReg();
LLT Ty = MRI.getType(DefReg);

// Use LEA to calculate frame index.
// Use LEA to calculate frame index and GEP
unsigned NewOpc;
if (Ty == LLT::pointer(0, 64))
NewOpc = X86::LEA64r;
else if (Ty == LLT::pointer(0, 32))
NewOpc = STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
else
llvm_unreachable("Can't select G_FRAME_INDEX, unsupported type.");
llvm_unreachable("Can't select G_FRAME_INDEX/G_GEP, unsupported type.");

I.setDesc(TII.get(NewOpc));
MachineInstrBuilder MIB(MF, I);
addOffset(MIB, 0);

if (Opc == TargetOpcode::G_FRAME_INDEX) {
addOffset(MIB, 0);
} else {
MachineOperand &InxOp = I.getOperand(2);
I.addOperand(InxOp); // set IndexReg
InxOp.ChangeToImmediate(1); // set Scale
MIB.addImm(0).addReg(0);
}

return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/X86/X86LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
// Pointer-handling
setAction({G_FRAME_INDEX, p0}, Legal);

setAction({G_GEP, p0}, Legal);
setAction({G_GEP, 1, s32}, Legal);

for (auto Ty : {s1, s8, s16})
setAction({G_GEP, 1, Ty}, WidenScalar);

// Constants
for (auto Ty : {s8, s16, s32, p0})
setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
Expand Down Expand Up @@ -114,6 +120,13 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
// Pointer-handling
setAction({G_FRAME_INDEX, p0}, Legal);

setAction({G_GEP, p0}, Legal);
setAction({G_GEP, 1, s32}, Legal);
setAction({G_GEP, 1, s64}, Legal);

for (auto Ty : {s1, s8, s16})
setAction({G_GEP, 1, Ty}, WidenScalar);

// Constants
for (auto Ty : {s8, s16, s32, s64, p0})
setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
Expand Down
136 changes: 136 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/gep.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64_GISEL
; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64

define i32* @test_gep_i8(i32 *%arr, i8 %ind) {
; X64_GISEL-LABEL: test_gep_i8:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: movsbq %sil, %rcx
; X64_GISEL-NEXT: imulq %rax, %rcx
; X64_GISEL-NEXT: leaq (%rdi,%rcx), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i8:
; X64: # BB#0:
; X64-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
; X64-NEXT: movsbq %sil, %rax
; X64-NEXT: leaq (%rdi,%rax,4), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i8 %ind
ret i32* %arrayidx
}

define i32* @test_gep_i8_const(i32 *%arr) {
; X64_GISEL-LABEL: test_gep_i8_const:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $80, %rax
; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i8_const:
; X64: # BB#0:
; X64-NEXT: leaq 80(%rdi), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i8 20
ret i32* %arrayidx
}

define i32* @test_gep_i16(i32 *%arr, i16 %ind) {
; X64_GISEL-LABEL: test_gep_i16:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: movswq %si, %rcx
; X64_GISEL-NEXT: imulq %rax, %rcx
; X64_GISEL-NEXT: leaq (%rdi,%rcx), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i16:
; X64: # BB#0:
; X64-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
; X64-NEXT: movswq %si, %rax
; X64-NEXT: leaq (%rdi,%rax,4), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i16 %ind
ret i32* %arrayidx
}

define i32* @test_gep_i16_const(i32 *%arr) {
; X64_GISEL-LABEL: test_gep_i16_const:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $80, %rax
; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i16_const:
; X64: # BB#0:
; X64-NEXT: leaq 80(%rdi), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i16 20
ret i32* %arrayidx
}

define i32* @test_gep_i32(i32 *%arr, i32 %ind) {
; X64_GISEL-LABEL: test_gep_i32:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: movslq %esi, %rcx
; X64_GISEL-NEXT: imulq %rax, %rcx
; X64_GISEL-NEXT: leaq (%rdi,%rcx), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i32:
; X64: # BB#0:
; X64-NEXT: movslq %esi, %rax
; X64-NEXT: leaq (%rdi,%rax,4), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i32 %ind
ret i32* %arrayidx
}

define i32* @test_gep_i32_const(i32 *%arr) {
; X64_GISEL-LABEL: test_gep_i32_const:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $20, %rax
; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i32_const:
; X64: # BB#0:
; X64-NEXT: leaq 20(%rdi), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i32 5
ret i32* %arrayidx
}

define i32* @test_gep_i64(i32 *%arr, i64 %ind) {
; X64_GISEL-LABEL: test_gep_i64:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: imulq %rsi, %rax
; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i64:
; X64: # BB#0:
; X64-NEXT: leaq (%rdi,%rsi,4), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i64 %ind
ret i32* %arrayidx
}

define i32* @test_gep_i64_const(i32 *%arr) {
; X64_GISEL-LABEL: test_gep_i64_const:
; X64_GISEL: # BB#0:
; X64_GISEL-NEXT: movq $20, %rax
; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i64_const:
; X64: # BB#0:
; X64-NEXT: leaq 20(%rdi), %rax
; X64-NEXT: retq
%arrayidx = getelementptr i32, i32* %arr, i64 5
ret i32* %arrayidx
}

101 changes: 101 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/legalize-gep.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s

--- |
define void @test_gep_i8() {
%arrayidx = getelementptr i32, i32* undef, i8 5
ret void
}

define void @test_gep_i16() {
%arrayidx = getelementptr i32, i32* undef, i16 5
ret void
}

define void @test_gep_i32() {
%arrayidx = getelementptr i32, i32* undef, i32 5
ret void
}

define void @test_gep_i64() {
%arrayidx = getelementptr i32, i32* undef, i64 5
ret void
}
...
---
name: test_gep_i8
# CHECK-LABEL: name: test_gep_i8
legalized: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(p0) = IMPLICIT_DEF
# CHECK-NEXT: %1(s8) = G_CONSTANT i8 20
# CHECK-NEXT: %3(s32) = G_SEXT %1(s8)
# CHECK-NEXT: %2(p0) = G_GEP %0, %3(s32)
# CHECK-NEXT: RET 0
body: |
bb.1 (%ir-block.0):
%0(p0) = IMPLICIT_DEF
%1(s8) = G_CONSTANT i8 20
%2(p0) = G_GEP %0, %1(s8)
RET 0
...
---
name: test_gep_i16
# CHECK-LABEL: name: test_gep_i16
legalized: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(p0) = IMPLICIT_DEF
# CHECK-NEXT: %1(s16) = G_CONSTANT i16 20
# CHECK-NEXT: %3(s32) = G_SEXT %1(s16)
# CHECK-NEXT: %2(p0) = G_GEP %0, %3(s32)
# CHECK-NEXT: RET 0
body: |
bb.1 (%ir-block.0):
%0(p0) = IMPLICIT_DEF
%1(s16) = G_CONSTANT i16 20
%2(p0) = G_GEP %0, %1(s16)
RET 0
...
---
name: test_gep_i32
# CHECK-LABEL: name: test_gep_i32
legalized: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(p0) = IMPLICIT_DEF
# CHECK-NEXT: %1(s32) = G_CONSTANT i32 20
# CHECK-NEXT: %2(p0) = G_GEP %0, %1(s32)
# CHECK-NEXT: RET 0
body: |
bb.1 (%ir-block.0):
%0(p0) = IMPLICIT_DEF
%1(s32) = G_CONSTANT i32 20
%2(p0) = G_GEP %0, %1(s32)
RET 0
...
---
name: test_gep_i64
# CHECK-LABEL: name: test_gep_i64
legalized: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(p0) = IMPLICIT_DEF
# CHECK-NEXT: %1(s64) = G_CONSTANT i64 20
# CHECK-NEXT: %2(p0) = G_GEP %0, %1(s64)
# CHECK-NEXT: RET 0
body: |
bb.1 (%ir-block.0):
%0(p0) = IMPLICIT_DEF
%1(s64) = G_CONSTANT i64 20
%2(p0) = G_GEP %0, %1(s64)
RET 0
...
32 changes: 32 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@
ret void
}

define void @test_gep() {
%p1 = getelementptr i32, i32* undef, i32 5
%p2 = getelementptr i32, i32* undef, i64 5
ret void
}

...
---
name: test_add_i8
Expand Down Expand Up @@ -703,3 +709,29 @@ body: |
RET 0
...
---
name: test_gep
legalized: true
# CHECK-LABEL: name: test_gep
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr }
# CHECK-NEXT: - { id: 1, class: gpr }
# CHECK-NEXT: - { id: 2, class: gpr }
# CHECK-NEXT: - { id: 3, class: gpr }
# CHECK-NEXT: - { id: 4, class: gpr }
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
- { id: 3, class: _ }
- { id: 4, class: _ }
body: |
bb.0 (%ir-block.0):
%0(p0) = IMPLICIT_DEF
%1(s32) = G_CONSTANT i32 20
%2(p0) = G_GEP %0, %1(s32)
%3(s64) = G_CONSTANT i64 20
%4(p0) = G_GEP %0, %3(s64)
RET 0
...

0 comments on commit 810c625

Please sign in to comment.