[Mesa-dev] [PATCH] SI: fix SGPR liveness v3
Christian König
deathsimple at vodafone.de
Fri Nov 9 08:01:33 PST 2012
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 <deathsimple at vodafone.de>
Tested-by: Michel Dänzer <michel.daenzer at amd.com>
Reviewed-by: Tom Stellard <thomas.stellard at 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
More information about the mesa-dev
mailing list