diff options
Diffstat (limited to 'lib/Target/R600/SILowerLiteralConstants.cpp')
-rw-r--r-- | lib/Target/R600/SILowerLiteralConstants.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/Target/R600/SILowerLiteralConstants.cpp b/lib/Target/R600/SILowerLiteralConstants.cpp new file mode 100644 index 0000000000..2d5ab0bea1 --- /dev/null +++ b/lib/Target/R600/SILowerLiteralConstants.cpp @@ -0,0 +1,108 @@ +//===-- 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. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// \brief 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; +} |