summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Lejeune <vljn@ovi.com>2012-08-05 21:26:05 +0200
committerVincent Lejeune <vljn@ovi.com>2012-08-10 20:58:17 +0200
commit1e247bdc8db5f219e1e711979389e328859f5bb9 (patch)
tree12f0a6855d58fcae241781d3988c39ac36cda315
parent3fd9bfd5c094d500ea8fe05edfeae9851a95ddba (diff)
radeon/llvm: Adds a pass that try to propagates NEG/ABS flags to their usermodprop
-rw-r--r--src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp1
-rw-r--r--src/gallium/drivers/radeon/AMDIL.h2
-rw-r--r--src/gallium/drivers/radeon/Makefile.sources1
-rw-r--r--src/gallium/drivers/radeon/R600CodeEmitter.cpp5
-rw-r--r--src/gallium/drivers/radeon/R600ModifiersPropagation.cpp236
5 files changed, 242 insertions, 3 deletions
diff --git a/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp b/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp
index 7b199f1702..0aaf1390b6 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 4029f2780d..499ffe20f3 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 fc7b652037..2a2ce8bb86 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 0c84633417..7e62936c4f 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 0000000000..11108db1fb
--- /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();
+}