[Mesa-dev] [PATCH] SI: further simplify SGPR liveness fix

Christian König deathsimple at vodafone.de
Wed Nov 14 06:54:13 PST 2012


Based on already merged v4 of "fix SGPR liveness"

Signed-off-by: Christian König <deathsimple at vodafone.de>
---
 lib/Target/AMDGPU/AMDGPU.h                |    4 +-
 lib/Target/AMDGPU/AMDGPUTargetMachine.cpp |   12 ++-
 lib/Target/AMDGPU/SIFixSGPRLiveness.cpp   |  152 +++++++++++++++--------------
 3 files changed, 89 insertions(+), 79 deletions(-)

diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h
index 2a06ade..b51cc90 100644
--- a/lib/Target/AMDGPU/AMDGPU.h
+++ b/lib/Target/AMDGPU/AMDGPU.h
@@ -28,7 +28,9 @@ FunctionPass *createSIAssignInterpRegsPass(TargetMachine &tm);
 FunctionPass *createSILowerControlFlowPass(TargetMachine &tm);
 FunctionPass *createSICodeEmitterPass(formatted_raw_ostream &OS);
 FunctionPass *createSILowerLiteralConstantsPass(TargetMachine &tm);
-FunctionPass *createSIFixSGPRLivenessPass(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 5c4af91..67ea931 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>();
@@ -111,9 +118,6 @@ 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/SIFixSGPRLiveness.cpp b/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp
index 71641d1..77f58f8 100644
--- a/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp
+++ b/lib/Target/AMDGPU/SIFixSGPRLiveness.cpp
@@ -7,17 +7,18 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// SGPRs are not affected by control flow. This pass adjust SGPR liveness in
+// 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"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
 
 using namespace llvm;
 
@@ -25,12 +26,11 @@ namespace {
 
 class SIFixSGPRLiveness : public MachineFunctionPass {
 private:
-  static char ID;
 
-  const TargetInstrInfo *TII;
   MachineRegisterInfo *MRI;
   MachineDominatorTree *MD;
   MachinePostDominatorTree *MPD;
+  LiveIntervals *LI;
 
   bool isSGPR(const TargetRegisterClass *RegClass)
   {
@@ -41,15 +41,19 @@ private:
            RegClass == &AMDGPU::SReg_256RegClass;
   }
 
-  void addKill(MachineBasicBlock::iterator I, unsigned Reg);
-  MachineBasicBlock *handleUses(unsigned VirtReg, MachineBasicBlock *Begin);
-  void handlePreds(MachineBasicBlock *Begin, MachineBasicBlock *End,
-                   unsigned VirtReg);
+  void getBegin(unsigned VirtReg, MachineInstr *&BeginDef,
+                MachineBasicBlock *&Begin);
+
+  void getEnd(unsigned VirtReg, bool &EndUses,
+              MachineBasicBlock *&End);
 
-  bool handleVirtReg(unsigned VirtReg);
+  void handleVirtReg(unsigned VirtReg);
 
 public:
-  SIFixSGPRLiveness(TargetMachine &tm);
+  static char ID;
+
+  SIFixSGPRLiveness():
+    MachineFunctionPass(ID) {}
 
   virtual bool runOnMachineFunction(MachineFunction &MF);
 
@@ -63,35 +67,59 @@ public:
 } // end anonymous namespace
 
 char SIFixSGPRLiveness::ID = 0;
+char &llvm::SIFixSGPRLivenessID = SIFixSGPRLiveness::ID;
 
-SIFixSGPRLiveness::SIFixSGPRLiveness(TargetMachine &tm):
-  MachineFunctionPass(ID),
-  TII(tm.getInstrInfo())
-{
-  initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
-}
+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.setPreservesCFG();
+  AU.addRequired<LiveIntervals>();
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
-void SIFixSGPRLiveness::addKill(MachineBasicBlock::iterator I, unsigned Reg)
+// Find the common dominator of all defines
+void SIFixSGPRLiveness::getBegin(unsigned VirtReg, MachineInstr *&BeginDef,
+                                 MachineBasicBlock *&Begin)
 {
-  MachineBasicBlock *MBB = I->getParent();
+  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;
 
-  BuildMI(*MBB, I, DebugLoc(), TII->get(TargetOpcode::KILL)).addReg(Reg);
+    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
-MachineBasicBlock *SIFixSGPRLiveness::handleUses(unsigned VirtReg,
-                                                 MachineBasicBlock *Begin)
+void SIFixSGPRLiveness::getEnd(unsigned VirtReg, bool &EndUses,
+                               MachineBasicBlock *&End)
 {
-  MachineBasicBlock *LastUse = Begin, *End = Begin;
-  bool EndUsesReg = true;
+  MachineBasicBlock *LastUse = End;
+  EndUses = true;
 
   MachineRegisterInfo::use_iterator i, e;
   for (i = MRI->use_begin(VirtReg), e = MRI->use_end(); i != e; ++i) {
@@ -103,84 +131,60 @@ MachineBasicBlock *SIFixSGPRLiveness::handleUses(unsigned VirtReg,
     MBB = MPD->findNearestCommonDominator(End, MBB);
 
     if (MBB == LastUse)
-      EndUsesReg = true;
+      EndUses = true;
     else if (MBB != End)
-      EndUsesReg = false;
+      EndUses = false;
 
     End = MBB;
   }
-
-  return EndUsesReg ? Begin : End;
 }
 
-// Handles predecessors separately, only add KILLs to dominated ones
-void SIFixSGPRLiveness::handlePreds(MachineBasicBlock *Begin,
-                                    MachineBasicBlock *End,
-                                    unsigned VirtReg)
+void SIFixSGPRLiveness::handleVirtReg(unsigned VirtReg)
 {
-  MachineBasicBlock::pred_iterator i, e;
-  for (i = End->pred_begin(), e = End->pred_end(); i != e; ++i) {
+  MachineBasicBlock *Begin, *End;
+  MachineInstr *BeginDef;
+  bool EndUses;
 
-    if (MD->dominates(End, *i))
-      continue; // ignore loops
+  getBegin(VirtReg, BeginDef, Begin);
+  if (!Begin)
+    return; // Neither defines nor used
 
-    if (MD->dominates(*i, Begin))
-      continue; // too far up, abort search
+  End = Begin;
+  getEnd(VirtReg, EndUses, End);
 
-    if (MD->dominates(Begin, *i)) {
-      // found end of livetime
-      addKill((*i)->getFirstTerminator(), VirtReg);
-      continue;
-    }
+  if (EndUses)
+    return; // End uses register anyway
 
-    handlePreds(Begin, *i, VirtReg);
-  }
-}
+  // Remove invalid analysis results
+  LI->getInterval(VirtReg).clear();
+  MRI->clearKillFlags(VirtReg);
 
-bool SIFixSGPRLiveness::handleVirtReg(unsigned VirtReg)
-{
+  // And add new one
+  if (BeginDef)
+    LI->addLiveRangeToEndOfBlock(VirtReg, BeginDef);
 
-  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
-
-  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);
+  df_iterator<MachineBasicBlock*> i = df_begin(Begin), e = df_end(End);
+  for (++i; i != e; ++i) {
+    LI->addLiveRangeToEndOfBlock(VirtReg, &i->front());
   }
-  return true;
 }
 
 bool SIFixSGPRLiveness::runOnMachineFunction(MachineFunction &MF)
 {
-  bool Changes = false;
-
   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))
+    if (!isSGPR(RegClass) || !LI->hasInterval(VirtReg))
       continue;
 
-    Changes |= handleVirtReg(VirtReg);
+    handleVirtReg(VirtReg);
   }
 
-  return Changes;
-}
-
-FunctionPass *llvm::createSIFixSGPRLivenessPass(TargetMachine &tm)
-{
-  return new SIFixSGPRLiveness(tm);
+  return false;
 }
-- 
1.7.9.5



More information about the mesa-dev mailing list