AMDGPU/SI: Handle hazard with s_rfe_b64
authorTom Stellard <thomas.stellard@amd.com>
Thu, 27 Oct 2016 23:50:21 +0000 (23:50 +0000)
committerTom Stellard <thomas.stellard@amd.com>
Thu, 27 Oct 2016 23:50:21 +0000 (23:50 +0000)
Reviewers: arsenm

Subscribers: kzhuravl, wdng, nhaehnle, yaxunl, llvm-commits, tony-tye

Differential Revision: https://reviews.llvm.org/D25638

llvm-svn: 285368

llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp
llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h
llvm/lib/Target/AMDGPU/SIDefines.h
llvm/test/CodeGen/MIR/AMDGPU/inserted-wait-states.mir

index 1df397b..70b7b6b 100644 (file)
@@ -54,7 +54,11 @@ static bool isRWLane(unsigned Opcode) {
   return Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32;
 }
 
-static bool getHWReg(const SIInstrInfo *TII, const MachineInstr &RegInstr) {
+static bool isRFE(unsigned Opcode) {
+  return Opcode == AMDGPU::S_RFE_B64;
+}
+
+static unsigned getHWReg(const SIInstrInfo *TII, const MachineInstr &RegInstr) {
 
   const MachineOperand *RegOp = TII->getNamedOperand(RegInstr,
                                                      AMDGPU::OpName::simm16);
@@ -89,6 +93,9 @@ GCNHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
   if (isSSetReg(MI->getOpcode()) && checkSetRegHazards(MI) > 0)
     return NoopHazard;
 
+  if (isRFE(MI->getOpcode()) && checkRFEHazards(MI) > 0)
+    return NoopHazard;
+
   return NoHazard;
 }
 
@@ -124,6 +131,9 @@ unsigned GCNHazardRecognizer::PreEmitNoops(MachineInstr *MI) {
   if (isSSetReg(MI->getOpcode()))
     return std::max(0, checkSetRegHazards(MI));
 
+  if (isRFE(MI->getOpcode()))
+    return std::max(0, checkRFEHazards(MI));
+
   return 0;
 }
 
@@ -470,3 +480,19 @@ int GCNHazardRecognizer::checkRWLaneHazards(MachineInstr *RWLane) {
   int WaitStatesSince = getWaitStatesSinceDef(LaneSelectReg, IsHazardFn);
   return RWLaneWaitStates - WaitStatesSince;
 }
+
+int GCNHazardRecognizer::checkRFEHazards(MachineInstr *RFE) {
+
+  if (ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
+    return 0;
+
+  const SIInstrInfo *TII = ST.getInstrInfo();
+
+  const int RFEWaitStates = 1;
+
+  auto IsHazardFn = [TII] (MachineInstr *MI) {
+    return getHWReg(TII, *MI) == AMDGPU::Hwreg::ID_TRAPSTS;
+  };
+  int WaitStatesNeeded = getWaitStatesSinceSetReg(IsHazardFn);
+  return RFEWaitStates - WaitStatesNeeded;
+}
index 8b9ea6a..0ab82ff 100644 (file)
@@ -51,6 +51,7 @@ class GCNHazardRecognizer final : public ScheduleHazardRecognizer {
   int createsVALUHazard(const MachineInstr &MI);
   int checkVALUHazards(MachineInstr *VALU);
   int checkRWLaneHazards(MachineInstr *RWLane);
+  int checkRFEHazards(MachineInstr *RFE);
 public:
   GCNHazardRecognizer(const MachineFunction &MF);
   // We can only issue one instruction per cycle.
index ad1bec2..5f7e981 100644 (file)
@@ -207,6 +207,13 @@ namespace Hwreg { // Encoding of SIMM16 used in s_setreg/getreg* insns.
 enum Id { // HwRegCode, (6) [5:0]
   ID_UNKNOWN_ = -1,
   ID_SYMBOLIC_FIRST_ = 1, // There are corresponding symbolic names defined.
+  ID_MODE = 1,
+  ID_STATUS = 2,
+  ID_TRAPSTS = 3,
+  ID_HW_ID = 4,
+  ID_GPR_ALLOC = 5,
+  ID_LDS_ALLOC = 6,
+  ID_IB_STS = 7,
   ID_SYMBOLIC_LAST_ = 8,
   ID_SHIFT_ = 0,
   ID_WIDTH_ = 6,
index 4d466d4..7cc9c7c 100644 (file)
@@ -8,6 +8,7 @@
   define void @s_setreg() { ret void }
   define void @vmem_gt_8dw_store() { ret void }
   define void @readwrite_lane() { ret void }
+  define void @rfe() { ret void }
 ...
 ---
 # GCN-LABEL: name: div_fmas
@@ -300,3 +301,33 @@ body: |
     S_ENDPGM
 
 ...
+
+...
+---
+
+# GCN-LABEL: name: rfe
+
+# GCN-LABEL: bb.0:
+# GCN: S_SETREG
+# VI: S_NOP
+# GCN-NEXT: S_RFE_B64
+
+# GCN-LABEL: bb.1:
+# GCN: S_SETREG
+# GCN-NEXT: S_RFE_B64
+
+name: rfe
+
+body: |
+  bb.0:
+    successors: %bb.1
+    S_SETREG_B32 %sgpr0, 3
+    S_RFE_B64 %sgpr2_sgpr3
+    S_BRANCH %bb.1
+
+  bb.1:
+    S_SETREG_B32 %sgpr0, 0
+    S_RFE_B64 %sgpr2_sgpr3
+    S_ENDPGM
+
+...