diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/X86/X86InstructionSelector.cpp | 93 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/GlobalISel/select-copy.mir | 185 |
2 files changed, 252 insertions, 26 deletions
diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp index 5801163573b..028039d0b0c 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -167,21 +167,72 @@ X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg, return getRegClass(Ty, RegBank); } +unsigned getSubRegIndex(const TargetRegisterClass *RC) { + unsigned SubIdx = X86::NoSubRegister; + if (RC == &X86::GR32RegClass) { + SubIdx = X86::sub_32bit; + } else if (RC == &X86::GR16RegClass) { + SubIdx = X86::sub_16bit; + } else if (RC == &X86::GR8RegClass) { + SubIdx = X86::sub_8bit; + } + + return SubIdx; +} + +const TargetRegisterClass *getRegClassFromGRPhysReg(unsigned Reg) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + if (X86::GR64RegClass.contains(Reg)) + return &X86::GR64RegClass; + if (X86::GR32RegClass.contains(Reg)) + return &X86::GR32RegClass; + if (X86::GR16RegClass.contains(Reg)) + return &X86::GR16RegClass; + if (X86::GR8RegClass.contains(Reg)) + return &X86::GR8RegClass; + + llvm_unreachable("Unknown RegClass for PhysReg!"); +} + // Set X86 Opcode and constrain DestReg. bool X86InstructionSelector::selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const { unsigned DstReg = I.getOperand(0).getReg(); + const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI); + const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI); + + unsigned SrcReg = I.getOperand(1).getReg(); + const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI); + const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI); + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { assert(I.isCopy() && "Generic operators do not allow physical registers"); + + if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID && + DstRegBank.getID() == X86::GPRRegBankID) { + + const TargetRegisterClass *SrcRC = + getRegClass(MRI.getType(SrcReg), SrcRegBank); + const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg); + + if (SrcRC != DstRC) { + // This case can be generated by ABI lowering, performe anyext + unsigned ExtSrc = MRI.createVirtualRegister(DstRC); + BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(TargetOpcode::SUBREG_TO_REG)) + .addDef(ExtSrc) + .addImm(0) + .addReg(SrcReg) + .addImm(getSubRegIndex(SrcRC)); + + I.getOperand(1).setReg(ExtSrc); + } + } + return true; } - const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI); - const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); - unsigned SrcReg = I.getOperand(1).getReg(); - const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI); - assert((!TargetRegisterInfo::isPhysicalRegister(SrcReg) || I.isCopy()) && "No phys reg on generic operators"); assert((DstSize == SrcSize || @@ -191,38 +242,28 @@ bool X86InstructionSelector::selectCopy(MachineInstr &I, DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) && "Copy with different width?!"); - const TargetRegisterClass *RC = nullptr; + const TargetRegisterClass *DstRC = + getRegClass(MRI.getType(DstReg), DstRegBank); - switch (RegBank.getID()) { - case X86::GPRRegBankID: - assert((DstSize <= 64) && "GPRs cannot get more than 64-bit width values."); - RC = getRegClass(MRI.getType(DstReg), RegBank); + if (SrcRegBank.getID() == X86::GPRRegBankID && + DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize && + TargetRegisterInfo::isPhysicalRegister(SrcReg)) { + // Change the physical register to performe truncate. - // Change the physical register - if (SrcSize > DstSize && TargetRegisterInfo::isPhysicalRegister(SrcReg)) { - if (RC == &X86::GR32RegClass) - I.getOperand(1).setSubReg(X86::sub_32bit); - else if (RC == &X86::GR16RegClass) - I.getOperand(1).setSubReg(X86::sub_16bit); - else if (RC == &X86::GR8RegClass) - I.getOperand(1).setSubReg(X86::sub_8bit); + const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg); + if (DstRC != SrcRC) { + I.getOperand(1).setSubReg(getSubRegIndex(DstRC)); I.getOperand(1).substPhysReg(SrcReg, TRI); } - break; - case X86::VECRRegBankID: - RC = getRegClass(MRI.getType(DstReg), RegBank); - break; - default: - llvm_unreachable("Unknown RegBank!"); } // No need to constrain SrcReg. It will get constrained when // we hit another of its use or its defs. // Copies do not have constraints. const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg); - if (!OldRC || !RC->hasSubClassEq(OldRC)) { - if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { + if (!OldRC || !DstRC->hasSubClassEq(OldRC)) { + if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) << " operand\n"); return false; diff --git a/llvm/test/CodeGen/X86/GlobalISel/select-copy.mir b/llvm/test/CodeGen/X86/GlobalISel/select-copy.mir new file mode 100644 index 00000000000..2b5126e9363 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/select-copy.mir @@ -0,0 +1,185 @@ +# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32 +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64 + +--- | + + define void @test_copy() { + ret void + } + + define void @test_copy2() { + ret void + } + + define void @test_copy3() { + ret void + } + + define void @test_copy4() { + ret void + } + + define void @test_copy5() { + ret void + } + + define void @test_copy6() { + ret void + } + +... +--- +name: test_copy +# ALL-LABEL: name: test_copy +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %al +# 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: %eax + + %0(s1) = COPY %al + %1(s32) = G_ZEXT %0(s1) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_copy2 +# ALL-LABEL: name: test_copy2 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %al +# ALL-NEXT: %1 = MOVZX32rr8 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %eax + + %0(s8) = COPY %al + %1(s32) = G_ZEXT %0(s8) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_copy3 +# ALL-LABEL: name: test_copy3 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %al +# ALL-NEXT: %1 = MOVZX32rr8 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %eax + + %0(s8) = COPY %ax + %1(s32) = G_ZEXT %0(s8) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_copy4 +# ALL-LABEL: name: test_copy4 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %ax +# ALL-NEXT: %1 = MOVZX32rr16 %0 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %eax + + %0(s16) = COPY %eax + %1(s32) = G_ZEXT %0(s16) + %eax = COPY %1(s32) + RET 0, implicit %eax + +... +--- +name: test_copy5 +# ALL-LABEL: name: test_copy5 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %dl +# ALL-NEXT: %1 = SUBREG_TO_REG 0, %0, 1 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %eax,%edx + + %0(s8) = COPY %edx + %eax = COPY %0(s8) + RET 0, implicit %eax + +... +--- +name: test_copy6 +# ALL-LABEL: name: test_copy6 +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr16, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } +# ALL: %0 = COPY %dx +# ALL-NEXT: %1 = SUBREG_TO_REG 0, %0, 3 +# ALL-NEXT: %eax = COPY %1 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1 (%ir-block.0): + liveins: %eax,%edx + + %0(s16) = COPY %edx + %eax = COPY %0(s16) + RET 0, implicit %eax + +... + |