} else
set<ir::Register> specialRegs; // already inserted registers
fn.foreachInstruction([&](const ir::Instruction &insn) {
+ // Special registers are immutable. So only check sources
const uint32_t srcNum = insn.getSrcNum();
for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
const ir::Register reg = insn.getSrc(srcID);
specialRegs.insert(reg);
}
});
- kernel->curbeSize = ALIGN(kernel->curbeSize, 32);
+ kernel->curbeSize = ALIGN(kernel->curbeSize, 32); // 32 == GEN_REG_SIZE
// Local IDs always go at the end of the curbe
const size_t localIDSize = sizeof(uint32_t) * this->simdWidth;
Context(unit, name) {}
GenContext::~GenContext(void) {}
+ void GenContext::allocateSpecialReg(gbe_curbe_type curbe, const ir::Register ®)
+ {
+ const int32_t offset = kernel->getCurbeOffset(curbe, 0);
+ GBE_ASSERT(this->isScalarReg(reg) == true);
+ if (offset >= 0) {
+ const ir::RegisterData data = fn.getRegisterData(reg);
+ const uint32_t typeSize = data.getSize();
+ const uint32_t nr = (offset + GEN_REG_SIZE) / GEN_REG_SIZE;
+ const uint32_t subnr = ((offset + GEN_REG_SIZE) % GEN_REG_SIZE) / typeSize;
+ GBE_ASSERT(data.family == ir::FAMILY_DWORD); // XXX support the rest
+ RA.insert(std::make_pair(reg, brw_vec1_reg(GEN_GENERAL_REGISTER_FILE, nr, subnr)));
+ }
+ }
+
void GenContext::allocateRegister(void) {
GBE_ASSERT(fn.getProfile() == ir::PROFILE_OCL);
+ // Allocate the special registers (only those which are actually used)
+ allocateSpecialReg(GBE_CURBE_LOCAL_ID_X, ir::ocl::lid0);
+ allocateSpecialReg(GBE_CURBE_LOCAL_ID_Y, ir::ocl::lid1);
+ allocateSpecialReg(GBE_CURBE_LOCAL_ID_Z, ir::ocl::lid2);
+ allocateSpecialReg(GBE_CURBE_LOCAL_SIZE_X, ir::ocl::lsize0);
+ allocateSpecialReg(GBE_CURBE_LOCAL_SIZE_Y, ir::ocl::lsize1);
+ allocateSpecialReg(GBE_CURBE_LOCAL_SIZE_Z, ir::ocl::lsize2);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_SIZE_X, ir::ocl::gsize0);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_SIZE_Y, ir::ocl::gsize1);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_SIZE_Z, ir::ocl::gsize2);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_OFFSET_X, ir::ocl::goffset0);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_OFFSET_Y, ir::ocl::goffset1);
+ allocateSpecialReg(GBE_CURBE_GLOBAL_OFFSET_Z, ir::ocl::goffset2);
+ allocateSpecialReg(GBE_CURBE_GROUP_NUM_X, ir::ocl::numgroup0);
+ allocateSpecialReg(GBE_CURBE_GROUP_NUM_Y, ir::ocl::numgroup1);
+ allocateSpecialReg(GBE_CURBE_GROUP_NUM_Z, ir::ocl::numgroup2);
+
+ // group IDs are always allocated by the hardware in r0
+ RA.insert(std::make_pair(ir::ocl::groupid0, brw_vec1_reg(GEN_GENERAL_REGISTER_FILE, 0, 1)));
+ RA.insert(std::make_pair(ir::ocl::groupid1, brw_vec1_reg(GEN_GENERAL_REGISTER_FILE, 0, 6)));
+ RA.insert(std::make_pair(ir::ocl::groupid2, brw_vec1_reg(GEN_GENERAL_REGISTER_FILE, 0, 7)));
+
// First we build the set of all used registers
set<ir::Register> usedRegs;
fn.foreachInstruction([&usedRegs](const ir::Instruction &insn) {
usedRegs.insert(insn.getDst(dstID));
});
-
+ // Allocate all used registers. Just crash when we run out-of-registers
+ // r0 is always taken by the HW
+ uint32_t grfOffset = kernel->getCurbeSize() + GEN_REG_SIZE;
+ if (simdWidth >= 16)
+ grfOffset = ALIGN(grfOffset, 2 * GEN_REG_SIZE);
+ GBE_ASSERT(simdWidth != 32); // a bit more complicated see later
+ for (auto reg : usedRegs) {
+ if (fn.isSpecialReg(reg) == true) continue; // already done
+ const ir::RegisterData regData = fn.getRegisterData(reg);
+ const ir::RegisterFamily family = regData.family;
+ const uint32_t typeSize = regData.getSize();
+ const uint32_t nr = grfOffset / GEN_REG_SIZE;
+ const uint32_t subnr = (grfOffset % GEN_REG_SIZE) / typeSize;
+ GBE_ASSERT(family == ir::FAMILY_DWORD); // XXX Do the rest
+ GBE_ASSERT(grfOffset + simdWidth*typeSize < GEN_GRF_SIZE);
+ RA.insert(std::make_pair(reg, brw_vec16_reg(GEN_GENERAL_REGISTER_FILE, nr, subnr)));
+ grfOffset += simdWidth * typeSize;
+ }
}
void GenContext::emitCode(void) {
} /* namespace gbe */
-
#ifndef __GBE_GEN_CONTEXT_HPP__
#define __GBE_GEN_CONTEXT_HPP__
-#include <string>
#include "backend/context.hpp"
#include "backend/gen_eu.hpp"
-#include "sys/set.hpp"
+#include "sys/map.hpp"
+#include "program.h"
+#include <string>
namespace gbe
{
~GenContext(void);
/*! Implements base class */
virtual void emitCode(void);
+ /*! Create a Gen register from the special register */
+ void allocateSpecialReg(gbe_curbe_type curbe, const ir::Register ®);
/*! Very stupid register allocator to start with */
void allocateRegister(void);
/*! Implements base class */
virtual Kernel *allocateKernel(void);
/*! Simplistic allocation to start with */
- set<ir::Register, GenReg> RA;
+ map<ir::Register, GenReg> RA;
};
} /* namespace gbe */
#define WRITEMASK_YZW 0xe
#define WRITEMASK_XYZW 0xf
-#define REG_SIZE (8*4)
+#define GEN_REG_SIZE (8*4)
+#define GEN_GRF_SIZE (GEN_REG_SIZE*128)
#define GEN_EU_MAX_INSN_STACK 5
#define VF_ZERO 0x0
/* Helpers for SEND instruction */
void set_sampler_message(GenInstruction *insn,
- uint32_t binding_table_index,
- uint32_t sampler,
- uint32_t msg_type,
- uint32_t response_length,
- uint32_t msg_length,
- uint32_t header_present,
- uint32_t simd_mode,
- uint32_t return_format);
+ uint32_t binding_table_index,
+ uint32_t sampler,
+ uint32_t msg_type,
+ uint32_t response_length,
+ uint32_t msg_length,
+ uint32_t header_present,
+ uint32_t simd_mode,
+ uint32_t return_format);
void set_dp_read_message(GenInstruction *insn,
- uint32_t binding_table_index,
- uint32_t msg_control,
- uint32_t msg_type,
- uint32_t target_cache,
- uint32_t msg_length,
- uint32_t response_length);
+ uint32_t binding_table_index,
+ uint32_t msg_control,
+ uint32_t msg_type,
+ uint32_t target_cache,
+ uint32_t msg_length,
+ uint32_t response_length);
void set_dp_write_message(GenInstruction *insn,
- uint32_t binding_table_index,
- uint32_t msg_control,
- uint32_t msg_type,
- uint32_t msg_length,
- bool header_present,
- uint32_t last_render_target,
- uint32_t response_length,
- uint32_t end_of_thread,
- uint32_t send_commit_msg);
+ uint32_t binding_table_index,
+ uint32_t msg_control,
+ uint32_t msg_type,
+ uint32_t msg_length,
+ bool header_present,
+ uint32_t last_render_target,
+ uint32_t response_length,
+ uint32_t end_of_thread,
+ uint32_t send_commit_msg);
void SAMPLE(GenReg dest,
- uint32_t msg_reg_nr,
- GenReg src0,
- uint32_t binding_table_index,
- uint32_t sampler,
- uint32_t writemask,
- uint32_t msg_type,
- uint32_t response_length,
- uint32_t msg_length,
- uint32_t header_present,
- uint32_t simd_mode,
- uint32_t return_format);
+ uint32_t msg_reg_nr,
+ GenReg src0,
+ uint32_t binding_table_index,
+ uint32_t sampler,
+ uint32_t writemask,
+ uint32_t msg_type,
+ uint32_t response_length,
+ uint32_t msg_length,
+ uint32_t header_present,
+ uint32_t simd_mode,
+ uint32_t return_format);
void math_16(GenReg dest,
- uint32_t function,
- uint32_t saturate,
- uint32_t msg_reg_nr,
- GenReg src,
- uint32_t precision);
+ uint32_t function,
+ uint32_t saturate,
+ uint32_t msg_reg_nr,
+ GenReg src,
+ uint32_t precision);
void math(GenReg dest,
uint32_t function,
static INLINE GenReg brw_vec16_reg(uint32_t file, uint32_t nr, uint32_t subnr)
{
return makeGenReg(file,
- nr,
- subnr,
- GEN_REGISTER_TYPE_F,
- GEN_VERTICAL_STRIDE_16,
- GEN_WIDTH_16,
- GEN_HORIZONTAL_STRIDE_1,
- GEN_SWIZZLE_XYZW,
- WRITEMASK_XYZW);
+ nr,
+ subnr,
+ GEN_REGISTER_TYPE_F,
+ GEN_VERTICAL_STRIDE_16,
+ GEN_WIDTH_16,
+ GEN_HORIZONTAL_STRIDE_1,
+ GEN_SWIZZLE_XYZW,
+ WRITEMASK_XYZW);
}
/** Construct float[8] register */
static INLINE GenReg brw_vec4_reg(uint32_t file, uint32_t nr, uint32_t subnr)
{
return makeGenReg(file,
- nr,
- subnr,
- GEN_REGISTER_TYPE_F,
- GEN_VERTICAL_STRIDE_4,
- GEN_WIDTH_4,
- GEN_HORIZONTAL_STRIDE_1,
- GEN_SWIZZLE_XYZW,
- WRITEMASK_XYZW);
+ nr,
+ subnr,
+ GEN_REGISTER_TYPE_F,
+ GEN_VERTICAL_STRIDE_4,
+ GEN_WIDTH_4,
+ GEN_HORIZONTAL_STRIDE_1,
+ GEN_SWIZZLE_XYZW,
+ WRITEMASK_XYZW);
}
/** Construct float[2] register */
static INLINE GenReg brw_vec1_reg(uint32_t file, uint32_t nr, uint32_t subnr)
{
return makeGenReg(file,
- nr,
- subnr,
- GEN_REGISTER_TYPE_F,
- GEN_VERTICAL_STRIDE_0,
- GEN_WIDTH_1,
- GEN_HORIZONTAL_STRIDE_0,
- GEN_SWIZZLE_XXXX,
- WRITEMASK_X);
+ nr,
+ subnr,
+ GEN_REGISTER_TYPE_F,
+ GEN_VERTICAL_STRIDE_0,
+ GEN_WIDTH_1,
+ GEN_HORIZONTAL_STRIDE_0,
+ GEN_SWIZZLE_XXXX,
+ WRITEMASK_X);
}
static INLINE GenReg retype(GenReg reg, uint32_t type)
static INLINE GenReg byte_offset(GenReg reg, uint32_t bytes)
{
- uint32_t newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
- reg.nr = newoffset / REG_SIZE;
- reg.subnr = newoffset % REG_SIZE;
+ uint32_t newoffset = reg.nr * GEN_REG_SIZE + reg.subnr + bytes;
+ reg.nr = newoffset / GEN_REG_SIZE;
+ reg.subnr = newoffset % GEN_REG_SIZE;
return reg;
}
static INLINE GenReg brw_address(GenReg reg)
{
- return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
+ return brw_imm_uw(reg.nr * GEN_REG_SIZE + reg.subnr);
}
/** Construct float[1] general-purpose register */
/*! Get the function name */
const std::string &getName(void) const { return name; }
/*! Extract the register from the register file */
- INLINE RegisterData getRegisterData(Register ID) const { return file.get(ID); }
+ INLINE RegisterData getRegisterData(Register reg) const { return file.get(reg); }
/*! Get the register family from the register itself */
- INLINE RegisterFamily getRegisterFamiy(Register ID) const {
- return this->getRegisterData(ID).family;
+ INLINE RegisterFamily getRegisterFamily(Register reg) const {
+ return this->getRegisterData(reg).family;
}
/*! Get the register index from the tuple vector */
INLINE Register getRegister(Tuple ID, uint32_t which) const {
return index;
}
+ const size_t RegisterData::familySize[] = {1,1,2,4,8};
+
} /* namespace ir */
} /* namespace gbe */
}
/*! Nothing really happens here */
INLINE ~RegisterData(void) {}
- RegisterFamily family;
+ /*! Get the size of the register */
+ INLINE size_t getSize(void) const { return familySize[family]; }
+ RegisterFamily family; //!< Register size or if it is a flag
+ static const size_t familySize[]; //!< Size per register family
GBE_CLASS(RegisterData);
};
if (fn.outputNum() == 1 && I.getNumOperands() > 0) {
const ir::Register dst = fn.getOutput(0);
const ir::Register src = this->getRegister(I.getOperand(0));
- const ir::RegisterFamily family = fn.getRegisterFamiy(dst);;
+ const ir::RegisterFamily family = fn.getRegisterFamily(dst);;
ctx.MOV(ir::getType(family), dst, src);
}
ctx.RET();