R600/SI: Choose the correct MOV instruction for copying immediates
authorTom Stellard <thomas.stellard@amd.com>
Wed, 14 Aug 2013 23:24:24 +0000 (23:24 +0000)
committerTom Stellard <thomas.stellard@amd.com>
Wed, 14 Aug 2013 23:24:24 +0000 (23:24 +0000)
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
lib/Target/R600/SIInstrInfo.td
lib/Target/R600/SIInstructions.td
lib/Target/R600/SIRegisterInfo.cpp
lib/Target/R600/SIRegisterInfo.h

index f222901b8fc1151d672e29c4e92aa948ceb11e24..d339b09b9e148cdc2cf4430c54dae17edde525c7 100644 (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);
 }
index 71d20eaa0fb6a5a9eb0910ca65f9e2fa0eff1bd2..df6d99410d9beda9c6502743505a4281b77775fb 100644 (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
 //===----------------------------------------------------------------------===//
index 5fbd68f3e7c7cd296ee611baba974a0fd732d737..b20d7c0533a546914e4338fa20672dfdce9f8979 100644 (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)
index 50fd4c7ed56397ebdb21995c02cd80cc466a1411..5d12564fe8ba8839d36a110426946eb5f5f8a9b9 100644 (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;
+}
index d0df4f9de60db54d565045efdf859f49cc1b3bd6..ffc57973e052f94a3e6cea36729aef3483499730 100644 (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