Started serious work on Gen backend. Made a first stupid register allocator to start...
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Wed, 18 Apr 2012 19:00:34 +0000 (19:00 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:16:37 +0000 (16:16 -0700)
backend/src/backend/context.cpp
backend/src/backend/gen_context.cpp
backend/src/backend/gen_context.hpp
backend/src/backend/gen_eu.hpp
backend/src/ir/function.hpp
backend/src/ir/register.cpp
backend/src/ir/register.hpp
backend/src/llvm/llvm_gen_backend.cpp

index 1a43ccb..ce3c34e 100644 (file)
@@ -86,6 +86,7 @@ namespace gbe
   } 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);
@@ -106,7 +107,7 @@ namespace gbe
         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;
index 227d414..367c0ab 100644 (file)
@@ -35,9 +35,45 @@ namespace gbe
     Context(unit, name) {}
   GenContext::~GenContext(void) {}
 
+  void GenContext::allocateSpecialReg(gbe_curbe_type curbe, const ir::Register &reg)
+  {
+    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) {
@@ -48,7 +84,24 @@ namespace gbe
         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) {
@@ -68,4 +121,3 @@ namespace gbe
 
 } /* namespace gbe */
 
-
index 6a8b98a..ddd4651 100644 (file)
 #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
 {
@@ -48,12 +49,14 @@ 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 &reg);
     /*! 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 */
index f4956b8..4db84e1 100644 (file)
@@ -55,7 +55,8 @@
 #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
@@ -175,53 +176,53 @@ namespace gbe
 
     /* 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,
@@ -332,14 +333,14 @@ namespace gbe
   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 */
@@ -360,14 +361,14 @@ namespace gbe
   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 */
@@ -388,14 +389,14 @@ namespace gbe
   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)
@@ -425,9 +426,9 @@ namespace gbe
 
   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;
   }
 
@@ -541,7 +542,7 @@ namespace gbe
 
   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 */
index 2ae8427..0e7064a 100644 (file)
@@ -158,10 +158,10 @@ namespace ir {
     /*! 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 {
index d2d7b02..cc0e3f9 100644 (file)
@@ -59,6 +59,8 @@ namespace ir {
     return index;
   }
 
+  const size_t RegisterData::familySize[] = {1,1,2,4,8};
+
 } /* namespace ir */
 } /* namespace gbe */
 
index a8e911c..2d0931b 100644 (file)
@@ -56,7 +56,10 @@ namespace ir {
     }
     /*! 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);
   };
 
index f55ebd5..c867969 100644 (file)
@@ -725,7 +725,7 @@ namespace gbe
     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();