From aea899e2a097375118e7b1726247015b79df0379 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Thu, 27 Oct 2016 23:50:21 +0000 Subject: [PATCH] AMDGPU/SI: Handle hazard with s_rfe_b64 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 | 28 ++++++++++++++++++- llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h | 1 + llvm/lib/Target/AMDGPU/SIDefines.h | 7 +++++ .../CodeGen/MIR/AMDGPU/inserted-wait-states.mir | 31 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp index 1df397b..70b7b6b 100644 --- a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp +++ b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp @@ -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; +} diff --git a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h index 8b9ea6a..0ab82ff 100644 --- a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h +++ b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h @@ -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. diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h index ad1bec2..5f7e981 100644 --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -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, diff --git a/llvm/test/CodeGen/MIR/AMDGPU/inserted-wait-states.mir b/llvm/test/CodeGen/MIR/AMDGPU/inserted-wait-states.mir index 4d466d4..7cc9c7c 100644 --- a/llvm/test/CodeGen/MIR/AMDGPU/inserted-wait-states.mir +++ b/llvm/test/CodeGen/MIR/AMDGPU/inserted-wait-states.mir @@ -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 + +... -- 2.7.4