Index: lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- lib/Target/X86/X86InstructionSelector.cpp +++ lib/Target/X86/X86InstructionSelector.cpp @@ -85,6 +85,7 @@ 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 @@ return true; if (selectCondBranch(I, MRI, MF)) return true; + if (selectImplicitDef(I, MRI)) + return true; return false; } @@ -1128,6 +1131,29 @@ 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, Index: lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- lib/Target/X86/X86LegalizerInfo.cpp +++ lib/Target/X86/X86LegalizerInfo.cpp @@ -52,6 +52,9 @@ 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 @@ 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); Index: lib/Target/X86/X86RegisterBankInfo.cpp =================================================================== --- lib/Target/X86/X86RegisterBankInfo.cpp +++ lib/Target/X86/X86RegisterBankInfo.cpp @@ -211,7 +211,8 @@ 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) Index: test/CodeGen/X86/GlobalISel/legalize-undef.mir =================================================================== --- /dev/null +++ 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 +... Index: test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir =================================================================== --- test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ 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 @@ 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 + +... Index: test/CodeGen/X86/GlobalISel/select-undef.mir =================================================================== --- /dev/null +++ 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 + +... Index: test/CodeGen/X86/GlobalISel/undef.ll =================================================================== --- /dev/null +++ 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 +} +