From 8dd4b724b5a731bd87353983ed0e0fa4048a6c61 Mon Sep 17 00:00:00 2001 From: Igor Breger Date: Thu, 24 Aug 2017 07:06:27 +0000 Subject: [PATCH] [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 --- lib/Target/X86/X86InstructionSelector.cpp | 26 ++++ lib/Target/X86/X86LegalizerInfo.cpp | 6 + lib/Target/X86/X86RegisterBankInfo.cpp | 3 +- .../CodeGen/X86/GlobalISel/legalize-undef.mir | 29 ++++ .../X86/GlobalISel/regbankselect-X86_64.mir | 135 ++++++++++++++++++ test/CodeGen/X86/GlobalISel/select-undef.mir | 71 +++++++++ test/CodeGen/X86/GlobalISel/undef.ll | 37 +++++ 7 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/X86/GlobalISel/legalize-undef.mir create mode 100644 test/CodeGen/X86/GlobalISel/select-undef.mir create mode 100644 test/CodeGen/X86/GlobalISel/undef.ll diff --git a/lib/Target/X86/X86InstructionSelector.cpp b/lib/Target/X86/X86InstructionSelector.cpp index 8902d7bfcda..be3826a36c5 100644 --- a/lib/Target/X86/X86InstructionSelector.cpp +++ b/lib/Target/X86/X86InstructionSelector.cpp @@ -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, diff --git a/lib/Target/X86/X86LegalizerInfo.cpp b/lib/Target/X86/X86LegalizerInfo.cpp index 05fde0fb92d..f918ad022b5 100644 --- a/lib/Target/X86/X86LegalizerInfo.cpp +++ b/lib/Target/X86/X86LegalizerInfo.cpp @@ -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); diff --git a/lib/Target/X86/X86RegisterBankInfo.cpp b/lib/Target/X86/X86RegisterBankInfo.cpp index a6f16ceffd3..ecb7be9b311 100644 --- a/lib/Target/X86/X86RegisterBankInfo.cpp +++ b/lib/Target/X86/X86RegisterBankInfo.cpp @@ -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) diff --git a/test/CodeGen/X86/GlobalISel/legalize-undef.mir b/test/CodeGen/X86/GlobalISel/legalize-undef.mir new file mode 100644 index 00000000000..83c92dfd2c7 --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/legalize-undef.mir @@ -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 +... diff --git a/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir b/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir index 95ef15ceb68..34e19b28657 100644 --- a/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ b/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir @@ -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 + +... diff --git a/test/CodeGen/X86/GlobalISel/select-undef.mir b/test/CodeGen/X86/GlobalISel/select-undef.mir new file mode 100644 index 00000000000..66d9e6eae23 --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/select-undef.mir @@ -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 + +... diff --git a/test/CodeGen/X86/GlobalISel/undef.ll b/test/CodeGen/X86/GlobalISel/undef.ll new file mode 100644 index 00000000000..cd82766be97 --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/undef.ll @@ -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 +} +