mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[GlobalISel][X86] Support G_IMPLICIT_DEF.
Summary: Support G_IMPLICIT_DEF. Reviewers: zvi, guyblank, t.p.northover Reviewed By: guyblank Subscribers: rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D36733 llvm-svn: 311633
This commit is contained in:
parent
16729fe8c1
commit
8dd4b724b5
@ -85,6 +85,7 @@ private:
|
||||
MachineFunction &MF) const;
|
||||
bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
bool selectImplicitDef(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||
|
||||
// emit insert subreg instruction and insert it before MachineInstr &I
|
||||
bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
|
||||
@ -334,6 +335,8 @@ bool X86InstructionSelector::select(MachineInstr &I) const {
|
||||
return true;
|
||||
if (selectCondBranch(I, MRI, MF))
|
||||
return true;
|
||||
if (selectImplicitDef(I, MRI))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1128,6 +1131,29 @@ bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool X86InstructionSelector::selectImplicitDef(MachineInstr &I,
|
||||
MachineRegisterInfo &MRI) const {
|
||||
|
||||
if (I.getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
|
||||
return false;
|
||||
|
||||
unsigned DstReg = I.getOperand(0).getReg();
|
||||
|
||||
if (!MRI.getRegClassOrNull(DstReg)) {
|
||||
const LLT DstTy = MRI.getType(DstReg);
|
||||
const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
|
||||
|
||||
if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
|
||||
DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
|
||||
<< " operand\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
I.setDesc(TII.get(X86::IMPLICIT_DEF));
|
||||
return true;
|
||||
}
|
||||
|
||||
InstructionSelector *
|
||||
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
|
||||
X86Subtarget &Subtarget,
|
||||
|
@ -52,6 +52,9 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
|
||||
const LLT s32 = LLT::scalar(32);
|
||||
const LLT s64 = LLT::scalar(64);
|
||||
|
||||
for (auto Ty : {p0, s1, s8, s16, s32})
|
||||
setAction({G_IMPLICIT_DEF, Ty}, Legal);
|
||||
|
||||
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
||||
for (auto Ty : {s8, s16, s32})
|
||||
setAction({BinOp, Ty}, Legal);
|
||||
@ -120,6 +123,9 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
|
||||
const LLT s32 = LLT::scalar(32);
|
||||
const LLT s64 = LLT::scalar(64);
|
||||
|
||||
for (auto Ty : {p0, s1, s8, s16, s32, s64})
|
||||
setAction({G_IMPLICIT_DEF, Ty}, Legal);
|
||||
|
||||
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
||||
for (auto Ty : {s8, s16, s32, s64})
|
||||
setAction({BinOp, Ty}, Legal);
|
||||
|
@ -211,7 +211,8 @@ X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
|
||||
|
||||
switch (MI.getOpcode()) {
|
||||
case TargetOpcode::G_LOAD:
|
||||
case TargetOpcode::G_STORE: {
|
||||
case TargetOpcode::G_STORE:
|
||||
case TargetOpcode::G_IMPLICIT_DEF: {
|
||||
// we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
|
||||
unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
|
||||
if (Size != 32 && Size != 64)
|
||||
|
29
test/CodeGen/X86/GlobalISel/legalize-undef.mir
Normal file
29
test/CodeGen/X86/GlobalISel/legalize-undef.mir
Normal file
@ -0,0 +1,29 @@
|
||||
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
|
||||
# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
|
||||
|
||||
---
|
||||
name: test_implicit_def
|
||||
# ALL-LABEL: name: test_implicit_def
|
||||
registers:
|
||||
# X64: %0(s1) = G_IMPLICIT_DEF
|
||||
# X64-NEXT: %1(s8) = G_IMPLICIT_DEF
|
||||
# X64-NEXT: %2(s16) = G_IMPLICIT_DEF
|
||||
# X64-NEXT: %3(s32) = G_IMPLICIT_DEF
|
||||
# X64-NEXT: %4(s64) = G_IMPLICIT_DEF
|
||||
#
|
||||
# X32: %0(s1) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %1(s8) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %2(s16) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %3(s32) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %5(s32) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %6(s32) = G_IMPLICIT_DEF
|
||||
# X32-NEXT: %4(s64) = G_MERGE_VALUES %5(s32), %6(s32)
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins:
|
||||
%0:_(s1) = G_IMPLICIT_DEF
|
||||
%1:_(s8) = G_IMPLICIT_DEF
|
||||
%2:_(s16) = G_IMPLICIT_DEF
|
||||
%3:_(s32) = G_IMPLICIT_DEF
|
||||
%4:_(s64) = G_IMPLICIT_DEF
|
||||
...
|
@ -181,6 +181,23 @@
|
||||
ret i32* @g_int
|
||||
}
|
||||
|
||||
define i8 @test_undef() {
|
||||
ret i8 undef
|
||||
}
|
||||
|
||||
define i8 @test_undef2(i8 %a) {
|
||||
%r = add i8 %a, undef
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
define float @test_undef3() {
|
||||
ret float undef
|
||||
}
|
||||
|
||||
define float @test_undef4(float %a) {
|
||||
%r = fadd float %a, undef
|
||||
ret float %r
|
||||
}
|
||||
...
|
||||
---
|
||||
name: test_add_i8
|
||||
@ -1111,4 +1128,122 @@ body: |
|
||||
RET 0, implicit %rax
|
||||
|
||||
...
|
||||
---
|
||||
name: test_undef
|
||||
# CHECK-LABEL: name: test_undef
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: false
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: _, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# CHECK: %0(s8) = G_IMPLICIT_DEF
|
||||
# CHECK-NEXT: %al = COPY %0(s8)
|
||||
# CHECK-NEXT: RET 0, implicit %al
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
%0(s8) = G_IMPLICIT_DEF
|
||||
%al = COPY %0(s8)
|
||||
RET 0, implicit %al
|
||||
|
||||
...
|
||||
---
|
||||
name: test_undef2
|
||||
# CHECK-LABEL: name: test_undef2
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: false
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
|
||||
# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
|
||||
# CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: _, preferred-register: '' }
|
||||
- { id: 1, class: _, preferred-register: '' }
|
||||
- { id: 2, class: _, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# CHECK: %0(s8) = COPY %edi
|
||||
# CHECK-NEXT: %1(s8) = G_IMPLICIT_DEF
|
||||
# CHECK-NEXT: %2(s8) = G_ADD %0, %1
|
||||
# CHECK-NEXT: %al = COPY %2(s8)
|
||||
# CHECK-NEXT: RET 0, implicit %al
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi
|
||||
|
||||
%0(s8) = COPY %edi
|
||||
%1(s8) = G_IMPLICIT_DEF
|
||||
%2(s8) = G_ADD %0, %1
|
||||
%al = COPY %2(s8)
|
||||
RET 0, implicit %al
|
||||
|
||||
...
|
||||
---
|
||||
name: test_undef3
|
||||
# CHECK-LABEL: name: test_undef3
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: false
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: _, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# CHECK: %0(s32) = G_IMPLICIT_DEF
|
||||
# CHECK-NEXT: %xmm0 = COPY %0(s32)
|
||||
# CHECK-NEXT: RET 0, implicit %xmm0
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
%0(s32) = G_IMPLICIT_DEF
|
||||
%xmm0 = COPY %0(s32)
|
||||
RET 0, implicit %xmm0
|
||||
|
||||
...
|
||||
---
|
||||
name: test_undef4
|
||||
# CHECK-LABEL: name: test_undef4
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: false
|
||||
# CHECK: registers:
|
||||
# CHECK-NEXT: - { id: 0, class: vecr, preferred-register: '' }
|
||||
# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
|
||||
# CHECK-NEXT: - { id: 2, class: vecr, preferred-register: '' }
|
||||
# CHECK-NEXT: - { id: 3, class: vecr, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: _, preferred-register: '' }
|
||||
- { id: 1, class: _, preferred-register: '' }
|
||||
- { id: 2, class: _, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# CHECK: %0(s32) = COPY %xmm0
|
||||
# CHECK-NEXT: %1(s32) = G_IMPLICIT_DEF
|
||||
# CHECK-NEXT: %3(s32) = COPY %1(s32)
|
||||
# CHECK-NEXT: %2(s32) = G_FADD %0, %3
|
||||
# CHECK-NEXT: %xmm0 = COPY %2(s32)
|
||||
# CHECK-NEXT: RET 0, implicit %xmm0
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %xmm0
|
||||
|
||||
%0(s32) = COPY %xmm0
|
||||
%1(s32) = G_IMPLICIT_DEF
|
||||
%2(s32) = G_FADD %0, %1
|
||||
%xmm0 = COPY %2(s32)
|
||||
RET 0, implicit %xmm0
|
||||
|
||||
...
|
||||
|
||||
|
71
test/CodeGen/X86/GlobalISel/select-undef.mir
Normal file
71
test/CodeGen/X86/GlobalISel/select-undef.mir
Normal file
@ -0,0 +1,71 @@
|
||||
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL
|
||||
--- |
|
||||
|
||||
define i8 @test() {
|
||||
ret i8 undef
|
||||
}
|
||||
|
||||
define i8 @test2(i8 %a) {
|
||||
%r = add i8 %a, undef
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
# ALL-LABEL: name: test
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# ALL: registers:
|
||||
# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: gpr, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# ALL: %0 = IMPLICIT_DEF
|
||||
# ALL-NEXT: %al = COPY %0
|
||||
# ALL-NEXT: RET 0, implicit %al
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
%0(s8) = G_IMPLICIT_DEF
|
||||
%al = COPY %0(s8)
|
||||
RET 0, implicit %al
|
||||
|
||||
...
|
||||
---
|
||||
name: test2
|
||||
# ALL-LABEL: name: test2
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
# ALL: registers:
|
||||
# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' }
|
||||
# ALL-NEXT: - { id: 1, class: gr8, preferred-register: '' }
|
||||
# ALL-NEXT: - { id: 2, class: gr8, preferred-register: '' }
|
||||
registers:
|
||||
- { id: 0, class: gpr, preferred-register: '' }
|
||||
- { id: 1, class: gpr, preferred-register: '' }
|
||||
- { id: 2, class: gpr, preferred-register: '' }
|
||||
liveins:
|
||||
fixedStack:
|
||||
stack:
|
||||
constants:
|
||||
# ALL: %0 = COPY %dil
|
||||
# ALL-NEXT: %1 = IMPLICIT_DEF
|
||||
# ALL-NEXT: %2 = ADD8rr %0, %1, implicit-def %eflags
|
||||
# ALL-NEXT: %al = COPY %2
|
||||
# ALL-NEXT: RET 0, implicit %al
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
liveins: %edi
|
||||
|
||||
%0(s8) = COPY %edi
|
||||
%1(s8) = G_IMPLICIT_DEF
|
||||
%2(s8) = G_ADD %0, %1
|
||||
%al = COPY %2(s8)
|
||||
RET 0, implicit %al
|
||||
|
||||
...
|
37
test/CodeGen/X86/GlobalISel/undef.ll
Normal file
37
test/CodeGen/X86/GlobalISel/undef.ll
Normal file
@ -0,0 +1,37 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=ALL
|
||||
|
||||
define i8 @test() {
|
||||
; ALL-LABEL: test:
|
||||
; ALL: # BB#0:
|
||||
; ALL-NEXT: retq
|
||||
ret i8 undef
|
||||
}
|
||||
|
||||
define i8 @test2(i8 %a) {
|
||||
; ALL-LABEL: test2:
|
||||
; ALL: # BB#0:
|
||||
; ALL-NEXT: addb %al, %dil
|
||||
; ALL-NEXT: movl %edi, %eax
|
||||
; ALL-NEXT: retq
|
||||
%r = add i8 %a, undef
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
|
||||
define float @test3() {
|
||||
; ALL-LABEL: test3:
|
||||
; ALL: # BB#0:
|
||||
; ALL-NEXT: retq
|
||||
ret float undef
|
||||
}
|
||||
|
||||
define float @test4(float %a) {
|
||||
; ALL-LABEL: test4:
|
||||
; ALL: # BB#0:
|
||||
; ALL-NEXT: addss %xmm0, %xmm0
|
||||
; ALL-NEXT: retq
|
||||
%r = fadd float %a, undef
|
||||
ret float %r
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user