[Mesa-dev] [PATCH] SI: fix SGPR liveness v5
Christian König
deathsimple at vodafone.de
Wed Nov 14 05:18:07 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
v4: remove unnecessary successor handling and kill handling
v5: adjust live analysis directly
Signed-off-by: Christian König <deathsimple at vodafone.de>
---
lib/Target/AMDGPU/AMDGPU.h | 3 +
lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 9 +-
lib/Target/AMDGPU/CMakeLists.txt | 1 +
lib/Target/AMDGPU/SIFixSGPRLiveness.cpp | 190 +++++++++++++++++++++++++++++
4 files changed, 202 insertions(+), 1 deletion(-)
create mode 100644 lib/Target/AMDGPU/SIFixSGPRLiveness.cpp
diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h
index c722d04..95625d2 100644
--- a/lib/Target/AMDGPU/AMDGPU.h
+++ b/lib/Target/AMDGPU/AMDGPU.h
@@ -29,6 +29,9 @@ FunctionPass *createSILowerFlowControlPass(TargetMachine &tm);
FunctionPass *createSICodeEmitterPass(formatted_raw_ostream &OS);
FunctionPass *createSILowerLiteralConstantsPass(TargetMachine &tm);
+void initializeSIFixSGPRLivenessPass(PassRegistry &Registry);
+extern char &SIFixSGPRLivenessID;
+
// 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..cf4006e 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -73,7 +73,14 @@ namespace {
class AMDGPUPassConfig : public TargetPassConfig {
public:
AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
- : TargetPassConfig(TM, PM) {}
+ : TargetPassConfig(TM, PM) {
+
+ const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
+ if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
+ initializeSIFixSGPRLivenessPass(*PassRegistry::getPassRegistry());
+ insertPass(&TwoAddressInstructionPassID, &SIFixSGPRLivenessID);
+ }
+ }
AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
return getTM<AMDGPUTargetMachine>();
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..77f58f8
--- /dev/null
+++ b/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp
@@ -0,0 +1,190 @@
+//===-- 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/ADT/DepthFirstIterator.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachinePostDominators.h"
+
+using namespace llvm;
+
+namespace {
+
+class SIFixSGPRLiveness : public MachineFunctionPass {
+private:
+
+ MachineRegisterInfo *MRI;
+ MachineDominatorTree *MD;
+ MachinePostDominatorTree *MPD;
+ LiveIntervals *LI;
+
+ 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 getBegin(unsigned VirtReg, MachineInstr *&BeginDef,
+ MachineBasicBlock *&Begin);
+
+ void getEnd(unsigned VirtReg, bool &EndUses,
+ MachineBasicBlock *&End);
+
+ void handleVirtReg(unsigned VirtReg);
+
+public:
+ static char ID;
+
+ SIFixSGPRLiveness():
+ MachineFunctionPass(ID) {}
+
+ 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;
+char &llvm::SIFixSGPRLivenessID = SIFixSGPRLiveness::ID;
+
+INITIALIZE_PASS(SIFixSGPRLiveness, "sifixsgprliveness",
+ "SI fix SGPR liveness pass", false, false)
+
+void SIFixSGPRLiveness::getAnalysisUsage(AnalysisUsage &AU) const
+{
+ AU.setPreservesAll();
+ AU.addRequired<MachineDominatorTree>();
+ AU.addRequired<MachinePostDominatorTree>();
+ AU.addRequired<LiveIntervals>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+// Find the common dominator of all defines
+void SIFixSGPRLiveness::getBegin(unsigned VirtReg, MachineInstr *&BeginDef,
+ MachineBasicBlock *&Begin)
+{
+ MachineBasicBlock *LastDef = 0;
+ BeginDef = 0;
+ Begin = 0;
+
+ MachineRegisterInfo::def_iterator i, e;
+ for (i = MRI->def_begin(VirtReg), e = MRI->def_end(); i != e; ++i) {
+ MachineBasicBlock *MBB = i->getParent();
+
+ if (!Begin) {
+ BeginDef = &*i;
+ LastDef = Begin = MBB;
+ continue;
+ }
+
+ if (LastDef == MBB)
+ continue;
+
+ LastDef = MBB;
+ MBB = MD->findNearestCommonDominator(Begin, MBB);
+
+ if (MBB == LastDef)
+ BeginDef = &*i;
+ else if (MBB != Begin)
+ BeginDef = 0;
+
+ Begin = MBB;
+ }
+}
+
+// Find the common post dominator of all uses
+void SIFixSGPRLiveness::getEnd(unsigned VirtReg, bool &EndUses,
+ MachineBasicBlock *&End)
+{
+ MachineBasicBlock *LastUse = End;
+ EndUses = true;
+
+ 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;
+ MBB = MPD->findNearestCommonDominator(End, MBB);
+
+ if (MBB == LastUse)
+ EndUses = true;
+ else if (MBB != End)
+ EndUses = false;
+
+ End = MBB;
+ }
+}
+
+void SIFixSGPRLiveness::handleVirtReg(unsigned VirtReg)
+{
+ MachineBasicBlock *Begin, *End;
+ MachineInstr *BeginDef;
+ bool EndUses;
+
+ getBegin(VirtReg, BeginDef, Begin);
+ if (!Begin)
+ return; // Neither defines nor used
+
+ End = Begin;
+ getEnd(VirtReg, EndUses, End);
+
+ if (EndUses)
+ return; // End uses register anyway
+
+ // Remove invalid analysis results
+ LI->getInterval(VirtReg).clear();
+ MRI->clearKillFlags(VirtReg);
+
+ // And add new one
+ if (BeginDef)
+ LI->addLiveRangeToEndOfBlock(VirtReg, BeginDef);
+
+ df_iterator<MachineBasicBlock*> i = df_begin(Begin), e = df_end(End);
+ for (++i; i != e; ++i) {
+ LI->addLiveRangeToEndOfBlock(VirtReg, &i->front());
+ }
+}
+
+bool SIFixSGPRLiveness::runOnMachineFunction(MachineFunction &MF)
+{
+ MRI = &MF.getRegInfo();
+ MD = &getAnalysis<MachineDominatorTree>();
+ MPD = &getAnalysis<MachinePostDominatorTree>();
+ LI = &getAnalysis<LiveIntervals>();
+
+ for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
+ unsigned VirtReg = TargetRegisterInfo::index2VirtReg(i);
+
+ const TargetRegisterClass *RegClass = MRI->getRegClass(VirtReg);
+ if (!isSGPR(RegClass) || !LI->hasInterval(VirtReg))
+ continue;
+
+ handleVirtReg(VirtReg);
+ }
+
+ return false;
+}
--
1.7.9.5
More information about the mesa-dev
mailing list