summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp')
-rw-r--r--src/gallium/drivers/radeon/R600ExpandSpecialInstrs.cpp91
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;
+}