diff options
Diffstat (limited to 'src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp')
-rw-r--r-- | src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp b/src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp new file mode 100644 index 00000000000..4c67ba47568 --- /dev/null +++ b/src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp @@ -0,0 +1,91 @@ +//===-- R600ExpandSpecialInstrs.cpp - Expand special instructions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Vector, Reduction, and Cube instructions need to fill the entire instruction +// group to work correctly. This pass expands these individual instructions +// into several instructions that will completely fill the instruction group. +//===----------------------------------------------------------------------===// + +#include "AMDGPU.h" +#include "R600InstrInfo.h" +#include "R600RegisterInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +namespace { + +class R600ExpandSpecialInstrsPass : public MachineFunctionPass { + +private: + static char ID; + const R600InstrInfo *TII; + +public: + R600ExpandSpecialInstrsPass(TargetMachine &tm) : MachineFunctionPass(ID), + TII (static_cast<const R600InstrInfo *>(tm.getInstrInfo())) { } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { + return "R600 Expand special instructions pass"; + } +}; + +} // End anonymous namespace + +char R600ExpandSpecialInstrsPass::ID = 0; + +FunctionPass *llvm::createR600ExpandSpecialInstrsPass(TargetMachine &TM) { + return new R600ExpandSpecialInstrsPass(TM); +} + +bool R600ExpandSpecialInstrsPass::runOnMachineFunction(MachineFunction &MF) { + + const R600RegisterInfo &TRI = TII->getRegisterInfo(); + + for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); + BB != BB_E; ++BB) { + MachineBasicBlock &MBB = *BB; + MachineBasicBlock::iterator I = MBB.begin(); + while (I != MBB.end()) { + MachineInstr &MI = *I; + I = llvm::next(I); + + if (!TII->isReductionOp(MI.getOpcode())) { + continue; + } + + // Expand the instruction + for (unsigned Chan = 0; Chan < 4; Chan++) { + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned Src0 = MI.getOperand(1).getReg(); + unsigned Src1 = MI.getOperand(2).getReg(); + unsigned SubRegIndex = TRI.getSubRegFromChannel(Chan); + unsigned NewSrc0 = TRI.getSubReg(Src0, SubRegIndex); + unsigned NewSrc1 = TRI.getSubReg(Src1, SubRegIndex); + unsigned DstBase = TRI.getHWRegIndex(DstReg); + unsigned NewDstReg = AMDGPU::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan); + unsigned Flags = (Chan != TRI.getHWRegChan(DstReg) ? MO_FLAG_MASK : 0); + Flags |= (Chan == 3 ? MO_FLAG_LAST : 0); + MachineOperand NewDstOp = MachineOperand::CreateReg(NewDstReg, true); + NewDstOp.addTargetFlag(Flags); + + BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(MI.getOpcode())) + .addOperand(NewDstOp) + .addReg(NewSrc0) + .addReg(NewSrc1) + ->setIsInsideBundle(Chan != 0); + } + MI.eraseFromParent(); + } + } + return false; +} |