SGPRs are not affected by control flow. v2: don't use liveness analyse any more, handle partial dominated end notes. v3: fix old pass name in CMakeLists.txt
Signed-off-by: Christian König <deathsim...@vodafone.de> Tested-by: Michel Dänzer <michel.daen...@amd.com> Reviewed-by: Tom Stellard <thomas.stell...@amd.com> --- lib/Target/AMDGPU/AMDGPU.h | 1 + lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 3 + lib/Target/AMDGPU/CMakeLists.txt | 1 + lib/Target/AMDGPU/SIFixSGPRLiveness.cpp | 192 +++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 lib/Target/AMDGPU/SIFixSGPRLiveness.cpp diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h index c722d04..33a74dc 100644 --- a/lib/Target/AMDGPU/AMDGPU.h +++ b/lib/Target/AMDGPU/AMDGPU.h @@ -28,6 +28,7 @@ FunctionPass *createSIAssignInterpRegsPass(TargetMachine &tm); FunctionPass *createSILowerFlowControlPass(TargetMachine &tm); FunctionPass *createSICodeEmitterPass(formatted_raw_ostream &OS); FunctionPass *createSILowerLiteralConstantsPass(TargetMachine &tm); +FunctionPass *createSIFixSGPRLivenessPass(TargetMachine &tm); // Passes common to R600 and SI FunctionPass *createAMDGPUConvertToISAPass(TargetMachine &tm); diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index dd4b733..024ff3d 100644 --- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -111,6 +111,9 @@ bool AMDGPUPassConfig::addPreRegAlloc() { addPass(createSIAssignInterpRegsPass(*TM)); } addPass(createAMDGPUConvertToISAPass(*TM)); + if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) { + addPass(createSIFixSGPRLivenessPass(*TM)); + } return false; } diff --git a/lib/Target/AMDGPU/CMakeLists.txt b/lib/Target/AMDGPU/CMakeLists.txt index 6bb7ba0..2a1f052 100644 --- a/lib/Target/AMDGPU/CMakeLists.txt +++ b/lib/Target/AMDGPU/CMakeLists.txt @@ -44,6 +44,7 @@ add_llvm_target(AMDGPUCodeGen SILowerFlowControl.cpp SIMachineFunctionInfo.cpp SIRegisterInfo.cpp + SIFixSGPRLiveness.cpp ) add_dependencies(LLVMAMDGPUCodeGen intrinsics_gen) diff --git a/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp b/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp new file mode 100644 index 0000000..028753e --- /dev/null +++ b/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp @@ -0,0 +1,192 @@ +//===-- SIFixSGPRLiveness.cpp - SGPR liveness adjustment ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SGPRs are not affected by flow control. This pass adjust SGPR liveness in +// so that the register allocator can still correctly allocate them. +// +//===----------------------------------------------------------------------===// + +#include "AMDGPU.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachinePostDominators.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; + +namespace { + +class SIFixSGPRLiveness : public MachineFunctionPass { +private: + static char ID; + + const TargetInstrInfo *TII; + MachineRegisterInfo *MRI; + MachineDominatorTree *MD; + MachinePostDominatorTree *MPD; + + bool isSGPR(const TargetRegisterClass *RegClass) + { + return RegClass == &AMDGPU::SReg_1RegClass || + RegClass == &AMDGPU::SReg_32RegClass || + RegClass == &AMDGPU::SReg_64RegClass || + RegClass == &AMDGPU::SReg_128RegClass || + RegClass == &AMDGPU::SReg_256RegClass; + } + + void addKill(MachineBasicBlock::iterator I, unsigned Reg); + MachineBasicBlock *handleUses(unsigned VirtReg, MachineBasicBlock *Begin); + MachineBasicBlock *handleSuccs(MachineBasicBlock *Begin, + MachineBasicBlock *End); + void handlePreds(MachineBasicBlock *Begin, MachineBasicBlock *End, + unsigned VirtReg); + + bool handleVirtReg(unsigned VirtReg); + +public: + SIFixSGPRLiveness(TargetMachine &tm); + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "SI fix SGPR liveness pass"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} // end anonymous namespace + +char SIFixSGPRLiveness::ID = 0; + +SIFixSGPRLiveness::SIFixSGPRLiveness(TargetMachine &tm): + MachineFunctionPass(ID), + TII(tm.getInstrInfo()) +{ + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); +} + +void SIFixSGPRLiveness::getAnalysisUsage(AnalysisUsage &AU) const +{ + AU.addRequired<MachineDominatorTree>(); + AU.addRequired<MachinePostDominatorTree>(); + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void SIFixSGPRLiveness::addKill(MachineBasicBlock::iterator I, unsigned Reg) +{ + MachineBasicBlock *MBB = I->getParent(); + + BuildMI(*MBB, I, DebugLoc(), TII->get(TargetOpcode::KILL)).addReg(Reg); +} + +// Find the common post dominator of all uses +MachineBasicBlock *SIFixSGPRLiveness::handleUses(unsigned VirtReg, + MachineBasicBlock *Begin) +{ + MachineBasicBlock *LastUse = Begin, *End = Begin; + + MachineRegisterInfo::use_iterator i, e; + for (i = MRI->use_begin(VirtReg), e = MRI->use_end(); i != e; ++i) { + MachineBasicBlock *MBB = i->getParent(); + if (LastUse == MBB) + continue; + + LastUse = MBB; + End = MPD->findNearestCommonDominator(End, MBB); + } + + return End; +} + +// Find the common post dominator of all successors +MachineBasicBlock *SIFixSGPRLiveness::handleSuccs(MachineBasicBlock *Begin, + MachineBasicBlock *End) +{ + MachineBasicBlock::succ_iterator i, e; + for (i = Begin->succ_begin(), e = Begin->succ_end(); i != e; ++i) { + End = MPD->findNearestCommonDominator(End, *i); + } + return End; +} + +// Handles predecessors separately, only add KILLs to dominated ones +void SIFixSGPRLiveness::handlePreds(MachineBasicBlock *Begin, + MachineBasicBlock *End, + unsigned VirtReg) +{ + MachineBasicBlock::pred_iterator i, e; + for (i = End->pred_begin(), e = End->pred_end(); i != e; ++i) { + + if (MD->dominates(End, *i)) + continue; // ignore loops + + if (MD->dominates(*i, Begin)) + continue; // too far up, abort search + + if (MD->dominates(Begin, *i)) { + // found end of livetime + addKill((*i)->getFirstTerminator(), VirtReg); + continue; + } + + handlePreds(Begin, *i, VirtReg); + } +} + +bool SIFixSGPRLiveness::handleVirtReg(unsigned VirtReg) +{ + + MachineInstr *Def = MRI->getVRegDef(VirtReg); + if (!Def || MRI->use_empty(VirtReg)) + return false; // No definition or not used + + MachineBasicBlock *Begin = Def->getParent(); + MachineBasicBlock *End = handleUses(VirtReg, Begin); + if (Begin == End) + return false; // Defined and only used in the same block + + End = handleSuccs(Begin, End); + if (MD->dominates(Begin, End)) { + // Lifetime dominate the end node, just kill it here + addKill(End->getFirstNonPHI(), VirtReg); + } else { + // only some predecessors are dominate, handle them separately + handlePreds(Begin, End, VirtReg); + } + return true; +} + +bool SIFixSGPRLiveness::runOnMachineFunction(MachineFunction &MF) +{ + bool Changes = false; + + MRI = &MF.getRegInfo(); + MD = &getAnalysis<MachineDominatorTree>(); + MPD = &getAnalysis<MachinePostDominatorTree>(); + + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned VirtReg = TargetRegisterInfo::index2VirtReg(i); + + const TargetRegisterClass *RegClass = MRI->getRegClass(VirtReg); + if (!isSGPR(RegClass)) + continue; + + Changes |= handleVirtReg(VirtReg); + } + + return Changes; +} + +FunctionPass *llvm::createSIFixSGPRLivenessPass(TargetMachine &tm) +{ + return new SIFixSGPRLiveness(tm); +} -- 1.7.9.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev