From 636298ba64fd07d4ddcae6005e7fc1db43eb5335 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 14 Aug 2013 23:24:24 +0000 Subject: [PATCH] R600/SI: Choose the correct MOV instruction for copying immediates The instruction selector will now try to infer the destination register so it can decided whether to use V_MOV_B32 or S_MOV_B32 when copying immediates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188426 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/R600/AMDGPUISelDAGToDAG.cpp | 29 ++++++++++++++++++++++++++ lib/Target/R600/SIInstrInfo.td | 16 ++++++++++++++ lib/Target/R600/SIInstructions.td | 10 +++++++++ lib/Target/R600/SIRegisterInfo.cpp | 11 ++++++++++ lib/Target/R600/SIRegisterInfo.h | 3 +++ 5 files changed, 69 insertions(+) diff --git a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp index f222901b8fc..d339b09b9e1 100644 --- a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp +++ b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp @@ -77,6 +77,7 @@ private: bool isLocalLoad(const LoadSDNode *N) const; bool isRegionLoad(const LoadSDNode *N) const; + const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr); bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, SDValue& Offset); @@ -102,6 +103,34 @@ AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM) AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() { } +/// \brief Determine the register class for \p OpNo +/// \returns The register class of the virtual register that will be used for +/// the given operand number \OpNo or NULL if the register class cannot be +/// determined. +const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N, + unsigned OpNo) const { + if (!N->isMachineOpcode()) { + return NULL; + } + switch (N->getMachineOpcode()) { + default: { + const MCInstrDesc &Desc = TM.getInstrInfo()->get(N->getMachineOpcode()); + int RegClass = Desc.OpInfo[Desc.getNumDefs() + OpNo].RegClass; + if (RegClass == -1) { + return NULL; + } + return TM.getRegisterInfo()->getRegClass(RegClass); + } + case AMDGPU::REG_SEQUENCE: { + const TargetRegisterClass *SuperRC = TM.getRegisterInfo()->getRegClass( + cast(N->getOperand(0))->getZExtValue()); + unsigned SubRegIdx = + dyn_cast(N->getOperand(OpNo + 1))->getZExtValue(); + return TM.getRegisterInfo()->getSubClassWithSubReg(SuperRC, SubRegIdx); + } + } +} + SDValue AMDGPUDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) { return CurDAG->getTargetConstant(Imm, MVT::i32); } diff --git a/lib/Target/R600/SIInstrInfo.td b/lib/Target/R600/SIInstrInfo.td index 71d20eaa0fb..df6d99410d9 100644 --- a/lib/Target/R600/SIInstrInfo.td +++ b/lib/Target/R600/SIInstrInfo.td @@ -58,6 +58,22 @@ class InlineImm : PatLeaf <(vt imm), [{ (*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0; }]>; +class SGPRImm : PatLeaf().getGeneration() < + AMDGPUSubtarget::SOUTHERN_ISLANDS) { + return false; + } + const SIRegisterInfo *SIRI = + static_cast(TM.getRegisterInfo()); + for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end(); + U != E; ++U) { + if (SIRI->isSGPRClass(getOperandRegClass(*U, U.getOperandNo()))) { + return true; + } + } + return false; +}]>; + //===----------------------------------------------------------------------===// // SI assembler operands //===----------------------------------------------------------------------===// diff --git a/lib/Target/R600/SIInstructions.td b/lib/Target/R600/SIInstructions.td index 5fbd68f3e7c..b20d7c0533a 100644 --- a/lib/Target/R600/SIInstructions.td +++ b/lib/Target/R600/SIInstructions.td @@ -1582,6 +1582,16 @@ def : Pat < /********** Immediate Patterns **********/ /********** ================== **********/ +def : Pat < + (SGPRImm<(i32 imm)>:$imm), + (S_MOV_B32 imm:$imm) +>; + +def : Pat < + (SGPRImm<(f32 fpimm)>:$imm), + (S_MOV_B32 fpimm:$imm) +>; + def : Pat < (i32 imm:$imm), (V_MOV_B32_e32 imm:$imm) diff --git a/lib/Target/R600/SIRegisterInfo.cpp b/lib/Target/R600/SIRegisterInfo.cpp index 50fd4c7ed56..5d12564fe8b 100644 --- a/lib/Target/R600/SIRegisterInfo.cpp +++ b/lib/Target/R600/SIRegisterInfo.cpp @@ -70,3 +70,14 @@ const TargetRegisterClass *SIRegisterInfo::getPhysRegClass(unsigned Reg) const { } return NULL; } + +bool SIRegisterInfo::isSGPRClass(const TargetRegisterClass *RC) const { + if (!RC) { + return false; + } + return RC == &AMDGPU::SReg_32RegClass || + RC == &AMDGPU::SReg_64RegClass || + RC == &AMDGPU::SReg_128RegClass || + RC == &AMDGPU::SReg_256RegClass || + RC == &AMDGPU::SReg_512RegClass; +} diff --git a/lib/Target/R600/SIRegisterInfo.h b/lib/Target/R600/SIRegisterInfo.h index d0df4f9de60..ffc57973e05 100644 --- a/lib/Target/R600/SIRegisterInfo.h +++ b/lib/Target/R600/SIRegisterInfo.h @@ -45,6 +45,9 @@ struct SIRegisterInfo : public AMDGPURegisterInfo { /// \brief Return the 'base' register class for this register. /// e.g. SGPR0 => SReg_32, VGPR => VReg_32 SGPR0_SGPR1 -> SReg_32, etc. const TargetRegisterClass *getPhysRegClass(unsigned Reg) const; + + /// \returns true if this class contains only SGPR registers + bool isSGPRClass(const TargetRegisterClass *RC) const; }; } // End namespace llvm