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.

llvm-svn: 188426
This commit is contained in:
Tom Stellard 2013-08-14 23:24:24 +00:00
parent 16a9a205c8
commit df94dc3917
5 changed files with 69 additions and 0 deletions

View File

@ -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<ConstantSDNode>(N->getOperand(0))->getZExtValue());
unsigned SubRegIdx =
dyn_cast<ConstantSDNode>(N->getOperand(OpNo + 1))->getZExtValue();
return TM.getRegisterInfo()->getSubClassWithSubReg(SuperRC, SubRegIdx);
}
}
}
SDValue AMDGPUDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i32);
}

View File

@ -58,6 +58,22 @@ class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
(*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0;
}]>;
class SGPRImm <dag frag> : PatLeaf<frag, [{
if (TM.getSubtarget<AMDGPUSubtarget>().getGeneration() <
AMDGPUSubtarget::SOUTHERN_ISLANDS) {
return false;
}
const SIRegisterInfo *SIRI =
static_cast<const SIRegisterInfo*>(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
//===----------------------------------------------------------------------===//

View File

@ -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)

View File

@ -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;
}

View File

@ -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