diff options
Diffstat (limited to 'src/gallium/drivers/radeon/SILowerLiteralConstants.cpp')
-rw-r--r-- | src/gallium/drivers/radeon/SILowerLiteralConstants.cpp | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeon/SILowerLiteralConstants.cpp b/src/gallium/drivers/radeon/SILowerLiteralConstants.cpp new file mode 100644 index 00000000000..720245091f7 --- /dev/null +++ b/src/gallium/drivers/radeon/SILowerLiteralConstants.cpp @@ -0,0 +1,105 @@ +//===-- SILowerLiteralConstants.cpp - Lower intrs using literal constants--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This pass performs the following transformation on instructions with +// literal constants: +// +// %VGPR0 = V_MOV_IMM_I32 1 +// +// becomes: +// +// BUNDLE +// * %VGPR = V_MOV_B32_32 SI_LITERAL_CONSTANT +// * SI_LOAD_LITERAL 1 +// +// The resulting sequence matches exactly how the hardware handles immediate +// operands, so this transformation greatly simplifies the code generator. +// +// Only the *_MOV_IMM_* support immediate operands at the moment, but when +// support for immediate operands is added to other instructions, they +// will be lowered here as well. +//===----------------------------------------------------------------------===// + +#include "AMDGPU.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineInstrBundle.h" + +using namespace llvm; + +namespace { + +class SILowerLiteralConstantsPass : public MachineFunctionPass { + +private: + static char ID; + const TargetInstrInfo *TII; + +public: + SILowerLiteralConstantsPass(TargetMachine &tm) : + MachineFunctionPass(ID), TII(tm.getInstrInfo()) { } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { + return "SI Lower literal constants pass"; + } +}; + +} // End anonymous namespace + +char SILowerLiteralConstantsPass::ID = 0; + +FunctionPass *llvm::createSILowerLiteralConstantsPass(TargetMachine &tm) { + return new SILowerLiteralConstantsPass(tm); +} + +bool SILowerLiteralConstantsPass::runOnMachineFunction(MachineFunction &MF) { + for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); + BB != BB_E; ++BB) { + MachineBasicBlock &MBB = *BB; + for (MachineBasicBlock::iterator I = MBB.begin(), Next = llvm::next(I); + I != MBB.end(); I = Next, Next = llvm::next(I)) { + MachineInstr &MI = *I; + switch (MI.getOpcode()) { + default: break; + case AMDGPU::S_MOV_IMM_I32: + case AMDGPU::S_MOV_IMM_I64: + case AMDGPU::V_MOV_IMM_F32: + case AMDGPU::V_MOV_IMM_I32: { + unsigned MovOpcode; + unsigned LoadLiteralOpcode; + MachineOperand LiteralOp = MI.getOperand(1); + if (AMDGPU::VReg_32RegClass.contains(MI.getOperand(0).getReg())) { + MovOpcode = AMDGPU::V_MOV_B32_e32; + } else { + MovOpcode = AMDGPU::S_MOV_B32; + } + if (LiteralOp.isImm()) { + LoadLiteralOpcode = AMDGPU::SI_LOAD_LITERAL_I32; + } else { + LoadLiteralOpcode = AMDGPU::SI_LOAD_LITERAL_F32; + } + MachineInstr *First = + BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(MovOpcode), + MI.getOperand(0).getReg()) + .addReg(AMDGPU::SI_LITERAL_CONSTANT); + MachineInstr *Last = + BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(LoadLiteralOpcode)) + .addOperand(MI.getOperand(1)); + Last->setIsInsideBundle(); + llvm::finalizeBundle(MBB, First, Last); + MI.eraseFromParent(); + break; + } + } + } + } + return false; +} |