Index: lib/Target/AMDGPU/AMDGPUTargetMachine.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -42,6 +42,9 @@ // Register the target RegisterTargetMachine X(TheAMDGPUTarget); RegisterTargetMachine Y(TheGCNTarget); + + PassRegistry *PR = PassRegistry::getPassRegistry(); + initializeSIFixSGPRLiveRangesPass(*PR); } static std::unique_ptr createTLOF(const Triple &TT) { @@ -160,6 +163,8 @@ : AMDGPUPassConfig(TM, PM) { } bool addPreISel() override; bool addInstSelector() override; + void addFastRegAlloc(FunctionPass *RegAllocPass) override; + void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override; void addPreRegAlloc() override; void addPostRegAlloc() override; void addPreSched2() override; @@ -294,7 +299,18 @@ insertPass(&MachineSchedulerID, &RegisterCoalescerID); } addPass(createSIShrinkInstructionsPass(), false); - addPass(createSIFixSGPRLiveRangesPass()); +} + +void GCNPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) { + addPass(&SIFixSGPRLiveRangesID); + TargetPassConfig::addFastRegAlloc(RegAllocPass); +} + +void GCNPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) { + // We want to run this after LiveVariables is computed to avoid computing them + // twice. + insertPass(&LiveVariablesID, &SIFixSGPRLiveRangesID); + TargetPassConfig::addOptimizedRegAlloc(RegAllocPass); } void GCNPassConfig::addPostRegAlloc() { Index: lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp =================================================================== --- lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp +++ lib/Target/AMDGPU/SIFixSGPRLiveRanges.cpp @@ -80,13 +80,13 @@ } void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); AU.setPreservesCFG(); - //AU.addPreserved(); // XXX - This might be OK - AU.addPreserved(); - MachineFunctionPass::getAnalysisUsage(AU); } }; @@ -95,7 +95,6 @@ INITIALIZE_PASS_BEGIN(SIFixSGPRLiveRanges, DEBUG_TYPE, "SI Fix SGPR Live Ranges", false, false) -INITIALIZE_PASS_DEPENDENCY(LiveIntervals) INITIALIZE_PASS_DEPENDENCY(LiveVariables) INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree) INITIALIZE_PASS_END(SIFixSGPRLiveRanges, DEBUG_TYPE, @@ -109,6 +108,15 @@ return new SIFixSGPRLiveRanges(); } +static bool isPhysRegLiveOut(unsigned Reg, const MachineBasicBlock &MBB) { + for (const MachineBasicBlock *Succ : MBB.successors()) { + if (Succ->isLiveIn(Reg)) + return true; + } + + return false; +} + bool SIFixSGPRLiveRanges::runOnMachineFunction(MachineFunction &MF) { MachineRegisterInfo &MRI = MF.getRegInfo(); const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); @@ -117,10 +125,9 @@ bool MadeChange = false; MachinePostDominatorTree *PDT = &getAnalysis(); - std::vector> SGPRLiveRanges; + SmallVector SGPRLiveRanges; - LiveIntervals *LIS = &getAnalysis(); - LiveVariables *LV = getAnalysisIfAvailable(); + LiveVariables *LV = &getAnalysis(); MachineBasicBlock *Entry = MF.begin(); // Use a depth first order so that in SSA, we encounter all defs before @@ -136,12 +143,17 @@ if (TRI->isSGPRClass(MRI.getRegClass(Def))) { // Only consider defs that are live outs. We don't care about def / // use within the same block. - LiveRange &LR = LIS->getInterval(Def); - if (LIS->isLiveOutOfMBB(LR, MBB)) - SGPRLiveRanges.push_back(std::make_pair(Def, &LR)); + + // LiveVariables does not consider registers that are only used in a + // phi in a sucessor block as live out, unlike LiveIntervals. + // + // This is OK because SIFixSGPRCopies replaced any SGPR phis with + // VGPRs. + if (LV->isLiveOut(Def, *MBB)) + SGPRLiveRanges.push_back(Def); } - } else if (TRI->isSGPRClass(TRI->getPhysRegClass(Def))) { - SGPRLiveRanges.push_back(std::make_pair(Def, &LIS->getRegUnit(Def))); + } else { + assert(!isPhysRegLiveOut(Def, *MBB) && "Should never see physical reg live outs"); } } } @@ -169,16 +181,13 @@ *(++NCD->succ_begin())); } - for (std::pair RegLR : SGPRLiveRanges) { - unsigned Reg = RegLR.first; - LiveRange *LR = RegLR.second; - + for (unsigned Reg : SGPRLiveRanges) { // FIXME: We could be smarter here. If the register is Live-In to one // block, but the other doesn't have any SGPR defs, then there won't be a // conflict. Also, if the branch condition is uniform then there will be // no conflict. - bool LiveInToA = LIS->isLiveInToMBB(*LR, SuccA); - bool LiveInToB = LIS->isLiveInToMBB(*LR, SuccB); + bool LiveInToA = LV->isLiveIn(Reg, *SuccA); + bool LiveInToB = LV->isLiveIn(Reg, *SuccB); if (!LiveInToA && !LiveInToB) { DEBUG(dbgs() << PrintReg(Reg, TRI, 0) @@ -195,9 +204,9 @@ // This interval is live in to one successor, but not the other, so // we need to update its range so it is live in to both. DEBUG(dbgs() << "Possible SGPR conflict detected for " - << PrintReg(Reg, TRI, 0) << " in " << *LR - << " BB#" << SuccA->getNumber() << ", BB#" - << SuccB->getNumber() + << PrintReg(Reg, TRI, 0) + << " BB#" << SuccA->getNumber() + << ", BB#" << SuccB->getNumber() << " with NCD = BB#" << NCD->getNumber() << '\n'); assert(TargetRegisterInfo::isVirtualRegister(Reg) && @@ -211,14 +220,7 @@ .addReg(Reg, RegState::Implicit); MadeChange = true; - - SlotIndex SI = LIS->InsertMachineInstrInMaps(NCDSGPRUse); - LIS->extendToIndices(*LR, SI.getRegSlot()); - - if (LV) { - // TODO: This won't work post-SSA - LV->HandleVirtRegUse(Reg, NCD, NCDSGPRUse); - } + LV->HandleVirtRegUse(Reg, NCD, NCDSGPRUse); DEBUG(NCDSGPRUse->dump()); }