diff options
| author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-07-15 19:50:07 +0000 |
|---|---|---|
| committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-07-15 19:50:07 +0000 |
| commit | c8291c94f8393162241a798df49ba53fddc49976 (patch) | |
| tree | c0bcbdadd6f9a118d890c167b73009ae97d00642 /llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp | |
| parent | ad19b50c000762c2c7c50ad8f171cbc60ca060d0 (diff) | |
| download | bcm5719-llvm-c8291c94f8393162241a798df49ba53fddc49976.tar.gz bcm5719-llvm-c8291c94f8393162241a798df49ba53fddc49976.zip | |
AMDGPU/GlobalISel: Select G_AND/G_OR/G_XOR
llvm-svn: 366121
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp')
| -rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp index e57478b00ee..fd5ee293d6c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -67,6 +67,8 @@ static bool isSCC(Register Reg, const MachineRegisterInfo &MRI) { const TargetRegisterClass *RC = RegClassOrBank.dyn_cast<const TargetRegisterClass*>(); if (RC) { + // FIXME: This is ambiguous for wave32. This could be SCC or VCC, but the + // context of the register bank has been lost. if (RC->getID() != AMDGPU::SReg_32_XM0RegClassID) return false; const LLT Ty = MRI.getType(Reg); @@ -244,6 +246,63 @@ static int64_t getConstant(const MachineInstr *MI) { return MI->getOperand(1).getCImm()->getSExtValue(); } +static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64) { + switch (Opc) { + case AMDGPU::G_AND: + return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32; + case AMDGPU::G_OR: + return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32; + case AMDGPU::G_XOR: + return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32; + default: + llvm_unreachable("not a bit op"); + } +} + +bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(MachineInstr &I) const { + MachineBasicBlock *BB = I.getParent(); + MachineFunction *MF = BB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineOperand &Dst = I.getOperand(0); + MachineOperand &Src0 = I.getOperand(1); + MachineOperand &Src1 = I.getOperand(2); + Register DstReg = Dst.getReg(); + unsigned Size = RBI.getSizeInBits(DstReg, MRI, TRI); + + const RegisterBank *DstRB = RBI.getRegBank(DstReg, MRI, TRI); + if (DstRB->getID() == AMDGPU::VCCRegBankID) { + const TargetRegisterClass *RC = TRI.getBoolRC(); + unsigned InstOpc = getLogicalBitOpcode(I.getOpcode(), + RC == &AMDGPU::SReg_64RegClass); + I.setDesc(TII.get(InstOpc)); + + // FIXME: Hack to avoid turning the register bank into a register class. + // The selector for G_ICMP relies on seeing the register bank for the result + // is VCC. In wave32 if we constrain the registers to SReg_32 here, it will + // be ambiguous whether it's a scalar or vector bool. + if (Src0.isUndef() && !MRI.getRegClassOrNull(Src0.getReg())) + MRI.setRegClass(Src0.getReg(), RC); + if (Src1.isUndef() && !MRI.getRegClassOrNull(Src1.getReg())) + MRI.setRegClass(Src1.getReg(), RC); + + return RBI.constrainGenericRegister(DstReg, *RC, MRI); + } + + // TODO: Should this allow an SCC bank result, and produce a copy from SCC for + // the result? + if (DstRB->getID() == AMDGPU::SGPRRegBankID) { + const TargetRegisterClass *RC + = TRI.getConstrainedRegClassForOperand(Dst, MRI); + unsigned InstOpc = getLogicalBitOpcode(I.getOpcode(), Size > 32); + I.setDesc(TII.get(InstOpc)); + return RBI.constrainGenericRegister(DstReg, *RC, MRI) && + RBI.constrainGenericRegister(Src0.getReg(), *RC, MRI) && + RBI.constrainGenericRegister(Src1.getReg(), *RC, MRI); + } + + return false; +} + bool AMDGPUInstructionSelector::selectG_ADD_SUB(MachineInstr &I) const { MachineBasicBlock *BB = I.getParent(); MachineFunction *MF = BB->getParent(); @@ -1293,6 +1352,12 @@ bool AMDGPUInstructionSelector::select(MachineInstr &I, } switch (I.getOpcode()) { + case TargetOpcode::G_AND: + case TargetOpcode::G_OR: + case TargetOpcode::G_XOR: + if (selectG_AND_OR_XOR(I)) + return true; + return selectImpl(I, CoverageInfo); case TargetOpcode::G_ADD: case TargetOpcode::G_SUB: if (selectG_ADD_SUB(I)) |

