sys/logging.hpp
sys/default_path.cpp
sys/default_path.hpp
+ ir/ir_instruction.cpp
+ ir/ir_instruction.hpp
ir/ir_register.cpp
ir/ir_register.hpp)
#ifndef __GBE_IR_FUNCTION_HPP__
#define __GBE_IR_FUNCTION_HPP__
+namespace gbe
+{
+ /*! A function is no more that a set of declared registers and a set of
+ * basic blocks
+ */
+ class Function
+ {
+ public:
+ /*! Create an empty function */
+ Function(void);
+
+ /*! Function basic blocks really belong to a function since:
+ * 1 - registers used in the basic blocks belongs to the function register
+ * file
+ * 2 - branches point to basic blocks of the same function
+ */
+ class BasicBlock
+ {
+ public:
+ /*! Empty basic block */
+ BasicBlock(void);
+ /*! Return the number of instruction in the block */
+ INLINE uint32 getInsnNum(void) { return insn.size(); }
+ private:
+ vector<Instruction> insn; //!< Sequence of instructions in the block
+ };
+
+ /*! Extract the register from the register file */
+ INLINE Register getRegister(uint32 ID) const { return file.get(ID); }
+
+ private:
+ /*! Create a function by sequential appending of instructions and registers */
+ friend class FunctionContext;
+ vector<uint16> input; //!< Input registers of the function
+ vector<uint16> output; //!< Output registers of the function
+ vector<BasicBlock> insn; //!< All the basic blocks one after the others
+ RegisterFile file; //!< All the registers used in the instructions
+ };
+
+} /* namespace gbe */
+
#endif /* __GBE_IR_FUNCTION_HPP__ */
*/
#include "ir_instruction.hpp"
+#include "ir_function.hpp"
+
+namespace gbe
+{
+ namespace internal
+ {
+ /*! All unary and binary arithmetic instructions */
+ template <uint32 srcNum> // 1 or 2
+ class ALIGNED(AlignOf<Instruction>::value) NaryInstruction
+ {
+ public:
+ INLINE uint32 getOpcode(void) const { return opcode; }
+ INLINE uint32 getSrcNum(void) const { return srcNum; }
+ INLINE uint32 getDstNum(void) const { return 1; }
+ INLINE uint32 getDstIndex(const Function &fn, uint32 ID) const {
+ assert(ID == 0);
+ return dst;
+ }
+ INLINE uint32 getSrcIndex(const Function &fn, uint32 ID) const {
+ assert(ID <= srcNum);
+ return src[ID];
+ }
+ INLINE Register getDst(const Function &fn, uint32 ID) const {
+ return fn.getRegister(this->getDstIndex(fn, ID));
+ }
+ INLINE Register getSrc(const Function &fn, uint32 ID) const {
+ return fn.getRegister(this->getSrcIndex(fn, ID));
+ }
+ protected:
+ uint8 opcode; //!< Instruction opcode
+ uint8 type; //!< Type of the instruction
+ uint16 dst; //!< Index of the register in the register file
+ uint16 src[srcNum]; //!< Indices of the sources
+ };
+
+ /*! All 1-source arithmetic instructions */
+ class UnaryInstruction : public NaryInstruction<1>
+ {
+ public:
+ UnaryInstruction(uint32 opcode, uint32 type, uint32 dst, uint32 src) {
+ this->opcode = opcode;
+ this->type = type;
+ this->dst = dst;
+ this->src[0] = src;
+ }
+ };
+
+ /*! All 2-source arithmetic instructions */
+ class BinaryInstruction : public NaryInstruction<2>
+ {
+ public:
+ BinaryInstruction(uint32 opcode, uint32 type, uint32 dst, uint32 src0, uint32 src1) {
+ this->opcode = opcode;
+ this->type = type;
+ this->dst = dst;
+ this->src[0] = src0;
+ this->src[1] = src1;
+ }
+ };
+
+ STATIC_ASSERT(sizeof(UnaryInstruction) <= sizeof(Instruction));
+ STATIC_ASSERT(sizeof(BinaryInstruction) <= sizeof(Instruction));
+
+ } /* namespace internal */
+} /* namespace gbe */
#ifndef __GBE_IR_INSTRUCTION_HPP__
#define __GBE_IR_INSTRUCTION_HPP__
-#endif /* __GBE_IR_INSTRUCTION_HPP__ */
+#include "sys/platform.hpp"
+#include "ir_register.hpp"
+
+namespace gbe
+{
+ /*! All opcodes */
+ enum {
+#define DECL_INSN(INSN, FAMILY) OP_##INSN,
+#include "ir_instruction.hxx"
+#undef DECL_INSN
+ OP_INVALID
+ };
+
+ /*! Different memory spaces */
+ enum {
+ MEM_GLOBAL = 0, /*! Global memory (a la OCL) */
+ MEM_LOCAL, /*! Local memory (thread group memory) */
+ MEM_PRIVATE /*! Per thread private memory */
+ };
+
+ /*! All types possibly supported by the instruction */
+ enum {
+ TYPE_S8 = 0, /*! signed 8 bits integer */
+ TYPE_U8, /*! unsigned 8 bits integer */
+ TYPE_S16, /*! signed 16 bits integer */
+ TYPE_U16, /*! unsigned 16 bits integer */
+ TYPE_S32, /*! signed 32 bits integer */
+ TYPE_U32, /*! unsigned 32 bits integer */
+ TYPE_S64, /*! signed 64 bits integer */
+ TYPE_U64, /*! unsigned 64 bits integer */
+ TYPE_FLOAT, /*! 32 bits floating point value */
+ TYPE_DOUBLE /*! 64 bits floating point value */
+ };
+
+ /*! Function class contains the register file and the register tuple. Any
+ * information related to the registers may therefore require a function
+ */
+ class Function;
+
+ /*! Store the instruction description in 8 bytes */
+ class Instruction
+ {
+ public:
+ /*! Get the instruction opcode */
+ uint32 getOpcode(void) const;
+ /*! Get the number of sources for this instruction */
+ uint32 getSrcNum(void) const;
+ /*! Get the number of destination for this instruction */
+ uint32 getDstNum(void) const;
+ /*! Get the register index of the given source */
+ uint32 getSrcIndex(const Function &fn, uint32 ID) const;
+ /*! Get the register index of the given destination */
+ uint32 getDstIndex(const Function &fn, uint32 ID) const;
+ /*! Get the register of the given source */
+ Register getSrc(const Function &fn, uint32 ID) const;
+ /*! Get the register of the given destination */
+ Register getDst(const Function &fn, uint32 ID) const;
+ /*! Check that the instruction is well formed. Return true if well formed.
+ * Otherwise, fill the string with a help message
+ */
+ bool check(void) const;
+ protected:
+ uint64 opaque; //!< Data depends on the instruction itself
+ };
+
+ /*! Binary instructions are typed. dst and sources share the same type */
+ class BinaryInstruction : public Instruction
+ {
+ public:
+ /*! Get the type manipulated by the instruction */
+ uint32 getType(void) const;
+ };
+ /*! Ternary instructions is mostly for MADs */
+ class TernaryInstruction : public Instruction
+ {
+ public:
+ /*! Get the type manipulated by the instruction */
+ uint32 getType(void) const;
+ };
+
+ /*! Conversion instruction converts from one type to another */
+ class ConvertInstruction : public Instruction
+ {
+ public:
+ /*! Get the type of the source */
+ uint32 getSrcType(void) const;
+ /*! Get the type of the destination */
+ uint32 getDstType(void) const;
+ };
+
+ /*! Store instruction */
+ class StoreInstruction : public Instruction
+ {
+ public:
+
+ };
+
+} /* namespace gbe */
+
+#endif /* __GBE_IR_INSTRUCTION_HPP__ */
--- /dev/null
+// ======================================================================== //
+// Copyright (C) 2012 Benjamin Segovia //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// ======================================================================== //
+
+DECL_INSN(MOV, UnaryInstruction)
+DECL_INSN(COS, UnaryInstruction)
+DECL_INSN(SIN, UnaryInstruction)
+DECL_INSN(TAN, UnaryInstruction)
+DECL_INSN(LOG, UnaryInstruction)
+DECL_INSN(SQR, UnaryInstruction)
+DECL_INSN(RSQ, UnaryInstruction)
+DECL_INSN(EXP2, UnaryInstruction)
+DECL_INSN(POW, BinaryInstruction)
+DECL_INSN(MUL, BinaryInstruction)
+DECL_INSN(ADD, BinaryInstruction)
+DECL_INSN(SUB, BinaryInstruction)
+DECL_INSN(DIV, BinaryInstruction)
+DECL_INSN(REM, BinaryInstruction)
+DECL_INSN(SHL, BinaryInstruction)
+DECL_INSN(SHR, BinaryInstruction)
+DECL_INSN(ASR, BinaryInstruction)
+DECL_INSN(BSF, BinaryInstruction)
+DECL_INSN(BSB, BinaryInstruction)
+DECL_INSN(OR, BinaryInstruction)
+DECL_INSN(XOR, BinaryInstruction)
+DECL_INSN(AND, BinaryInstruction)
+DECL_INSN(MAD, TernaryInstruction)
+DECL_INSN(CVT, ConvertInstruction)
+DECL_INSN(BRA, BranchInstruction)
+DECL_INSN(TEX, TextureInstruction)
+DECL_INSN(LOADI, LoadImmInstruction)
+DECL_INSN(LOAD, LoadInstruction)
+DECL_INSN(STORE, StoreInstruction)
+DECL_INSN(FENCE, FenceInstruction)
+DECL_INSN(LABEL, LabelInstruction)
+
*/
#include "ir_register.hpp"
-#include "sys/map.hpp"
-#include "sys/fixed_array.hpp"
-#include "sys/vector.hpp"
namespace gbe
{
- const uint8 Register::familySize[] = {
- 1, // bool
- 1, // byte
- 2, // word
- 4, // dword
- 5, // qword
- };
-
- /*! Implement register file class */
- class RegisterFileInternal : public RegisterFile
- {
- // Implements base class methods
- virtual ~RegisterFileInternal(void);
- virtual Register *create(Register::Family family, uint8 width);
- virtual Register *get(uint32 id);
- virtual void destroy(Register *reg);
-
-
- };
} /* namespace gbe */
#ifndef __GBE_IR_REGISTER_HPP__
#define __GBE_IR_REGISTER_HPP__
-#include "sys/ref.hpp"
-#include <new>
+#include "sys/vector.hpp"
namespace gbe
{
- /*! Describe a register in GBE register file. Each register can be either a
- * boolean value or a {8|16|32|64} bit word. Also, each register contains some
- * number of lanes that describes its SIMD width
+ /*! A register can be either a byte, a word, a dword or a qword. It can be
+ * either scalar or a vector. Everything is packed in 32 bits
*/
- class Register : public RefCount, public NonCopyable
+ class Register
{
public:
- /*! Family basically gives the size of each register lane */
- enum Family
- {
+ /*! Build a register. All fields will be immutable */
+ INLINE Register(uint8 type) : type(type) {}
+ /*! Copy constructor */
+ INLINE Register(const Register &other) : type(other.type) {}
+ /*! Copy operator */
+ Register &operator= (const Register &other) {
+ *this = Register(other.type);
+ return *this;
+ }
+ /*! Nothing really happens here */
+ INLINE ~Register(void) {}
+ /*! Register type */
+ enum {
BOOL = 0,
BYTE = 1,
WORD = 2,
DWORD = 3,
QWORD = 4
};
- friend class RegisterFile; // Allocates and destroys registers
- /*! Get the register identifier */
- INLINE uint32 id(void) const { return this->_id; }
- /*! Get the register width (ie number of lanes) */
- INLINE uint16 width(void) const { return this->_width; }
- /*! Get the register family */
- INLINE Family family(void) const { return this->_family; }
- /*! Get the register *individual* lane size */
- INLINE uint8 size(void) const { return this->_size; }
- private:
- /*! */
- INLINE Register(uint32 id, Family family, uint8 width) :
- _id(id), _width(width), _family(family), _size(familySize[family]) {}
- INLINE ~Register(void) {}
- const uint32 _id; //!< Uniquely identifies the register
- const uint16 _width; //!< Number of lane in the vector
- const Family _family; //!< From Family enum
- const uint8 _size; //!< Directly related to its type
- /*! Gives the size for each family */
- static const uint8 familySize[];
+ const uint8 type;
GBE_CLASS(Register);
};
- /*! Registers are equal if they have same width, ID and family */
- INLINE bool operator== (const Register &a, const Register &b) {
- return a.id() == b.id() &&
- a.width() == b.width() &&
- a.family() == b.family();
- }
-
- /*! != is just "not equal" */
- INLINE bool operator!= (const Register &a, const Register &b) {
- return !(a == b);
- }
-
- /*! To sort registers */
- INLINE bool operator< (const Register &a, const Register &b) {
- if (a.family() != b.family()) return a.family() < b.family();
- if (a.width() != b.width()) return a.width() < b.width();
- if (a.id() != b.id()) return a.id() < b.id();
- return false;
- }
-
/*! A register file allocates and destroys registers. Basically, we will have
* one register file per function
*/
- class RegisterFile : public RefCount
+ class RegisterFile
{
public:
- /*! Destroy the register file */
- virtual ~RegisterFile(void) = 0;
- /*! Allocate and return a valid register */
- virtual Register *create(Register::Family family, uint8 width) = 0;
- /*! Get the register with index id */
- virtual Register *get(uint32 id) = 0;
- /*! Deallocate the register */
- virtual void destroy(Register *reg) = 0;
+ /*! Return the index of a newly allocated register register */
+ INLINE uint32 append(uint32 type) {
+ const uint32 index = regs.size();
+ const Register reg(type);
+ assert(index <= MAX_INDEX);
+ regs.push_back(reg);
+ return index;
+ }
+ /*! Return a copy of the register at index */
+ INLINE Register get(uint32 index) const {
+ assert(index < regs.size() && index <= MAX_INDEX);
+ return regs[index];
+ }
+ /*! Number of registers in the register file */
+ INLINE uint32 regNum(void) const { return regs.size(); }
+ private:
+ enum { MAX_INDEX = 0xffff }; //!< We encode indices in 2 bytes
+ vector<Register> regs; //!< All the registers together
+ GBE_CLASS(RegisterFile);
};
- /*! Allocate a new register file */
- RegisterFile *RegisterFileNew(void);
-
} /* namespace gbe */
#endif /* __GBE_IR_REGISTER_HPP__ */
struct AlignOf
{
struct Helper { char x; T t; };
- static const size_t value = offsetof(Helper, t);
+ enum { value = offsetof(Helper, t) };
};
////////////////////////////////////////////////////////////////////////////////