diff options
author | Vincent Lejeune <vljn@ovi.com> | 2012-08-05 21:26:05 +0200 |
---|---|---|
committer | Vincent Lejeune <vljn@ovi.com> | 2012-08-10 20:58:17 +0200 |
commit | 1e247bdc8db5f219e1e711979389e328859f5bb9 (patch) | |
tree | 12f0a6855d58fcae241781d3988c39ac36cda315 | |
parent | 3fd9bfd5c094d500ea8fe05edfeae9851a95ddba (diff) |
radeon/llvm: Adds a pass that try to propagates NEG/ABS flags to their usermodprop
-rw-r--r-- | src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp | 1 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/AMDIL.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/Makefile.sources | 1 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/R600CodeEmitter.cpp | 5 | ||||
-rw-r--r-- | src/gallium/drivers/radeon/R600ModifiersPropagation.cpp | 236 |
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(); +} |