1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[GlobalISel][X86] G_ZEXT i1 to i32/i64 support.

Summary: Support G_ZEXT i1 to i32/i64 instruction selection.

Reviewers: zvi, guyblank

Reviewed By: guyblank

Subscribers: rovka, llvm-commits, kristof.beyls

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

llvm-svn: 302623
This commit is contained in:
Igor Breger 2017-05-10 06:52:58 +00:00
parent 41f55d04e2
commit 7350527066
8 changed files with 283 additions and 4 deletions

View File

@ -71,6 +71,8 @@ private:
MachineFunction &MF) const;
bool selectTrunc(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
MachineFunction &MF) const;
const X86TargetMachine &TM;
const X86Subtarget &STI;
@ -226,7 +228,7 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
"Generic instruction has unexpected implicit operands\n");
if (selectImpl(I))
return true;
return true;
DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
@ -241,6 +243,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
return true;
if (selectTrunc(I, MRI, MF))
return true;
if (selectZext(I, MRI, MF))
return true;
return false;
}
@ -562,6 +566,52 @@ bool X86InstructionSelector::selectTrunc(MachineInstr &I,
return true;
}
bool X86InstructionSelector::selectZext(MachineInstr &I,
MachineRegisterInfo &MRI,
MachineFunction &MF) const {
if (I.getOpcode() != TargetOpcode::G_ZEXT)
return false;
const unsigned DstReg = I.getOperand(0).getReg();
const unsigned SrcReg = I.getOperand(1).getReg();
const LLT DstTy = MRI.getType(DstReg);
const LLT SrcTy = MRI.getType(SrcReg);
if (SrcTy == LLT::scalar(1)) {
unsigned AndOpc;
if (DstTy == LLT::scalar(32))
AndOpc = X86::AND32ri8;
else if (DstTy == LLT::scalar(64))
AndOpc = X86::AND64ri8;
else
return false;
const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
unsigned DefReg =
MRI.createVirtualRegister(getRegClassForTypeOnBank(DstTy, RegBank));
BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
.addImm(0)
.addReg(SrcReg)
.addImm(X86::sub_8bit);
MachineInstr &AndInst =
*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
.addReg(DefReg)
.addImm(1);
constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
I.eraseFromParent();
return true;
}
return false;
}
InstructionSelector *
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
X86Subtarget &Subtarget,

View File

@ -87,7 +87,7 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
setAction({G_ZEXT, s32}, Legal);
setAction({G_SEXT, s32}, Legal);
for (auto Ty : {s8, s16}) {
for (auto Ty : {s1, s8, s16}) {
setAction({G_ZEXT, 1, Ty}, Legal);
setAction({G_SEXT, 1, Ty}, Legal);
}
@ -139,7 +139,7 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
setAction({G_SEXT, Ty}, Legal);
}
for (auto Ty : {s8, s16, s32}) {
for (auto Ty : {s1, s8, s16, s32}) {
setAction({G_ZEXT, 1, Ty}, Legal);
setAction({G_SEXT, 1, Ty}, Legal);
}

View File

@ -1,7 +1,19 @@
; 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=X64
; TODO merge with ext.ll after i64 sext suported on 32bit platform
; TODO merge with ext.ll after i64 sext suported on 32bit platform
define i64 @test_zext_i1(i8 %a) {
; X64-LABEL: test_zext_i1:
; X64: # BB#0:
; X64-NEXT: # kill: %DIL<def> %DIL<kill> %RDI<def>
; X64-NEXT: andq $1, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: retq
%val = trunc i8 %a to i1
%r = zext i1 %val to i64
ret i64 %r
}
define i64 @test_sext_i8(i8 %val) {
; X64-LABEL: test_sext_i8:

View File

@ -2,6 +2,24 @@
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=X64
; RUN: llc -mtriple=i386-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=X32
define i32 @test_zext_i1(i32 %a) {
; X64-LABEL: test_zext_i1:
; X64: # BB#0:
; X64-NEXT: andl $1, %edi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: retq
;
; X32-LABEL: test_zext_i1:
; X32: # BB#0:
; X32-NEXT: leal 4(%esp), %eax
; X32-NEXT: movl (%eax), %eax
; X32-NEXT: andl $1, %eax
; X32-NEXT: retl
%val = trunc i32 %a to i1
%r = zext i1 %val to i32
ret i32 %r
}
define i32 @test_zext_i8(i8 %val) {
; X64-LABEL: test_zext_i8:
; X64: # BB#0:

View File

@ -1,6 +1,12 @@
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s
--- |
define i64 @test_sext_i1(i8 %a) {
%val = trunc i8 %a to i1
%r = sext i1 %val to i64
ret i64 %r
}
define i64 @test_sext_i8(i8 %val) {
%r = sext i8 %val to i64
ret i64 %r
@ -16,6 +22,12 @@
ret i64 %r
}
define i64 @test_zext_i1(i8 %a) {
%val = trunc i8 %a to i1
%r = zext i1 %val to i64
ret i64 %r
}
define i64 @test_zext_i8(i8 %val) {
%r = zext i8 %val to i64
ret i64 %r
@ -31,6 +43,32 @@
ret i64 %r
}
...
---
name: test_sext_i1
# CHECK-LABEL: name: test_sext_i1
alignment: 4
legalized: false
regBankSelected: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(s8) = COPY %edi
# CHECK-NEXT: %1(s1) = G_TRUNC %0(s8)
# CHECK-NEXT: %2(s64) = G_SEXT %1(s1)
# CHECK-NEXT: %rax = COPY %2(s64)
# CHECK-NEXT: RET 0, implicit %rax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s8) = COPY %edi
%1(s1) = G_TRUNC %0(s8)
%2(s64) = G_SEXT %1(s1)
%rax = COPY %2(s64)
RET 0, implicit %rax
...
---
name: test_sext_i8
@ -100,6 +138,32 @@ body: |
%rax = COPY %1(s64)
RET 0, implicit %rax
...
---
name: test_zext_i1
# CHECK-LABEL: name: test_zext_i1
alignment: 4
legalized: false
regBankSelected: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# CHECK: %0(s8) = COPY %edi
# CHECK-NEXT: %1(s1) = G_TRUNC %0(s8)
# CHECK-NEXT: %2(s64) = G_ZEXT %1(s1)
# CHECK-NEXT: %rax = COPY %2(s64)
# CHECK-NEXT: RET 0, implicit %rax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s8) = COPY %edi
%1(s1) = G_TRUNC %0(s8)
%2(s64) = G_ZEXT %1(s1)
%rax = COPY %2(s64)
RET 0, implicit %rax
...
---
name: test_zext_i8

View File

@ -1,6 +1,12 @@
# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
--- |
define i32 @test_zext_i1(i8 %a) {
%val = trunc i8 %a to i1
%r = zext i1 %val to i32
ret i32 %r
}
define i32 @test_zext_i8(i8 %val) {
%r = zext i8 %val to i32
ret i32 %r
@ -11,6 +17,12 @@
ret i32 %r
}
define i32 @test_sext_i1(i8 %a) {
%val = trunc i8 %a to i1
%r = sext i1 %val to i32
ret i32 %r
}
define i32 @test_sext_i8(i8 %val) {
%r = sext i8 %val to i32
ret i32 %r
@ -21,6 +33,32 @@
ret i32 %r
}
...
---
name: test_zext_i1
# ALL-LABEL: name: test_zext_i1
alignment: 4
legalized: false
regBankSelected: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# ALL: %0(s8) = COPY %edi
# ALL-NEXT: %1(s1) = G_TRUNC %0(s8)
# ALL-NEXT: %2(s32) = G_ZEXT %1(s1)
# ALL-NEXT: %eax = COPY %2(s32)
# ALL-NEXT: RET 0, implicit %eax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s8) = COPY %edi
%1(s1) = G_TRUNC %0(s8)
%2(s32) = G_ZEXT %1(s1)
%eax = COPY %2(s32)
RET 0, implicit %eax
...
---
name: test_zext_i8
@ -67,6 +105,32 @@ body: |
%eax = COPY %1(s32)
RET 0, implicit %eax
...
---
name: test_sext_i1
# ALL-LABEL: name: test_sext_i1
alignment: 4
legalized: false
regBankSelected: false
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
# ALL: %0(s8) = COPY %edi
# ALL-NEXT: %1(s1) = G_TRUNC %0(s8)
# ALL-NEXT: %2(s32) = G_SEXT %1(s1)
# ALL-NEXT: %eax = COPY %2(s32)
# ALL-NEXT: RET 0, implicit %eax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s8) = COPY %edi
%1(s1) = G_TRUNC %0(s8)
%2(s32) = G_SEXT %1(s1)
%eax = COPY %2(s32)
RET 0, implicit %eax
...
---
name: test_sext_i8

View File

@ -1,6 +1,12 @@
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
--- |
define i64 @test_zext_i1(i8 %a) {
%val = trunc i8 %a to i1
%r = zext i1 %val to i64
ret i64 %r
}
define i64 @test_sext_i8(i8 %val) {
%r = sext i8 %val to i64
ret i64 %r
@ -11,6 +17,38 @@
ret i64 %r
}
...
---
name: test_zext_i1
# ALL-LABEL: name: test_zext_i1
alignment: 4
legalized: true
regBankSelected: true
# ALL: registers:
# ALL-NEXT: - { id: 0, class: gr8 }
# ALL-NEXT: - { id: 1, class: gr8 }
# ALL-NEXT: - { id: 2, class: gr64 }
# ALL-NEXT: - { id: 3, class: gr64 }
registers:
- { id: 0, class: gpr }
- { id: 1, class: gpr }
- { id: 2, class: gpr }
# ALL: %0 = COPY %dil
# ALL-NEXT: %1 = COPY %0
# ALL-NEXT: %3 = SUBREG_TO_REG 0, %1, 1
# ALL-NEXT: %2 = AND64ri8 %3, 1, implicit-def %eflags
# ALL-NEXT: %rax = COPY %2
# ALL-NEXT: RET 0, implicit %rax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s8) = COPY %edi
%1(s1) = G_TRUNC %0(s8)
%2(s64) = G_ZEXT %1(s1)
%rax = COPY %2(s64)
RET 0, implicit %rax
...
---
name: test_sext_i8

View File

@ -2,6 +2,11 @@
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
--- |
define i32 @test_zext_i1(i1 %a) {
%r = zext i1 %a to i32
ret i32 %r
}
define i32 @test_zext_i8(i8 %val) {
%r = zext i8 %val to i32
ret i32 %r
@ -22,6 +27,34 @@
ret i32 %r
}
...
---
name: test_zext_i1
# ALL-LABEL: name: test_zext_i1
alignment: 4
legalized: true
regBankSelected: true
# ALL: registers:
# ALL-NEXT: - { id: 0, class: gr8 }
# ALL-NEXT: - { id: 1, class: gr32 }
# ALL-NEXT: - { id: 2, class: gr32 }
registers:
- { id: 0, class: gpr }
- { id: 1, class: gpr }
# ALL: %0 = COPY %dil
# ALL-NEXT: %2 = SUBREG_TO_REG 0, %0, 1
# ALL-NEXT: %1 = AND32ri8 %2, 1, implicit-def %eflags
# ALL-NEXT: %eax = COPY %1
# ALL-NEXT: RET 0, implicit %eax
body: |
bb.1 (%ir-block.0):
liveins: %edi
%0(s1) = COPY %edi
%1(s32) = G_ZEXT %0(s1)
%eax = COPY %1(s32)
RET 0, implicit %eax
...
---
name: test_zext_i8