1 //===--- AMDGPUExportClusting.cpp - AMDGPU Export Clustering -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file This file contains a DAG scheduling mutation to cluster shader 10 /// exports. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPUExportClustering.h" 15 #include "AMDGPUSubtarget.h" 16 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 17 #include "SIInstrInfo.h" 18 19 using namespace llvm; 20 21 namespace { 22 23 class ExportClustering : public ScheduleDAGMutation { 24 public: 25 ExportClustering() {} 26 void apply(ScheduleDAGInstrs *DAG) override; 27 }; 28 29 static bool isExport(const SUnit &SU) { 30 const MachineInstr *MI = SU.getInstr(); 31 return MI->getOpcode() == AMDGPU::EXP || 32 MI->getOpcode() == AMDGPU::EXP_DONE; 33 } 34 35 static void buildCluster(ArrayRef<SUnit *> Exports, ScheduleDAGInstrs *DAG) { 36 // Cluster a series of exports. Also copy all dependencies to the first 37 // export to avoid computation being inserted into the chain. 38 SUnit *ChainHead = Exports[0]; 39 for (unsigned Idx = 0, End = Exports.size() - 1; Idx < End; ++Idx) { 40 SUnit *SUa = Exports[Idx]; 41 SUnit *SUb = Exports[Idx + 1]; 42 if (DAG->addEdge(SUb, SDep(SUa, SDep::Cluster))) { 43 for (const SDep &Pred : SUb->Preds) { 44 SUnit *PredSU = Pred.getSUnit(); 45 if (Pred.isWeak() || isExport(*PredSU)) 46 continue; 47 DAG->addEdge(ChainHead, SDep(PredSU, SDep::Artificial)); 48 } 49 } 50 } 51 } 52 53 void ExportClustering::apply(ScheduleDAGInstrs *DAG) { 54 SmallVector<SmallVector<SUnit *, 8>, 4> ExportChains; 55 DenseMap<unsigned, unsigned> ChainMap; 56 57 // Build chains of exports 58 for (SUnit &SU : DAG->SUnits) { 59 if (!isExport(SU)) 60 continue; 61 62 unsigned ChainID = ExportChains.size(); 63 for (const SDep &Pred : SU.Preds) { 64 const SUnit &PredSU = *Pred.getSUnit(); 65 if (isExport(PredSU) && !Pred.isArtificial()) { 66 ChainID = ChainMap.lookup(PredSU.NodeNum); 67 break; 68 } 69 } 70 ChainMap[SU.NodeNum] = ChainID; 71 72 if (ChainID == ExportChains.size()) 73 ExportChains.push_back(SmallVector<SUnit *, 8>()); 74 75 auto &Chain = ExportChains[ChainID]; 76 Chain.push_back(&SU); 77 } 78 79 // Apply clustering 80 for (auto &Chain : ExportChains) 81 buildCluster(Chain, DAG); 82 } 83 84 } // end namespace 85 86 namespace llvm { 87 88 std::unique_ptr<ScheduleDAGMutation> createAMDGPUExportClusteringDAGMutation() { 89 return std::make_unique<ExportClustering>(); 90 } 91 92 } // end namespace llvm 93