[Mesa-dev] [PATCH] radeon/llvm: Adds a pass that try to propagates NEG/ABS flags to their user

Vincent Lejeune vljn at ovi.com
Tue Aug 14 09:49:43 PDT 2012


---
 src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp |   1 +
 src/gallium/drivers/radeon/AMDIL.h                 |   2 +
 src/gallium/drivers/radeon/Makefile.sources        |   1 +
 src/gallium/drivers/radeon/R600CodeEmitter.cpp     |   5 +-
 .../drivers/radeon/R600ModifiersPropagation.cpp    | 236 +++++++++++++++++++++
 5 files changed, 242 insertions(+), 3 deletions(-)
 create mode 100644 src/gallium/drivers/radeon/R600ModifiersPropagation.cpp

diff --git a/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp b/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp
index 7b199f1..0aaf139 100644
--- a/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp
+++ b/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp
@@ -148,6 +148,7 @@ bool AMDGPUPassConfig::addPostRegAlloc() {
 }
 
 bool AMDGPUPassConfig::addPreSched2() {
+  PM->add(createR600ModifiersPropagation());
   return false;
 }
 
diff --git a/src/gallium/drivers/radeon/AMDIL.h b/src/gallium/drivers/radeon/AMDIL.h
index 4029f27..499ffe2 100644
--- a/src/gallium/drivers/radeon/AMDIL.h
+++ b/src/gallium/drivers/radeon/AMDIL.h
@@ -99,6 +99,8 @@ FunctionPass*
   createAMDILCFGPreparationPass(TargetMachine &TM AMDIL_OPT_LEVEL_DECL);
 FunctionPass*
   createAMDILCFGStructurizerPass(TargetMachine &TM AMDIL_OPT_LEVEL_DECL);
+  
+FunctionPass *createR600ModifiersPropagation();
 
 extern Target TheAMDILTarget;
 extern Target TheAMDGPUTarget;
diff --git a/src/gallium/drivers/radeon/Makefile.sources b/src/gallium/drivers/radeon/Makefile.sources
index fc7b652..2a2ce8b 100644
--- a/src/gallium/drivers/radeon/Makefile.sources
+++ b/src/gallium/drivers/radeon/Makefile.sources
@@ -42,6 +42,7 @@ CPP_SOURCES := \
 	R600InstrInfo.cpp		\
 	R600KernelParameters.cpp	\
 	R600MachineFunctionInfo.cpp	\
+	R600ModifiersPropagation.cpp    \
 	R600RegisterInfo.cpp		\
 	SIAssignInterpRegs.cpp		\
 	SICodeEmitter.cpp		\
diff --git a/src/gallium/drivers/radeon/R600CodeEmitter.cpp b/src/gallium/drivers/radeon/R600CodeEmitter.cpp
index 0c84633..7e62936 100644
--- a/src/gallium/drivers/radeon/R600CodeEmitter.cpp
+++ b/src/gallium/drivers/radeon/R600CodeEmitter.cpp
@@ -313,10 +313,9 @@ void R600CodeEmitter::EmitSrc(const MachineOperand & MO, int chan_override)
   }
 
   // XXX: Emit isNegated (1 byte)
-  if ((!(MO.getTargetFlags() & MO_FLAG_ABS))
-      && (MO.getTargetFlags() & MO_FLAG_NEG ||
+  if ( (MO.getTargetFlags() & MO_FLAG_NEG) ||
      (MO.isReg() &&
-      (MO.getReg() == AMDGPU::NEG_ONE || MO.getReg() == AMDGPU::NEG_HALF)))){
+      (MO.getReg() == AMDGPU::NEG_ONE || MO.getReg() == AMDGPU::NEG_HALF))){
     EmitByte(1);
   } else {
     EmitByte(0);
diff --git a/src/gallium/drivers/radeon/R600ModifiersPropagation.cpp b/src/gallium/drivers/radeon/R600ModifiersPropagation.cpp
new file mode 100644
index 0000000..11108db
--- /dev/null
+++ b/src/gallium/drivers/radeon/R600ModifiersPropagation.cpp
@@ -0,0 +1,236 @@
+//===-- AMDILCFGStructurizer.cpp - CFG Structurizer -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//==-----------------------------------------------------------------------===//
+
+
+#define DEBUG_TYPE "modifier-prop"
+
+#include "AMDIL.h"
+#include "AMDILInstrInfo.h"
+#include "AMDILRegisterInfo.h"
+#include "AMDILUtilityFunctions.h"
+#include "AMDGPUUtil.h"
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+using namespace llvm;
+
+#include <iostream>
+
+struct PropagateChainCandidate {
+public:
+  MachineInstr *DefMI;
+  SmallPtrSet<MachineOperand*, 8> Uses;
+};
+
+class R600ModifiersPropagation : public MachineFunctionPass {
+protected:
+  const TargetRegisterInfo *TRI;
+  bool ModifierPropagateBlock(MachineBasicBlock &MBB);
+  void substitute(PropagateChainCandidate &PCC);
+  
+  typedef SmallVector<unsigned, 4> DestList;
+  typedef DenseMap<unsigned, DestList> SourceMap;
+  
+  void SourceNoLongerAvailable(unsigned Reg,
+					 SourceMap &SrcMap,
+					 DenseMap<unsigned, PropagateChainCandidate> &TargetMap);
+					 
+  void RemoveDstFromSourceMap(unsigned Dst, SourceMap &SrcMap);
+public:
+  static char ID;
+  
+  R600ModifiersPropagation() : MachineFunctionPass(ID) {
+
+  }
+    
+  bool runOnMachineFunction(MachineFunction& MF);
+};
+
+char R600ModifiersPropagation::ID = 0;
+
+void R600ModifiersPropagation::substitute(PropagateChainCandidate &PCC) {
+  for (SmallPtrSet<MachineOperand*, 8>::iterator it = PCC.Uses.begin(), e = PCC.Uses.end(); it != e; ++it) {
+    MachineOperand *MO = *it;
+    MO->setReg(PCC.DefMI->getOperand(1).getReg());
+    MO->addTargetFlag(PCC.DefMI->getOperand(1).getTargetFlags());
+  }
+  PCC.DefMI->eraseFromParent();
+}
+
+void R600ModifiersPropagation::SourceNoLongerAvailable(unsigned Reg,
+                                                       SourceMap &SrcMap,
+                                                       DenseMap<unsigned, PropagateChainCandidate> &TargetMap) {
+  SourceMap::iterator SI = SrcMap.find(Reg);
+  if (SI != SrcMap.end()) {
+    const DestList& Defs = SI->second;
+    for (DestList::const_iterator I = Defs.begin(), E = Defs.end();
+         I != E; ++I) {
+      unsigned MappedDef = *I;
+      // Source of copy is no longer available for propagation.
+      if (TargetMap.erase(MappedDef)) {
+        for (const uint16_t *SR = TRI->getSubRegisters(MappedDef); *SR; ++SR)
+          TargetMap.erase(*SR);
+      }
+    }
+  }
+}
+
+void R600ModifiersPropagation::RemoveDstFromSourceMap(unsigned Dst, SourceMap &SrcMap) {
+  for (SourceMap::iterator it = SrcMap.begin(), e = SrcMap.end(); it != e; it++) {
+    DestList &dl = it->second;
+    
+    DestList::iterator dlit = std::find(dl.begin(), dl.end(), Dst);
+    if (dlit != dl.end())
+      dl.erase(dlit);
+  }
+}
+
+// Using MachineCopyPropagation code
+bool R600ModifiersPropagation::ModifierPropagateBlock(MachineBasicBlock &MBB) {
+  bool Changed = false;
+  DenseMap<unsigned, PropagateChainCandidate> Candidates;    // Def -> available target map
+  SourceMap SrcMap;
+
+  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
+    MachineInstr *MI = &*I;
+    ++I;
+
+    if (MI->getOpcode() == AMDGPU::MOV && MI->getOperand(1).getTargetFlags() & (MO_FLAG_NEG | MO_FLAG_ABS )) {
+      unsigned Def = MI->getOperand(0).getReg();
+      unsigned Src = MI->getOperand(1).getReg();
+      
+      assert(!TargetRegisterInfo::isVirtualRegister(Def) && !TargetRegisterInfo::isVirtualRegister(Src));
+
+      // If we have a 
+      // REG1 = REG0[TF=2]
+      // REG2 = REG1[TF=4]
+      // maps this to 
+      // REG1 = REG0[TF=2]
+      // REG2 = REG0[TF=6]
+	
+	SourceNoLongerAvailable(Def, SrcMap, Candidates);
+	
+      DenseMap<unsigned, PropagateChainCandidate>::iterator CI = Candidates.find(Src);
+      if (CI != Candidates.end()) {
+        PropagateChainCandidate &PCC = CI->second;
+        MI->getOperand(1).setReg(PCC.DefMI->getOperand(1).getReg());
+        MI->getOperand(1).addTargetFlag(PCC.DefMI->getOperand(1).getTargetFlags());
+        Src = PCC.DefMI->getOperand(1).getReg();
+      }
+      
+      Candidates[Def].DefMI = MI;
+	  SrcMap[Src].push_back(Def);
+
+      continue;
+    }
+
+    // Not a copy.
+    SmallVector<unsigned, 2> Defs;
+    
+    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+      MachineOperand &MO = MI->getOperand(i);
+      if (!MO.isReg())
+        continue;
+      unsigned Reg = MO.getReg();
+      if (!Reg)
+        continue;
+      assert(!TargetRegisterInfo::isVirtualRegister(Reg));
+
+      if (MO.isDef()) {
+        Defs.push_back(Reg);
+        continue;
+      }
+      
+      // Cannot negate operand in a return
+      if (MI->isTerminator()) {
+        continue;
+      }
+      
+      // The operand is a vec4 reg and cannot be negated per component
+      // so keep the MOV instruction
+      for (unsigned j = 3; j < 7; j++) {
+        unsigned sub_reg = TRI->getSubReg(Reg,j);
+        if (!sub_reg)
+          continue;
+        DenseMap<unsigned, PropagateChainCandidate>::iterator CI = Candidates.find(sub_reg);
+        if (CI != Candidates.end()) {
+          RemoveDstFromSourceMap(sub_reg, SrcMap);
+          Candidates.erase(CI);
+        }
+      }
+	
+
+      DenseMap<unsigned, PropagateChainCandidate>::iterator CI = Candidates.find(Reg);
+      if (CI != Candidates.end()) {
+      // No ABS when more than 3 operands
+	  if (MI->getNumExplicitOperands() > 3) {
+	     RemoveDstFromSourceMap(Reg, SrcMap);
+	     Candidates.erase(CI);
+	  }
+	  else
+          Candidates[Reg].Uses.insert(&MO);
+      }
+      
+      if (MO.isKill()) {
+        DenseMap<unsigned, PropagateChainCandidate>::iterator CI = Candidates.find(Reg);
+        if (CI != Candidates.end()) {
+          substitute(CI->second);
+          RemoveDstFromSourceMap(Reg, SrcMap);
+	      Candidates.erase(Reg);	   
+        }
+      }
+      
+
+    }
+
+    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
+      unsigned Reg = Defs[i];
+	
+      // No longer defined by a copy.
+	{
+	  DenseMap<unsigned, PropagateChainCandidate>::iterator CI = Candidates.find(Reg);
+	  if (CI != Candidates.end()) {
+	    RemoveDstFromSourceMap(Reg, SrcMap);
+	    Candidates.erase(Reg);	   
+	  }
+	}
+	
+	// If src is redefined, give up
+	SourceNoLongerAvailable(Reg, SrcMap, Candidates);
+    }
+  }
+
+  return Changed;
+}
+
+bool R600ModifiersPropagation::runOnMachineFunction(MachineFunction &MF) {
+  bool Changed = false;
+  
+  TRI = MF.getTarget().getRegisterInfo();
+
+  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
+    Changed |= ModifierPropagateBlock(*I);
+
+  return Changed;
+}
+
+FunctionPass *llvm::createR600ModifiersPropagation() {
+  return new R600ModifiersPropagation();
+}
-- 
1.7.11.2



More information about the mesa-dev mailing list