Added proper flag register allocation. Flag are spilled into GRFs. The spilling
authorbsegovia <segovia.benjamin@gmail.com>
Mon, 17 Sep 2012 18:01:32 +0000 (18:01 +0000)
committerbsegovia <segovia.benjamin@gmail.com>
Mon, 17 Sep 2012 18:01:32 +0000 (18:01 +0000)
code is not reaaly efficient i.e. sometimes the spilling can be avoided in a
basic block but it is still done. The idea is to improve that when the general
GRF spilling will be implemented. Right now, it works, so it is good enough

backend/src/backend/context.hpp
backend/src/backend/gen_context.cpp
backend/src/backend/gen_context.hpp
backend/src/backend/gen_defs.hpp
backend/src/backend/gen_encoder.cpp
backend/src/backend/gen_encoder.hpp
backend/src/backend/gen_insn_selection.cpp
backend/src/backend/gen_insn_selection.hpp
backend/src/backend/gen_reg_allocation.cpp
backend/src/backend/gen_reg_allocation.hpp
backend/src/backend/gen_register.hpp [new file with mode: 0644]

index c30db68..5e10a95 100644 (file)
@@ -21,6 +21,7 @@
  * \file context.hpp
  * \author Benjamin Segovia <benjamin.segovia@intel.com>
  */
+
 #ifndef __GBE_CONTEXT_HPP__
 #define __GBE_CONTEXT_HPP__
 
index 0951991..13d8a11 100644 (file)
@@ -52,25 +52,14 @@ namespace gbe
     GBE_DELETE(this->p);
   }
 
-  /*! XXX Make both structures the same! */
-  INLINE void setInstructionState(GenInstructionState &dst,
-                                  const SelectionState &src)
-  {
-    dst.execWidth = src.execWidth;
-    dst.quarterControl = src.quarterControl;
-    dst.noMask = src.noMask;
-    dst.flag = src.flag;
-    dst.subFlag = src.subFlag;
-    dst.predicate = src.predicate;
-    dst.inversePredicate = src.inversePredicate;
-  }
-
   void GenContext::emitInstructionStream(void) {
     // Emit Gen ISA
     sel->foreachInstruction([&](const SelectionInstruction &insn) {
       const uint32_t opcode = insn.opcode;
       p->push();
-      setInstructionState(p->curr, insn.state);
+      // no more virtual register here in that part of the code generation
+      GBE_ASSERT(insn.state.physicalFlag);
+      p->curr = insn.state;
       switch (opcode) {
 #define DECL_SELECTION_IR(OPCODE, FAMILY) \
   case SEL_OP_##OPCODE: this->emit##FAMILY(insn); break;
@@ -109,26 +98,26 @@ namespace gbe
     // Use shifts rather than muls which are limited to 32x16 bit sources
     const uint32_t perLaneShift = logi2(perLaneSize);
     const uint32_t perThreadShift = logi2(perThreadSize);
-    const SelectionReg selStatckPtr = this->simdWidth == 8 ?
-      SelectionReg::ud8grf(ir::ocl::stackptr) :
-      SelectionReg::ud16grf(ir::ocl::stackptr);
-    const GenReg stackptr = ra->genReg(selStatckPtr);
+    const GenRegister selStatckPtr = this->simdWidth == 8 ?
+      GenRegister::ud8grf(ir::ocl::stackptr) :
+      GenRegister::ud16grf(ir::ocl::stackptr);
+    const GenRegister stackptr = ra->genReg(selStatckPtr);
     const uint32_t nr = offset / GEN_REG_SIZE;
     const uint32_t subnr = (offset % GEN_REG_SIZE) / sizeof(uint32_t);
-    const GenReg bufferptr = GenReg::ud1grf(nr, subnr);
+    const GenRegister bufferptr = GenRegister::ud1grf(nr, subnr);
 
     // We compute the per-lane stack pointer here
     p->push();
       p->curr.execWidth = 1;
       p->curr.predicate = GEN_PREDICATE_NONE;
-      p->SHR(GenReg::ud1grf(126,0), GenReg::ud1grf(0,5), GenReg::immud(10));
+      p->SHR(GenRegister::ud1grf(126,0), GenRegister::ud1grf(0,5), GenRegister::immud(10));
       p->curr.execWidth = this->simdWidth;
-      p->SHL(stackptr, stackptr, GenReg::immud(perLaneShift));
+      p->SHL(stackptr, stackptr, GenRegister::immud(perLaneShift));
       p->curr.execWidth = 1;
-      p->SHL(GenReg::ud1grf(126,0), GenReg::ud1grf(126,0), GenReg::immud(perThreadShift));
+      p->SHL(GenRegister::ud1grf(126,0), GenRegister::ud1grf(126,0), GenRegister::immud(perThreadShift));
       p->curr.execWidth = this->simdWidth;
       p->ADD(stackptr, stackptr, bufferptr);
-      p->ADD(stackptr, stackptr, GenReg::ud1grf(126,0));
+      p->ADD(stackptr, stackptr, GenRegister::ud1grf(126,0));
     p->pop();
   }
 
@@ -138,8 +127,8 @@ namespace gbe
   }
 
   void GenContext::emitUnaryInstruction(const SelectionInstruction &insn) {
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     switch (insn.opcode) {
       case SEL_OP_MOV: p->MOV(dst, src); break;
       case SEL_OP_NOT: p->NOT(dst, src); break;
@@ -148,9 +137,9 @@ namespace gbe
   }
 
   void GenContext::emitBinaryInstruction(const SelectionInstruction &insn) { 
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg src0 = ra->genReg(insn.src[0]);
-    const GenReg src1 = ra->genReg(insn.src[1]);
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister src0 = ra->genReg(insn.src[0]);
+    const GenRegister src1 = ra->genReg(insn.src[1]);
     switch (insn.opcode) {
       case SEL_OP_SEL:  p->SEL(dst, src0, src1); break;
       case SEL_OP_AND:  p->AND(dst, src0, src1); break;
@@ -177,22 +166,22 @@ namespace gbe
   }
 
   void GenContext::emitMathInstruction(const SelectionInstruction &insn) {
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg src0 = ra->genReg(insn.src[0]);
-    const GenReg src1 = ra->genReg(insn.src[1]);
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister src0 = ra->genReg(insn.src[0]);
+    const GenRegister src1 = ra->genReg(insn.src[1]);
     const uint32_t function = insn.extra.function;
     p->MATH(dst, function, src0, src1);
   }
 
   void GenContext::emitCompareInstruction(const SelectionInstruction &insn) {
-    const GenReg src0 = ra->genReg(insn.src[0]);
-    const GenReg src1 = ra->genReg(insn.src[1]);
+    const GenRegister src0 = ra->genReg(insn.src[0]);
+    const GenRegister src1 = ra->genReg(insn.src[1]);
     p->CMP(insn.extra.function, src0, src1);
   }
 
   void GenContext::emitJumpInstruction(const SelectionInstruction &insn) {
     const ir::LabelIndex label(insn.index);
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     this->branchPos2.push_back(std::make_pair(label, p->store.size()));
     p->JMPI(src);
   }
@@ -202,36 +191,36 @@ namespace gbe
       p->curr.predicate = GEN_PREDICATE_NONE;
       p->curr.execWidth = 8;
       p->curr.noMask = 1;
-      p->MOV(GenReg::f8grf(127,0), GenReg::f8grf(0,0));
+      p->MOV(GenRegister::f8grf(127,0), GenRegister::f8grf(0,0));
       p->EOT(127);
     p->pop();
   }
 
   void GenContext::emitUntypedReadInstruction(const SelectionInstruction &insn) {
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     const uint32_t bti = insn.extra.function;
     const uint32_t elemNum = insn.extra.elem;
     p->UNTYPED_READ(dst, src, bti, elemNum);
   }
 
   void GenContext::emitUntypedWriteInstruction(const SelectionInstruction &insn) {
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     const uint32_t bti = insn.extra.function;
     const uint32_t elemNum = insn.extra.elem;
     p->UNTYPED_WRITE(src, bti, elemNum);
   }
 
   void GenContext::emitByteGatherInstruction(const SelectionInstruction &insn) {
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     const uint32_t bti = insn.extra.function;
     const uint32_t elemSize = insn.extra.elem;
     p->BYTE_GATHER(dst, src, bti, elemSize);
   }
 
   void GenContext::emitByteScatterInstruction(const SelectionInstruction &insn) {
-    const GenReg src = ra->genReg(insn.src[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
     const uint32_t bti = insn.extra.function;
     const uint32_t elemSize = insn.extra.elem;
     p->BYTE_SCATTER(src, bti, elemSize);
@@ -240,9 +229,9 @@ namespace gbe
   void GenContext::emitRegionInstruction(const SelectionInstruction &insn) {
     GBE_ASSERT(insn.dst[0].width == GEN_WIDTH_8 ||
                insn.dst[0].width == GEN_WIDTH_16);
-    const GenReg src = ra->genReg(insn.src[0]);
-    const GenReg dst = ra->genReg(insn.dst[1]);
-    const GenReg final = ra->genReg(insn.dst[0]);
+    const GenRegister src = ra->genReg(insn.src[0]);
+    const GenRegister dst = ra->genReg(insn.dst[1]);
+    const GenRegister final = ra->genReg(insn.dst[0]);
 
     // Region dimensions
     const uint32_t offset = insn.extra.offset;
@@ -270,72 +259,72 @@ namespace gbe
         {
           const uint32_t dstnr = dstOffset / GEN_REG_SIZE;
           const uint32_t dstsubnr = (dstOffset % GEN_REG_SIZE) / sizeof(int);
-          const GenReg dstReg = GenReg::f1grf(dstnr, dstsubnr);
+          const GenRegister dstReg = GenRegister::f1grf(dstnr, dstsubnr);
           if (srcOffset + sizeof(int) > end)
-            p->MOV(dstReg, GenReg::immf(0.f));
+            p->MOV(dstReg, GenRegister::immf(0.f));
           else {
             GBE_ASSERT(srcOffset % sizeof(int) == 0);
             const uint32_t srcnr = srcOffset / GEN_REG_SIZE;
             const uint32_t srcsubnr = (srcOffset % GEN_REG_SIZE) / sizeof(int);
-            const GenReg srcReg = GenReg::f1grf(srcnr, srcsubnr);
+            const GenRegister srcReg = GenRegister::f1grf(srcnr, srcsubnr);
             p->MOV(dstReg, srcReg);
           }
         }
       }
     p->pop();
-    p->MOV(GenReg::retype(final, GEN_TYPE_F), GenReg::retype(dst, GEN_TYPE_F));
+    p->MOV(GenRegister::retype(final, GEN_TYPE_F), GenRegister::retype(dst, GEN_TYPE_F));
   }
 
   void GenContext::emitRGatherInstruction(const SelectionInstruction &insn) {
-    const GenReg index0 = GenReg::retype(ra->genReg(insn.src[0]), GEN_TYPE_UW);
-    const GenReg dst0 = GenReg::retype(ra->genReg(insn.dst[0]), GEN_TYPE_F);
-    const GenReg src = ra->genReg(insn.src[1]);
+    const GenRegister index0 = GenRegister::retype(ra->genReg(insn.src[0]), GEN_TYPE_UW);
+    const GenRegister dst0 = GenRegister::retype(ra->genReg(insn.dst[0]), GEN_TYPE_F);
+    const GenRegister src = ra->genReg(insn.src[1]);
     const uint32_t offset = src.nr * GEN_REG_SIZE + src.subnr;
     p->push();
       p->curr.execWidth = 8;
-      p->SHL(GenReg::addr8(0), index0, GenReg::immuw(2));
-      p->ADD(GenReg::addr8(0), GenReg::addr8(0), GenReg::immuw(offset));
-      p->MOV(dst0, GenReg::indirect(GEN_TYPE_F, 0, GEN_WIDTH_8));
+      p->SHL(GenRegister::addr8(0), index0, GenRegister::immuw(2));
+      p->ADD(GenRegister::addr8(0), GenRegister::addr8(0), GenRegister::immuw(offset));
+      p->MOV(dst0, GenRegister::indirect(GEN_TYPE_F, 0, GEN_WIDTH_8));
     p->pop();
 
     if (simdWidth == 16) {
-      const GenReg dst1 = GenReg::Qn(dst0, 1);
-      const GenReg index1 = GenReg::Qn(index0, 1);
+      const GenRegister dst1 = GenRegister::Qn(dst0, 1);
+      const GenRegister index1 = GenRegister::Qn(index0, 1);
       p->push();
         p->curr.execWidth = 8;
         p->curr.quarterControl = GEN_COMPRESSION_Q2;
-        p->SHL(GenReg::addr8(0), index1, GenReg::immuw(2));
-        p->ADD(GenReg::addr8(0), GenReg::addr8(0), GenReg::immuw(offset));
-        p->MOV(dst1, GenReg::indirect(GEN_TYPE_F, 0, GEN_WIDTH_8));
+        p->SHL(GenRegister::addr8(0), index1, GenRegister::immuw(2));
+        p->ADD(GenRegister::addr8(0), GenRegister::addr8(0), GenRegister::immuw(offset));
+        p->MOV(dst1, GenRegister::indirect(GEN_TYPE_F, 0, GEN_WIDTH_8));
       p->pop();
     }
   }
 
   void GenContext::emitOBReadInstruction(const SelectionInstruction &insn) {
-    const GenReg dst = ra->genReg(insn.dst[0]);
-    const GenReg addr = ra->genReg(insn.src[0]);
-    const GenReg first = GenReg::ud1grf(addr.nr,addr.subnr/sizeof(float));
-    GenReg header;
+    const GenRegister dst = ra->genReg(insn.dst[0]);
+    const GenRegister addr = ra->genReg(insn.src[0]);
+    const GenRegister first = GenRegister::ud1grf(addr.nr,addr.subnr/sizeof(float));
+    GenRegister header;
     if (simdWidth == 8)
-      header = GenReg::retype(ra->genReg(insn.src[1]), GEN_TYPE_F);
+      header = GenRegister::retype(ra->genReg(insn.src[1]), GEN_TYPE_F);
     else
-      header = GenReg::retype(GenReg::Qn(ra->genReg(insn.src[1]),1), GEN_TYPE_F);
+      header = GenRegister::retype(GenRegister::Qn(ra->genReg(insn.src[1]),1), GEN_TYPE_F);
 
     p->push();
       // Copy r0 into the header first
       p->curr.execWidth = 8;
       p->curr.predicate = GEN_PREDICATE_NONE;
       p->curr.noMask = 1;
-      p->MOV(header, GenReg::f8grf(0,0));
+      p->MOV(header, GenRegister::f8grf(0,0));
 
       // Update the header with the current address
       p->curr.execWidth = 1;
       const uint32_t nr = header.nr;
       const uint32_t subnr = header.subnr / sizeof(float);
-      p->SHR(GenReg::ud1grf(nr, subnr+2), first, GenReg::immud(4));
+      p->SHR(GenRegister::ud1grf(nr, subnr+2), first, GenRegister::immud(4));
 
       // Put zero in the general state base address
-      p->MOV(GenReg::f1grf(nr, subnr+5), GenReg::immf(0));
+      p->MOV(GenRegister::f1grf(nr, subnr+5), GenRegister::immf(0));
 
       // Now read the data
       p->OBREAD(dst, header, insn.extra.function, insn.extra.elem);
@@ -343,29 +332,29 @@ namespace gbe
   }
 
   void GenContext::emitOBWriteInstruction(const SelectionInstruction &insn) {
-    const GenReg addr = ra->genReg(insn.src[2]);
-    const GenReg first = GenReg::ud1grf(addr.nr,addr.subnr/sizeof(float));
-    GenReg header;
+    const GenRegister addr = ra->genReg(insn.src[2]);
+    const GenRegister first = GenRegister::ud1grf(addr.nr,addr.subnr/sizeof(float));
+    GenRegister header;
     if (simdWidth == 8)
-      header = GenReg::retype(ra->genReg(insn.src[0]), GEN_TYPE_F);
+      header = GenRegister::retype(ra->genReg(insn.src[0]), GEN_TYPE_F);
     else
-      header = GenReg::retype(GenReg::Qn(ra->genReg(insn.src[0]),1), GEN_TYPE_F);
+      header = GenRegister::retype(GenRegister::Qn(ra->genReg(insn.src[0]),1), GEN_TYPE_F);
 
     p->push();
       // Copy r0 into the header first
       p->curr.execWidth = 8;
       p->curr.predicate = GEN_PREDICATE_NONE;
       p->curr.noMask = 1;
-      p->MOV(header, GenReg::f8grf(0,0));
+      p->MOV(header, GenRegister::f8grf(0,0));
 
       // Update the header with the current address
       p->curr.execWidth = 1;
       const uint32_t nr = header.nr;
       const uint32_t subnr = header.subnr / sizeof(float);
-      p->SHR(GenReg::ud1grf(nr, subnr+2), first, GenReg::immud(4));
+      p->SHR(GenRegister::ud1grf(nr, subnr+2), first, GenRegister::immud(4));
 
       // Put zero in the general state base address
-      p->MOV(GenReg::f1grf(nr, subnr+5), GenReg::immf(0));
+      p->MOV(GenRegister::f1grf(nr, subnr+5), GenRegister::immf(0));
 
       // Now read the data
       p->OBWRITE(header, insn.extra.function, insn.extra.elem);
index d865d79..13b791b 100644 (file)
@@ -65,7 +65,7 @@ namespace gbe
     void emitInstructionStream(void);
     /*! Set the correct target values for the branches */
     void patchBranches(void);
-    /*! Forward ir::Function method */
+    /*! Forward ir::Function isSpecialReg method */
     INLINE bool isSpecialReg(ir::Register reg) const {
       return fn.isSpecialReg(reg);
     }
@@ -73,7 +73,6 @@ namespace gbe
     INLINE const ir::Liveness::LiveOut &getLiveOut(const ir::BasicBlock *bb) const {
       return this->liveness->getLiveOut(bb);
     }
-
     /*! Final Gen ISA emission helper functions */
     void emitLabelInstruction(const SelectionInstruction &insn);
     void emitUnaryInstruction(const SelectionInstruction &insn);
@@ -111,3 +110,4 @@ namespace gbe
 
 #endif /* __GBE_GEN_CONTEXT_HPP__ */
 
+
index 7689a06..43d8993 100644 (file)
@@ -22,8 +22,8 @@
   *   Keith Whitwell <keith@tungstengraphics.com>
   */
 
-#ifndef GEN_DEFINES_H
-#define GEN_DEFINES_H
+#ifndef __GEN_DEFS_HPP__
+#define __GEN_DEFS_HPP__
 
 #include <cstdint>
 
@@ -35,6 +35,8 @@
 #define GEN_ALIGN_1   0
 #define GEN_ALIGN_16  1
 
+#define GEN_REG_SIZE 32
+
 #define GEN_ADDRESS_DIRECT                        0
 #define GEN_ADDRESS_REGISTER_INDIRECT_REGISTER    1
 
@@ -703,5 +705,5 @@ struct GenInstruction
   } bits3;
 };
 
-#endif /* GEN_DEFINES_H */
+#endif /* __GEN_DEFS_HPP__ */
 
index 28c61d1..2c647ea 100644 (file)
@@ -31,7 +31,7 @@ namespace gbe
   //////////////////////////////////////////////////////////////////////////
   // Some helper functions to encode
   //////////////////////////////////////////////////////////////////////////
-  INLINE bool isVectorOfBytes(GenReg reg) {
+  INLINE bool isVectorOfBytes(GenRegister reg) {
     if (reg.hstride != GEN_HORIZONTAL_STRIDE_0 &&
         (reg.type == GEN_TYPE_UB || reg.type == GEN_TYPE_B))
       return true;
@@ -39,14 +39,14 @@ namespace gbe
       return false;
   }
 
-  INLINE bool needToSplitAlu1(GenEncoder *p, GenReg dst, GenReg src) {
+  INLINE bool needToSplitAlu1(GenEncoder *p, GenRegister dst, GenRegister src) {
     if (p->curr.execWidth != 16) return false;
     if (isVectorOfBytes(dst) == true) return true;
     if (isVectorOfBytes(src) == true) return true;
     return false;
   }
 
-  INLINE bool needToSplitAlu2(GenEncoder *p, GenReg dst, GenReg src0, GenReg src1) {
+  INLINE bool needToSplitAlu2(GenEncoder *p, GenRegister dst, GenRegister src0, GenRegister src1) {
     if (p->curr.execWidth != 16) return false;
     if (isVectorOfBytes(dst) == true) return true;
     if (isVectorOfBytes(src0) == true) return true;
@@ -54,7 +54,7 @@ namespace gbe
     return false;
   }
 
-  INLINE bool needToSplitCmp(GenEncoder *p, GenReg src0, GenReg src1) {
+  INLINE bool needToSplitCmp(GenEncoder *p, GenRegister src0, GenRegister src1) {
     if (p->curr.execWidth != 16) return false;
     if (isVectorOfBytes(src0) == true) return true;
     if (isVectorOfBytes(src1) == true) return true;
@@ -73,7 +73,7 @@ namespace gbe
                                    bool header_present = false,
                                    bool end_of_thread = false)
   {
-     p->setSrc1(inst, GenReg::immd(0));
+     p->setSrc1(inst, GenRegister::immd(0));
      inst->bits3.generic_gen5.header_present = header_present;
      inst->bits3.generic_gen5.response_length = response_length;
      inst->bits3.generic_gen5.msg_length = msg_length;
@@ -193,7 +193,7 @@ namespace gbe
     }
   }
 
-  void GenEncoder::setDst(GenInstruction *insn, GenReg dest) {
+  void GenEncoder::setDst(GenInstruction *insn, GenRegister dest) {
      if (dest.file != GEN_ARCHITECTURE_REGISTER_FILE)
         assert(dest.nr < 128);
 
@@ -207,7 +207,7 @@ namespace gbe
      insn->bits1.da1.dest_horiz_stride = dest.hstride;
   }
 
-  void GenEncoder::setSrc0(GenInstruction *insn, GenReg reg) {
+  void GenEncoder::setSrc0(GenInstruction *insn, GenRegister reg) {
      if (reg.file != GEN_ARCHITECTURE_REGISTER_FILE)
         assert(reg.nr < 128);
 
@@ -219,7 +219,7 @@ namespace gbe
        insn->bits2.da1.src0_address_mode = reg.address_mode;
 
        if (reg.file == GEN_IMMEDIATE_VALUE) {
-          insn->bits3.ud = reg.dw1.ud;
+          insn->bits3.ud = reg.immediate.ud;
 
           /* Required to set some fields in src1 as well: */
           insn->bits1.da1.src1_reg_file = 0; /* arf */
@@ -260,7 +260,7 @@ namespace gbe
     }
   }
 
-  void GenEncoder::setSrc1(GenInstruction *insn, GenReg reg) {
+  void GenEncoder::setSrc1(GenInstruction *insn, GenRegister reg) {
      assert(reg.nr < 128);
 
      insn->bits1.da1.src1_reg_file = reg.file;
@@ -271,7 +271,7 @@ namespace gbe
      assert(insn->bits1.da1.src0_reg_file != GEN_IMMEDIATE_VALUE);
 
      if (reg.file == GEN_IMMEDIATE_VALUE)
-       insn->bits3.ud = reg.dw1.ud;
+       insn->bits3.ud = reg.immediate.ud;
      else {
        assert (reg.address_mode == GEN_ADDRESS_DIRECT);
        if (insn->header.access_mode == GEN_ALIGN_1) {
@@ -303,7 +303,7 @@ namespace gbe
     0
   };
 
-  void GenEncoder::UNTYPED_READ(GenReg dst, GenReg src, uint32_t bti, uint32_t elemNum) {
+  void GenEncoder::UNTYPED_READ(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemNum) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     assert(elemNum >= 1 || elemNum <= 4);
     uint32_t msg_length = 0;
@@ -318,9 +318,9 @@ namespace gbe
       NOT_IMPLEMENTED;
 
     this->setHeader(insn);
-    this->setDst(insn, GenReg::uw16grf(dst.nr, 0));
-    this->setSrc0(insn, GenReg::ud8grf(src.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
+    this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
     setDPUntypedRW(this,
                    insn,
                    bti,
@@ -330,23 +330,23 @@ namespace gbe
                    response_length);
   }
 
-  void GenEncoder::UNTYPED_WRITE(GenReg msg, uint32_t bti, uint32_t elemNum) {
+  void GenEncoder::UNTYPED_WRITE(GenRegister msg, uint32_t bti, uint32_t elemNum) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     assert(elemNum >= 1 || elemNum <= 4);
     uint32_t msg_length = 0;
     uint32_t response_length = 0;
     this->setHeader(insn);
     if (this->curr.execWidth == 8) {
-      this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UD));
+      this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UD));
       msg_length = 1+elemNum;
     } else if (this->curr.execWidth == 16) {
-      this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UW));
+      this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UW));
       msg_length = 2*(1+elemNum);
     }
     else
       NOT_IMPLEMENTED;
-    this->setSrc0(insn, GenReg::ud8grf(msg.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setSrc0(insn, GenRegister::ud8grf(msg.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
     setDPUntypedRW(this,
                    insn,
                    bti,
@@ -356,7 +356,7 @@ namespace gbe
                    response_length);
   }
 
-  void GenEncoder::BYTE_GATHER(GenReg dst, GenReg src, uint32_t bti, uint32_t elemSize) {
+  void GenEncoder::BYTE_GATHER(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemSize) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     uint32_t msg_length = 0;
     uint32_t response_length = 0;
@@ -370,9 +370,9 @@ namespace gbe
       NOT_IMPLEMENTED;
 
     this->setHeader(insn);
-    this->setDst(insn, GenReg::uw16grf(dst.nr, 0));
-    this->setSrc0(insn, GenReg::ud8grf(src.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
+    this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
     setDPByteScatterGather(this,
                            insn,
                            bti,
@@ -382,21 +382,21 @@ namespace gbe
                            response_length);
   }
 
-  void GenEncoder::BYTE_SCATTER(GenReg msg, uint32_t bti, uint32_t elemSize) {
+  void GenEncoder::BYTE_SCATTER(GenRegister msg, uint32_t bti, uint32_t elemSize) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     uint32_t msg_length = 0;
     uint32_t response_length = 0;
     this->setHeader(insn);
     if (this->curr.execWidth == 8) {
-      this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UD));
+      this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UD));
       msg_length = 2;
     } else if (this->curr.execWidth == 16) {
-      this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UW));
+      this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UW));
       msg_length = 4;
     } else
       NOT_IMPLEMENTED;
-    this->setSrc0(insn, GenReg::ud8grf(msg.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setSrc0(insn, GenRegister::ud8grf(msg.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
     setDPByteScatterGather(this,
                            insn,
                            bti,
@@ -414,7 +414,7 @@ namespace gbe
      return &this->store.back();
   }
 
-  INLINE void alu1(GenEncoder *p, uint32_t opcode, GenReg dst, GenReg src) {
+  INLINE void alu1(GenEncoder *p, uint32_t opcode, GenRegister dst, GenRegister src) {
      if (needToSplitAlu1(p, dst, src) == false) {
        GenInstruction *insn = p->next(opcode);
        p->setHeader(insn);
@@ -436,16 +436,16 @@ namespace gbe
        p->setHeader(insnQ2);
        insnQ2->header.quarter_control = GEN_COMPRESSION_Q2;
        insnQ2->header.execution_size = GEN_WIDTH_8;
-       p->setDst(insnQ2, GenReg::Qn(dst, 1));
-       p->setSrc0(insnQ2, GenReg::Qn(src, 1));
+       p->setDst(insnQ2, GenRegister::Qn(dst, 1));
+       p->setSrc0(insnQ2, GenRegister::Qn(src, 1));
      }
   }
 
   INLINE void alu2(GenEncoder *p,
                    uint32_t opcode,
-                   GenReg dst,
-                   GenReg src0,
-                   GenReg src1,
+                   GenRegister dst,
+                   GenRegister src0,
+                   GenRegister src1,
                    int accWriteControl = 0)
   {
      if (needToSplitAlu2(p, dst, src0, src1) == false) {
@@ -474,15 +474,15 @@ namespace gbe
        insnQ2->header.acc_wr_control = accWriteControl;
        insnQ2->header.quarter_control = GEN_COMPRESSION_Q2;
        insnQ2->header.execution_size = GEN_WIDTH_8;
-       p->setDst(insnQ2, GenReg::Qn(dst, 1));
-       p->setSrc0(insnQ2, GenReg::Qn(src0, 1));
-       p->setSrc1(insnQ2, GenReg::Qn(src1, 1));
+       p->setDst(insnQ2, GenRegister::Qn(dst, 1));
+       p->setSrc0(insnQ2, GenRegister::Qn(src0, 1));
+       p->setSrc1(insnQ2, GenRegister::Qn(src1, 1));
     }
   }
 
 #if 0
   static int
-  get_3src_subreg_nr(GenReg reg)
+  get_3src_subreg_nr(GenRegister reg)
   {
      if (reg.vstride == GEN_VERTICAL_STRIDE_0) {
         assert(brw_is_single_value_swizzle(reg.dw1.bits.swizzle));
@@ -493,10 +493,10 @@ namespace gbe
 
   static GenInstruction *alu3(GenEncoder *p,
                               uint32_t opcode,
-                              GenReg dest,
-                              GenReg src0,
-                              GenReg src1,
-                              GenReg src2)
+                              GenRegister dest,
+                              GenRegister src0,
+                              GenRegister src1,
+                              GenRegister src2)
   {
      GenInstruction *insn = p->next(opcode);
 
@@ -551,17 +551,17 @@ namespace gbe
 #endif
 
 #define ALU1(OP) \
-  void GenEncoder::OP(GenReg dest, GenReg src0) { \
+  void GenEncoder::OP(GenRegister dest, GenRegister src0) { \
     alu1(this, GEN_OPCODE_##OP, dest, src0); \
   }
 
 #define ALU2(OP) \
-  void GenEncoder::OP(GenReg dest, GenReg src0, GenReg src1) { \
+  void GenEncoder::OP(GenRegister dest, GenRegister src0, GenRegister src1) { \
     alu2(this, GEN_OPCODE_##OP, dest, src0, src1); \
   }
 
 #define ALU3(OP) \
-  void GenEncoder::OP(GenReg dest, GenReg src0, GenReg src1, GenReg src2) { \
+  void GenEncoder::OP(GenRegister dest, GenRegister src0, GenRegister src1, GenRegister src2) { \
     alu3(this, GEN_OPCODE_##OP, dest, src0, src1, src2); \
   }
 
@@ -586,11 +586,11 @@ namespace gbe
   ALU2(PLN)
   // ALU3(MAD)
 
-  void GenEncoder::MACH(GenReg dest, GenReg src0, GenReg src1) {
+  void GenEncoder::MACH(GenRegister dest, GenRegister src0, GenRegister src1) {
      alu2(this, GEN_OPCODE_MACH, dest, src0, src1, 1);
   }
 
-  void GenEncoder::ADD(GenReg dest, GenReg src0, GenReg src1) {
+  void GenEncoder::ADD(GenRegister dest, GenRegister src0, GenRegister src1) {
      if (src0.type == GEN_TYPE_F ||
          (src0.file == GEN_IMMEDIATE_VALUE &&
           src0.type == GEN_TYPE_VF)) {
@@ -608,7 +608,7 @@ namespace gbe
      alu2(this, GEN_OPCODE_ADD, dest, src0, src1);
   }
 
-  void GenEncoder::MUL(GenReg dest, GenReg src0, GenReg src1) {
+  void GenEncoder::MUL(GenRegister dest, GenRegister src0, GenRegister src1) {
      if (src0.type == GEN_TYPE_D ||
          src0.type == GEN_TYPE_UD ||
          src1.type == GEN_TYPE_D ||
@@ -640,28 +640,28 @@ namespace gbe
 
   void GenEncoder::NOP(void) {
     GenInstruction *insn = this->next(GEN_OPCODE_NOP);
-    this->setDst(insn, GenReg::retype(GenReg::f4grf(0,0), GEN_TYPE_UD));
-    this->setSrc0(insn, GenReg::retype(GenReg::f4grf(0,0), GEN_TYPE_UD));
-    this->setSrc1(insn, GenReg::immud(0x0));
+    this->setDst(insn, GenRegister::retype(GenRegister::f4grf(0,0), GEN_TYPE_UD));
+    this->setSrc0(insn, GenRegister::retype(GenRegister::f4grf(0,0), GEN_TYPE_UD));
+    this->setSrc1(insn, GenRegister::immud(0x0));
   }
 
-  void GenEncoder::JMPI(GenReg src) {
-    alu2(this, GEN_OPCODE_JMPI, GenReg::ip(), GenReg::ip(), src);
+  void GenEncoder::JMPI(GenRegister src) {
+    alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
   }
 
   void GenEncoder::patchJMPI(uint32_t insnID, int32_t jumpDistance) {
     GenInstruction &insn = this->store[insnID];
     assert(insnID < this->store.size());
     assert(insn.header.opcode == GEN_OPCODE_JMPI);
-    this->setSrc1(&insn, GenReg::immd(jumpDistance));
+    this->setSrc1(&insn, GenRegister::immd(jumpDistance));
   }
 
-  void GenEncoder::CMP(uint32_t conditional, GenReg src0, GenReg src1) {
+  void GenEncoder::CMP(uint32_t conditional, GenRegister src0, GenRegister src1) {
     if (needToSplitCmp(this, src0, src1) == false) {
       GenInstruction *insn = this->next(GEN_OPCODE_CMP);
       this->setHeader(insn);
       insn->header.destreg_or_condmod = conditional;
-      this->setDst(insn, GenReg::null());
+      this->setDst(insn, GenRegister::null());
       this->setSrc0(insn, src0);
       this->setSrc1(insn, src1);
     } else {
@@ -673,7 +673,7 @@ namespace gbe
       insnQ1->header.quarter_control = GEN_COMPRESSION_Q1;
       insnQ1->header.execution_size = GEN_WIDTH_8;
       insnQ1->header.destreg_or_condmod = conditional;
-      this->setDst(insnQ1, GenReg::null());
+      this->setDst(insnQ1, GenRegister::null());
       this->setSrc0(insnQ1, src0);
       this->setSrc1(insnQ1, src1);
 
@@ -683,24 +683,24 @@ namespace gbe
       insnQ2->header.quarter_control = GEN_COMPRESSION_Q2;
       insnQ2->header.execution_size = GEN_WIDTH_8;
       insnQ2->header.destreg_or_condmod = conditional;
-      this->setDst(insnQ2, GenReg::null());
-      this->setSrc0(insnQ2, GenReg::Qn(src0, 1));
-      this->setSrc1(insnQ2, GenReg::Qn(src1, 1));
+      this->setDst(insnQ2, GenRegister::null());
+      this->setSrc0(insnQ2, GenRegister::Qn(src0, 1));
+      this->setSrc1(insnQ2, GenRegister::Qn(src1, 1));
     }
   }
 
   void GenEncoder::WAIT(void) {
      GenInstruction *insn = this->next(GEN_OPCODE_WAIT);
-     GenReg src = GenReg::notification1();
+     GenRegister src = GenRegister::notification1();
      this->setDst(insn, src);
      this->setSrc0(insn, src);
-     this->setSrc1(insn, GenReg::null());
+     this->setSrc1(insn, GenRegister::null());
      insn->header.execution_size = 0; /* must */
      insn->header.predicate_control = 0;
      insn->header.quarter_control = 0;
   }
 
-  void GenEncoder::MATH(GenReg dest, uint32_t function, GenReg src0, GenReg src1) {
+  void GenEncoder::MATH(GenRegister dest, uint32_t function, GenRegister src0, GenRegister src1) {
      GenInstruction *insn = this->next(GEN_OPCODE_MATH);
      assert(dest.file == GEN_GENERAL_REGISTER_FILE);
      assert(src0.file == GEN_GENERAL_REGISTER_FILE);
@@ -724,9 +724,9 @@ namespace gbe
      this->setSrc1(insn, src1);
   }
 
-  void GenEncoder::SAMPLE(GenReg dest,
+  void GenEncoder::SAMPLE(GenRegister dest,
                           uint32_t msg_reg_nr,
-                          GenReg src0,
+                          GenRegister src0,
                           uint32_t bti,
                           uint32_t sampler,
                           uint32_t writemask,
@@ -756,14 +756,14 @@ namespace gbe
                        return_format);
   }
 
-  void GenEncoder::OBREAD(GenReg dst, GenReg header, uint32_t bti, uint32_t size) {
+  void GenEncoder::OBREAD(GenRegister dst, GenRegister header, uint32_t bti, uint32_t size) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     const uint32_t msg_length = 1;
     const uint32_t response_length = size / 2; // Size is in owords
     this->setHeader(insn);
-    this->setDst(insn, GenReg::uw16grf(dst.nr, 0));
-    this->setSrc0(insn, GenReg::ud8grf(header.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
+    this->setSrc0(insn, GenRegister::ud8grf(header.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
     insn->header.execution_size = response_length == 1 ? GEN_WIDTH_8 : GEN_WIDTH_16;
     setOBlockRW(this,
                 insn,
@@ -774,14 +774,14 @@ namespace gbe
                 response_length);
   }
 
-  void GenEncoder::OBWRITE(GenReg header, uint32_t bti, uint32_t size) {
+  void GenEncoder::OBWRITE(GenRegister header, uint32_t bti, uint32_t size) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
     const uint32_t msg_length = 1 + size / 2; // Size is in owords
     const uint32_t response_length = 0;
     this->setHeader(insn);
-    this->setSrc0(insn, GenReg::ud8grf(header.nr, 0));
-    this->setSrc1(insn, GenReg::immud(0));
-    this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UW));
+    this->setSrc0(insn, GenRegister::ud8grf(header.nr, 0));
+    this->setSrc1(insn, GenRegister::immud(0));
+    this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UW));
     insn->header.execution_size = msg_length == 2 ? GEN_WIDTH_8 : GEN_WIDTH_16;
     setOBlockRW(this,
                 insn,
@@ -794,9 +794,9 @@ namespace gbe
 
   void GenEncoder::EOT(uint32_t msg) {
     GenInstruction *insn = this->next(GEN_OPCODE_SEND);
-    this->setDst(insn, GenReg::retype(GenReg::null(), GEN_TYPE_UD));
-    this->setSrc0(insn, GenReg::ud8grf(msg,0));
-    this->setSrc1(insn, GenReg::immud(0));
+    this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UD));
+    this->setSrc0(insn, GenRegister::ud8grf(msg,0));
+    this->setSrc1(insn, GenRegister::immud(0));
     insn->header.execution_size = GEN_WIDTH_8;
     insn->bits3.spawner_gen5.resource = GEN_DO_NOT_DEREFERENCE_URB;
     insn->bits3.spawner_gen5.msg_length = 1;
index 244b9f8..57706fc 100644 (file)
 #define __GBE_GEN_ENCODER_HPP__
 
 #include "backend/gen_defs.hpp"
+#include "backend/gen_register.hpp"
 #include "sys/platform.hpp"
 #include "sys/vector.hpp"
 #include <cassert>
 
-#define GEN_REG_SIZE 32
-#define GEN_EU_MAX_INSN_STACK 5
-
 namespace gbe
 {
-  /*! Type size in bytes for each Gen type */
-  INLINE int typeSize(uint32_t type) {
-    switch(type) {
-      case GEN_TYPE_UD:
-      case GEN_TYPE_D:
-      case GEN_TYPE_F:
-        return 4;
-      case GEN_TYPE_HF:
-      case GEN_TYPE_UW:
-      case GEN_TYPE_W:
-        return 2;
-      case GEN_TYPE_UB:
-      case GEN_TYPE_B:
-        return 1;
-      default:
-        assert(0);
-        return 0;
-    }
-  }
-
-  /*! Convert a hstride to a number of element */
-  INLINE uint32_t stride(uint32_t stride) {
-    switch (stride) {
-      case 0: return 0;
-      case 1: return 1;
-      case 2: return 2;
-      case 3: return 4;
-      case 4: return 8;
-      case 5: return 16;
-      default: assert(0); return 0;
-    }
-  }
-
-  /*! These are not hardware structs, just something useful to pass around */
-  class GenReg
-  {
-  public:
-    /*! Empty constructor */
-    INLINE GenReg(void) {}
-
-    /*! General constructor */
-    INLINE GenReg(uint32_t file,
-                  uint32_t nr,
-                  uint32_t subnr,
-                  uint32_t type,
-                  uint32_t vstride,
-                  uint32_t width,
-                  uint32_t hstride)
-    {
-      if (file == GEN_GENERAL_REGISTER_FILE)
-        assert(nr < GEN_MAX_GRF);
-      else if (file == GEN_ARCHITECTURE_REGISTER_FILE)
-        assert(nr <= GEN_ARF_IP);
-
-      this->type = type;
-      this->file = file;
-      this->nr = nr;
-      this->subnr = subnr * typeSize(type);
-      this->negation = 0;
-      this->absolute = 0;
-      this->vstride = vstride;
-      this->width = width;
-      this->hstride = hstride;
-      this->address_mode = GEN_ADDRESS_DIRECT;
-    }
-
-    /*! Build an indirectly addressed source */
-    static INLINE GenReg indirect(uint32_t type, uint32_t subnr, uint32_t width) {
-      GenReg reg;
-      reg.type = type;
-      reg.file = GEN_GENERAL_REGISTER_FILE;
-      reg.address_mode = GEN_ADDRESS_REGISTER_INDIRECT_REGISTER;
-      reg.width = width;
-      reg.subnr = subnr;
-      reg.nr = 0;
-      reg.negation = 0;
-      reg.absolute = 0;
-      reg.vstride = 0;
-      reg.hstride = 0;
-      return reg;
-    }
-
-    static INLINE GenReg Qn(GenReg reg, uint32_t quarter) {
-      if (reg.hstride == GEN_HORIZONTAL_STRIDE_0) // scalar register
-        return reg;
-      else {
-        const uint32_t typeSz = typeSize(reg.type);
-        const uint32_t horizontal = stride(reg.hstride);
-        const uint32_t grfOffset = reg.nr*GEN_REG_SIZE + reg.subnr;
-        const uint32_t nextOffset = grfOffset + 8*quarter*horizontal*typeSz;
-        reg.nr = nextOffset / GEN_REG_SIZE;
-        reg.subnr = (nextOffset % GEN_REG_SIZE);
-        return reg;
-      }
-    }
-
-    static INLINE GenReg vec16(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_F,
-                    GEN_VERTICAL_STRIDE_8,
-                    GEN_WIDTH_8,
-                    GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE GenReg vec8(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_F,
-                    GEN_VERTICAL_STRIDE_8,
-                    GEN_WIDTH_8,
-                    GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE GenReg vec4(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_F,
-                    GEN_VERTICAL_STRIDE_4,
-                    GEN_WIDTH_4,
-                    GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE GenReg vec2(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_F,
-                    GEN_VERTICAL_STRIDE_2,
-                    GEN_WIDTH_2,
-                    GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE GenReg vec1(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_F,
-                    GEN_VERTICAL_STRIDE_0,
-                    GEN_WIDTH_1,
-                    GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE GenReg retype(GenReg reg, uint32_t type) {
-      reg.type = type;
-      return reg;
-    }
-
-    static INLINE GenReg suboffset(GenReg reg, uint32_t delta) {
-      reg.subnr += delta * typeSize(reg.type);
-      return reg;
-    }
-
-    static INLINE GenReg ud16(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return retype(vec16(file, nr, subnr), GEN_TYPE_UD);
-    }
-
-    static INLINE GenReg ud8(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return retype(vec8(file, nr, subnr), GEN_TYPE_UD);
-    }
-
-    static INLINE GenReg ud1(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return retype(vec1(file, nr, subnr), GEN_TYPE_UD);
-    }
-
-    static INLINE GenReg d8(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return retype(vec8(file, nr, subnr), GEN_TYPE_D);
-    }
-
-    static INLINE GenReg uw16(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return suboffset(retype(vec16(file, nr, 0), GEN_TYPE_UW), subnr);
-    }
-
-    static INLINE GenReg uw8(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return suboffset(retype(vec8(file, nr, 0), GEN_TYPE_UW), subnr);
-    }
-
-    static INLINE GenReg uw1(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UW), subnr);
-    }
-
-    static INLINE GenReg ub16(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_UB,
-                    GEN_VERTICAL_STRIDE_16,
-                    GEN_WIDTH_8,
-                    GEN_HORIZONTAL_STRIDE_2);
-    }
-
-    static INLINE GenReg ub8(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return GenReg(file,
-                    nr,
-                    subnr,
-                    GEN_TYPE_UB,
-                    GEN_VERTICAL_STRIDE_16,
-                    GEN_WIDTH_8,
-                    GEN_HORIZONTAL_STRIDE_2);
-    }
-
-    static INLINE GenReg ub1(uint32_t file, uint32_t nr, uint32_t subnr) {
-      return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UB), subnr);
-    }
-
-    static INLINE GenReg imm(uint32_t type) {
-      return GenReg(GEN_IMMEDIATE_VALUE,
-                    0,
-                    0,
-                    type,
-                    GEN_VERTICAL_STRIDE_0,
-                    GEN_WIDTH_1,
-                    GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE GenReg immf(float f) {
-      GenReg immediate = imm(GEN_TYPE_F);
-      immediate.dw1.f = f;
-      return immediate;
-    }
-
-    static INLINE GenReg immd(int d) {
-      GenReg immediate = imm(GEN_TYPE_D);
-      immediate.dw1.d = d;
-      return immediate;
-    }
-
-    static INLINE GenReg immud(uint32_t ud) {
-      GenReg immediate = imm(GEN_TYPE_UD);
-      immediate.dw1.ud = ud;
-      return immediate;
-    }
-
-    static INLINE GenReg immuw(uint16_t uw) {
-      GenReg immediate = imm(GEN_TYPE_UW);
-      immediate.dw1.ud = uw | (uw << 16);
-      return immediate;
-    }
-
-    static INLINE GenReg immw(int16_t w) {
-      GenReg immediate = imm(GEN_TYPE_W);
-      immediate.dw1.d = w | (w << 16);
-      return immediate;
-    }
-
-    static INLINE GenReg immv(uint32_t v) {
-      GenReg immediate = imm(GEN_TYPE_V);
-      immediate.vstride = GEN_VERTICAL_STRIDE_0;
-      immediate.width = GEN_WIDTH_8;
-      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
-      immediate.dw1.ud = v;
-      return immediate;
-    }
-
-    static INLINE GenReg f1grf(uint32_t nr, uint32_t subnr) {
-      return vec1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg f2grf(uint32_t nr, uint32_t subnr) {
-      return vec2(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg f4grf(uint32_t nr, uint32_t subnr) {
-      return vec4(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg f8grf(uint32_t nr, uint32_t subnr) {
-      return vec8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg f16grf(uint32_t nr, uint32_t subnr) {
-      return vec16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ud16grf(uint32_t nr, uint32_t subnr) {
-      return ud16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ud8grf(uint32_t nr, uint32_t subnr) {
-      return ud8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ud1grf(uint32_t nr, uint32_t subnr) {
-      return ud1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg uw1grf(uint32_t nr, uint32_t subnr) {
-      return uw1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg uw8grf(uint32_t nr, uint32_t subnr) {
-      return uw8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg uw16grf(uint32_t nr, uint32_t subnr) {
-      return uw16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ub1grf(uint32_t nr, uint32_t subnr) {
-      return ub1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ub8grf(uint32_t nr, uint32_t subnr) {
-      return ub8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg ub16grf(uint32_t nr, uint32_t subnr) {
-      return ub16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
-    }
-
-    static INLINE GenReg null(void) {
-      return vec8(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_NULL, 0);
-    }
-
-    static INLINE GenReg acc(void) {
-      return vec8(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_ACCUMULATOR, 0);
-    }
-
-    static INLINE GenReg ip(void) {
-      return GenReg(GEN_ARCHITECTURE_REGISTER_FILE, 
-                    GEN_ARF_IP,
-                    0,
-                    GEN_TYPE_D,
-                    GEN_VERTICAL_STRIDE_4,
-                    GEN_WIDTH_1,
-                    GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE GenReg notification1(void) {
-      return GenReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                    GEN_ARF_NOTIFICATION_COUNT,
-                    1,
-                    GEN_TYPE_UD,
-                    GEN_VERTICAL_STRIDE_0,
-                    GEN_WIDTH_1,
-                    GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE GenReg flag(uint32_t nr, uint32_t subnr) {
-      return uw1(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_FLAG | nr, subnr);
-    }
-
-    static INLINE GenReg mask(uint32_t subnr) {
-      return uw1(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_MASK, subnr);
-    }
-
-    static INLINE GenReg addr1(uint32_t subnr) {
-      return uw1(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_ADDRESS, subnr);
-    }
-
-    static INLINE GenReg addr8(uint32_t subnr) {
-      return uw8(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_ADDRESS, subnr);
-    }
-
-    static INLINE GenReg next(GenReg reg) {
-      reg.nr++;
-      return reg;
-    }
-
-    static INLINE GenReg negate(GenReg reg) {
-      reg.negation ^= 1;
-      return reg;
-    }
-
-    static INLINE GenReg abs(GenReg reg) {
-      reg.absolute = 1;
-      reg.negation = 0;
-      return reg;
-    }
-
-    uint32_t type:4;
-    uint32_t file:2;
-    uint32_t nr:8;
-    uint32_t subnr:5;        /* :1 in align16 */
-    uint32_t negation:1;     /* source only */
-    uint32_t absolute:1;     /* source only */
-    uint32_t vstride:4;      /* source only */
-    uint32_t width:3;        /* src only, align1 only */
-    uint32_t hstride:2;      /* align1 only */
-    uint32_t address_mode:1; /* relative addressing, hopefully! */
-
-    union {
-      float f;
-      int32_t d;
-      uint32_t ud;
-    } dw1;
-  };
-
-  /*! The state for each instruction.  */
-  struct GenInstructionState
-  {
-    uint32_t execWidth:6;
-    uint32_t quarterControl:2;
-    uint32_t noMask:1;
-    uint32_t flag:1;
-    uint32_t subFlag:1;
-    uint32_t predicate:4;
-    uint32_t inversePredicate:1;
-  };
-
   /*! Helper structure to emit Gen instructions */
   class GenEncoder
   {
@@ -472,9 +67,9 @@ namespace gbe
     // Encoding functions
     ////////////////////////////////////////////////////////////////////////
 
-#define ALU1(OP) void OP(GenReg dest, GenReg src0);
-#define ALU2(OP) void OP(GenReg dest, GenReg src0, GenReg src1);
-#define ALU3(OP) void OP(GenReg dest, GenReg src0, GenReg src1, GenReg src2);
+#define ALU1(OP) void OP(GenRegister dest, GenRegister src0);
+#define ALU2(OP) void OP(GenRegister dest, GenRegister src0, GenRegister src1);
+#define ALU3(OP) void OP(GenRegister dest, GenRegister src0, GenRegister src1, GenRegister src2);
     ALU1(MOV)
     ALU1(RNDZ)
     ALU1(RNDE)
@@ -503,9 +98,9 @@ namespace gbe
 #undef ALU3
 
     /*! Jump indexed instruction */
-    void JMPI(GenReg src);
+    void JMPI(GenRegister src);
     /*! Compare instructions */
-    void CMP(uint32_t conditional, GenReg src0, GenReg src1);
+    void CMP(uint32_t conditional, GenRegister src0, GenRegister src1);
     /*! EOT is used to finish GPGPU threads */
     void EOT(uint32_t msg_nr);
     /*! No-op */
@@ -513,21 +108,21 @@ namespace gbe
     /*! Wait instruction (used for the barrier) */
     void WAIT(void);
     /*! Untyped read (upto 4 channels) */
-    void UNTYPED_READ(GenReg dst, GenReg src, uint32_t bti, uint32_t elemNum);
+    void UNTYPED_READ(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemNum);
     /*! Untyped write (upto 4 channels) */
-    void UNTYPED_WRITE(GenReg src, uint32_t bti, uint32_t elemNum);
+    void UNTYPED_WRITE(GenRegister src, uint32_t bti, uint32_t elemNum);
     /*! Byte gather (for unaligned bytes, shorts and ints) */
-    void BYTE_GATHER(GenReg dst, GenReg src, uint32_t bti, uint32_t elemSize);
+    void BYTE_GATHER(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemSize);
     /*! Byte scatter (for unaligned bytes, shorts and ints) */
-    void BYTE_SCATTER(GenReg src, uint32_t bti, uint32_t elemSize);
+    void BYTE_SCATTER(GenRegister src, uint32_t bti, uint32_t elemSize);
     /*! OBlock read */
-    void OBREAD(GenReg dst, GenReg header, uint32_t bti, uint32_t elemSize);
+    void OBREAD(GenRegister dst, GenRegister header, uint32_t bti, uint32_t elemSize);
     /*! OBlock read */
-    void OBWRITE(GenReg header, uint32_t bti, uint32_t elemSize);
+    void OBWRITE(GenRegister header, uint32_t bti, uint32_t elemSize);
     /*! Send instruction for the sampler */
-    void SAMPLE(GenReg dest,
+    void SAMPLE(GenRegister dest,
                 uint32_t msg_reg_nr,
-                GenReg src0,
+                GenRegister src0,
                 uint32_t bti,
                 uint32_t sampler,
                 uint32_t writemask,
@@ -538,7 +133,7 @@ namespace gbe
                 uint32_t simd_mode,
                 uint32_t return_format);
     /*! Extended math function */
-    void MATH(GenReg dst, uint32_t function, GenReg src0, GenReg src1);
+    void MATH(GenRegister dst, uint32_t function, GenRegister src0, GenRegister src1);
 
     /*! Patch JMPI (located at index insnID) with the given jump distance */
     void patchJMPI(uint32_t insnID, int32_t jumpDistance);
@@ -547,9 +142,9 @@ namespace gbe
     // Helper functions to encode
     ////////////////////////////////////////////////////////////////////////
     void setHeader(GenInstruction *insn);
-    void setDst(GenInstruction *insn, GenReg dest);
-    void setSrc0(GenInstruction *insn, GenReg reg);
-    void setSrc1(GenInstruction *insn, GenReg reg);
+    void setDst(GenInstruction *insn, GenRegister dest);
+    void setSrc0(GenInstruction *insn, GenRegister reg);
+    void setSrc1(GenInstruction *insn, GenRegister reg);
     GenInstruction *next(uint32_t opcode);
     GBE_CLASS(GenEncoder); //!< Use custom allocators
   };
index fc6096a..1c5ee9a 100644 (file)
 #include "backend/gen_insn_selection.hpp"
 #include "backend/gen_context.hpp"
 #include "ir/function.hpp"
+#include "sys/cvar.hpp"
 
 namespace gbe
 {
   ///////////////////////////////////////////////////////////////////////////
+  // SelectionInstruction
+  ///////////////////////////////////////////////////////////////////////////
+
+  void SelectionInstruction::appendBefore(const SelectionInstruction &other) {
+    Selection *selection = this->parent->parent;
+    SelectionInstruction *toAppend = selection->newSelectionInstruction(other);
+    SelectionInstruction *prev = this->prev;
+    this->prev = toAppend;
+    toAppend->next = this;
+    if (prev) {
+      toAppend->prev = prev;
+      prev->next = toAppend;
+    } else {
+      GBE_ASSERT (this == this->parent->insnHead);
+      this->parent->insnHead = toAppend;
+    }
+  }
+
+  void SelectionInstruction::appendAfter(const SelectionInstruction &other) {
+    Selection *selection = this->parent->parent;
+    SelectionInstruction *toAppend = selection->newSelectionInstruction(other);
+    SelectionInstruction *next = this->next;
+    this->next = toAppend;
+    toAppend->prev = this;
+    if (next) {
+      toAppend->next = next;
+      next->prev = toAppend;
+    } else {
+      GBE_ASSERT (this == this->parent->insnTail);
+      this->parent->insnTail = toAppend;
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
   // Selection
   ///////////////////////////////////////////////////////////////////////////
+
   Selection::Selection(GenContext &ctx) :
     ctx(ctx), blockHead(NULL), blockTail(NULL), block(NULL),
     curr(ctx.getSimdWidth()), file(ctx.getFunction().getRegisterFile()),
@@ -85,27 +121,13 @@ namespace gbe
     tmp = this->reg(ir::FAMILY_DWORD);
 
     // Generate the MOV instruction and replace the register in the instruction
-    SelectionInstruction *mov = this->newSelectionInstruction();
-    mov->opcode = SEL_OP_MOV;
-    mov->src[0] = SelectionReg::retype(insn->src[regID], GEN_TYPE_F);
-    mov->state = SelectionState(simdWidth);
-    mov->dstNum = mov->srcNum = 1;
-    if (simdWidth == 8)
-      insn->src[regID] = mov->dst[0] = SelectionReg::f8grf(tmp);
-    else
-      insn->src[regID] = mov->dst[0] = SelectionReg::f16grf(tmp);
-
-    // Insert the MOV instruction before the current instruction
-    SelectionInstruction *prev = insn->prev;
-    insn->prev = mov;
-    mov->next = insn;
-    if (prev) {
-      mov->prev = prev;
-      prev->next = mov;
-    } else {
-      GBE_ASSERT (insn == block->insnHead);
-      block->insnHead = mov;
-    }
+    SelectionInstruction mov;
+    mov.opcode = SEL_OP_MOV;
+    mov.src[0] = GenRegister::retype(insn->src[regID], GEN_TYPE_F);
+    mov.state = GenInstructionState(simdWidth);
+    mov.dstNum = mov.srcNum = 1;
+    insn->src[regID] = mov.dst[0] = GenRegister::fxgrf(simdWidth, tmp);
+    insn->appendBefore(mov);
 
     return tmp;
   }
@@ -120,27 +142,13 @@ namespace gbe
     tmp = this->reg(ir::FAMILY_DWORD);
 
     // Generate the MOV instruction and replace the register in the instruction
-    SelectionInstruction *mov = this->newSelectionInstruction();
-    mov->opcode = SEL_OP_MOV;
-    mov->dst[0] = SelectionReg::retype(insn->dst[regID], GEN_TYPE_F);
-    mov->state = SelectionState(simdWidth);
-    mov->dstNum = mov->srcNum = 1;
-    if (simdWidth == 8)
-      insn->dst[regID] = mov->src[0] = SelectionReg::f8grf(tmp);
-    else
-      insn->dst[regID] = mov->src[0] = SelectionReg::f16grf(tmp);
-
-    // Insert the MOV instruction after the current instruction
-    SelectionInstruction *next = insn->next;
-    insn->next = mov;
-    mov->prev = insn;
-    if (next) {
-      mov->next = next;
-      next->prev = mov;
-    } else {
-      GBE_ASSERT (insn == block->insnTail);
-      block->insnTail = mov;
-    }
+    SelectionInstruction mov;
+    mov.opcode = SEL_OP_MOV;
+    mov.dst[0] = GenRegister::retype(insn->dst[regID], GEN_TYPE_F);
+    mov.state = GenInstructionState(simdWidth);
+    mov.dstNum = mov.srcNum = 1;
+    insn->dst[regID] = mov.src[0] = GenRegister::fxgrf(simdWidth, tmp);
+    insn->appendAfter(mov);
 
     return tmp;
   }
@@ -156,15 +164,15 @@ namespace gbe
 
 #define SEL_REG(SIMD16, SIMD8, SIMD1) \
   if (ctx.sel->isScalarOrBool(reg) == true) \
-    return SelectionReg::retype(SelectionReg::SIMD1(reg), genType); \
+    return GenRegister::retype(GenRegister::SIMD1(reg), genType); \
   else if (simdWidth == 8) \
-    return SelectionReg::retype(SelectionReg::SIMD8(reg), genType); \
+    return GenRegister::retype(GenRegister::SIMD8(reg), genType); \
   else { \
     GBE_ASSERT (simdWidth == 16); \
-    return SelectionReg::retype(SelectionReg::SIMD16(reg), genType); \
+    return GenRegister::retype(GenRegister::SIMD16(reg), genType); \
   }
 
-  SelectionReg Selection::selReg(ir::Register reg, ir::Type type) {
+  GenRegister Selection::selReg(ir::Register reg, ir::Type type) {
     using namespace ir;
     const uint32_t genType = getGenType(type);
     const uint32_t simdWidth = ctx.getSimdWidth();
@@ -178,19 +186,19 @@ namespace gbe
       default: NOT_SUPPORTED;
     }
     GBE_ASSERT(false);
-    return SelectionReg();
+    return GenRegister();
   }
 
 #undef SEL_REG
 
-  SelectionReg Selection::selRegQn(ir::Register reg, uint32_t q, ir::Type type) {
-    SelectionReg sreg = this->selReg(reg, type);
+  GenRegister Selection::selRegQn(ir::Register reg, uint32_t q, ir::Type type) {
+    GenRegister sreg = this->selReg(reg, type);
     sreg.quarter = q;
     return sreg;
   }
 
   /*! Syntactic sugar for method declaration */
-  typedef const SelectionReg &Reg;
+  typedef const GenRegister &Reg;
 
   void Selection::LABEL(ir::LabelIndex index) {
     SelectionInstruction *insn = this->appendInsn();
@@ -244,7 +252,7 @@ namespace gbe
   }
 
   void Selection::UNTYPED_READ(Reg addr,
-                               const SelectionReg *dst,
+                               const GenRegister *dst,
                                uint32_t elemNum,
                                uint32_t bti)
   {
@@ -275,9 +283,9 @@ namespace gbe
   }
 
   void Selection::UNTYPED_WRITE(Reg addr,
-                               const SelectionReg *src,
-                               uint32_t elemNum,
-                               uint32_t bti)
+                                const GenRegister *src,
+                                uint32_t elemNum,
+                                uint32_t bti)
   {
     SelectionInstruction *insn = this->appendInsn();
     SelectionVector *vector = this->appendVector();
@@ -377,7 +385,7 @@ namespace gbe
     insn->dstNum = 1;
   }
 
-  void Selection::REGION(Reg dst0, Reg dst1, const SelectionReg *src,
+  void Selection::REGION(Reg dst0, Reg dst1, const GenRegister *src,
                          uint32_t offset, uint32_t vstride,
                          uint32_t width, uint32_t hstride,
                          uint32_t srcNum)
@@ -406,7 +414,7 @@ namespace gbe
     vector->isSrc = 1;
   }
 
-  void Selection::RGATHER(Reg dst, const SelectionReg *src, uint32_t srcNum)
+  void Selection::RGATHER(Reg dst, const GenRegister *src, uint32_t srcNum)
   {
     SelectionInstruction *insn = this->appendInsn();
     SelectionVector *vector = this->appendVector();
@@ -488,13 +496,13 @@ namespace gbe
     void emitFenceInstruction(const ir::FenceInstruction &insn);
     void emitLabelInstruction(const ir::LabelInstruction &insn);
     /*! It is not natively suppored on Gen. We implement it here */
-    void emitIntMul32x32(const ir::Instruction &insn, SelectionReg dst, SelectionReg src0, SelectionReg src1);
+    void emitIntMul32x32(const ir::Instruction &insn, GenRegister dst, GenRegister src0, GenRegister src1);
     /*! Use untyped writes and reads for everything aligned on 4 bytes */
-    void emitUntypedRead(const ir::LoadInstruction &insn, SelectionReg address);
+    void emitUntypedRead(const ir::LoadInstruction &insn, GenRegister address);
     void emitUntypedWrite(const ir::StoreInstruction &insn);
     /*! Use byte scatters and gathers for everything not aligned on 4 bytes */
-    void emitByteGather(const ir::LoadInstruction &insn, SelectionReg address, SelectionReg value);
-    void emitByteScatter(const ir::StoreInstruction &insn, SelectionReg address, SelectionReg value);
+    void emitByteGather(const ir::LoadInstruction &insn, GenRegister address, GenRegister value);
+    void emitByteScatter(const ir::StoreInstruction &insn, GenRegister address, GenRegister value);
     /*! Backward and forward branches are handled slightly differently */
     void emitForwardBranch(const ir::BranchInstruction&, ir::LabelIndex dst, ir::LabelIndex src);
     void emitBackwardBranch(const ir::BranchInstruction&, ir::LabelIndex dst, ir::LabelIndex src);
@@ -534,37 +542,37 @@ namespace gbe
   }
 
   void SimpleSelection::emitIntMul32x32(const ir::Instruction &insn,
-                                        SelectionReg dst,
-                                        SelectionReg src0,
-                                        SelectionReg src1)
+                                        GenRegister dst,
+                                        GenRegister src0,
+                                        GenRegister src1)
   {
     using namespace ir;
-    const uint32_t width = this->curr.execWidth;
+    const uint32_t simdWidth = this->curr.execWidth;
     this->push();
 
     // Either left part of the 16-wide register or just a simd 8 register
-    dst  = SelectionReg::retype(dst,  GEN_TYPE_D);
-    src0 = SelectionReg::retype(src0, GEN_TYPE_D);
-    src1 = SelectionReg::retype(src1, GEN_TYPE_D);
+    dst  = GenRegister::retype(dst,  GEN_TYPE_D);
+    src0 = GenRegister::retype(src0, GEN_TYPE_D);
+    src1 = GenRegister::retype(src1, GEN_TYPE_D);
     this->curr.execWidth = 8;
     this->curr.quarterControl = GEN_COMPRESSION_Q1;
-    this->MUL(SelectionReg::retype(SelectionReg::acc(), GEN_TYPE_D), src0, src1);
-    this->MACH(SelectionReg::retype(SelectionReg::null(), GEN_TYPE_D), src0, src1);
-    this->MOV(SelectionReg::retype(dst, GEN_TYPE_F), SelectionReg::acc());
+    this->MUL(GenRegister::retype(GenRegister::acc(), GEN_TYPE_D), src0, src1);
+    this->MACH(GenRegister::retype(GenRegister::null(), GEN_TYPE_D), src0, src1);
+    this->MOV(GenRegister::retype(dst, GEN_TYPE_F), GenRegister::acc());
 
     // Right part of the 16-wide register now
-    if (width == 16) {
+    if (simdWidth == 16) {
       this->curr.noMask = 1;
-      const SelectionReg nextSrc0 = this->selRegQn(insn.getSrc(0), 1, TYPE_S32);
-      const SelectionReg nextSrc1 = this->selRegQn(insn.getSrc(1), 1, TYPE_S32);
-      this->MUL(SelectionReg::retype(SelectionReg::acc(), GEN_TYPE_D), nextSrc0, nextSrc1);
-      this->MACH(SelectionReg::retype(SelectionReg::null(), GEN_TYPE_D), nextSrc0, nextSrc1);
+      const GenRegister nextSrc0 = this->selRegQn(insn.getSrc(0), 1, TYPE_S32);
+      const GenRegister nextSrc1 = this->selRegQn(insn.getSrc(1), 1, TYPE_S32);
+      this->MUL(GenRegister::retype(GenRegister::acc(), GEN_TYPE_D), nextSrc0, nextSrc1);
+      this->MACH(GenRegister::retype(GenRegister::null(), GEN_TYPE_D), nextSrc0, nextSrc1);
       this->curr.quarterControl = GEN_COMPRESSION_Q2;
       const ir::Register reg = this->reg(FAMILY_DWORD);
-      this->MOV(SelectionReg::f8grf(reg), SelectionReg::acc());
+      this->MOV(GenRegister::f8grf(reg), GenRegister::acc());
       this->curr.noMask = 0;
-      this->MOV(SelectionReg::retype(SelectionReg::next(dst), GEN_TYPE_F),
-                SelectionReg::f8grf(reg));
+      this->MOV(GenRegister::retype(GenRegister::next(dst), GEN_TYPE_F),
+                GenRegister::f8grf(reg));
     }
 
     this->pop();
@@ -574,9 +582,9 @@ namespace gbe
     using namespace ir;
     const Opcode opcode = insn.getOpcode();
     const Type type = insn.getType();
-    SelectionReg dst  = this->selReg(insn.getDst(0), type);
-    SelectionReg src0 = this->selReg(insn.getSrc(0), type);
-    SelectionReg src1 = this->selReg(insn.getSrc(1), type);
+    GenRegister dst  = this->selReg(insn.getDst(0), type);
+    GenRegister src0 = this->selReg(insn.getSrc(0), type);
+    GenRegister src1 = this->selReg(insn.getSrc(1), type);
 
     this->push();
 
@@ -590,7 +598,7 @@ namespace gbe
     // Output the binary instruction
     switch (opcode) {
       case OP_ADD: this->ADD(dst, src0, src1); break;
-      case OP_SUB: this->ADD(dst, src0, SelectionReg::negate(src1)); break;
+      case OP_SUB: this->ADD(dst, src0, GenRegister::negate(src1)); break;
       case OP_AND: this->AND(dst, src0, src1); break;
       case OP_XOR: this->XOR(dst, src0, src1); break;
       case OP_OR:  this->OR(dst, src0,  src1); break;
@@ -621,31 +629,23 @@ namespace gbe
 
     // Get all registers for the instruction
     const Type type = insn.getType();
-    const SelectionReg pred = this->selReg(insn.getPredicate(), TYPE_BOOL);
-    const SelectionReg dst  = this->selReg(insn.getDst(0), type);
-    const SelectionReg src0 = this->selReg(insn.getSrc(SelectInstruction::src0Index), type);
-    const SelectionReg src1 = this->selReg(insn.getSrc(SelectInstruction::src1Index), type);
+    const GenRegister dst  = this->selReg(insn.getDst(0), type);
+    const GenRegister src0 = this->selReg(insn.getSrc(SelectInstruction::src0Index), type);
+    const GenRegister src1 = this->selReg(insn.getSrc(SelectInstruction::src1Index), type);
 
     // Since we cannot predicate the select instruction with our current mask,
     // we need to perform the selection in two steps (one to select, one to
     // update the destination register)
     const RegisterFamily family = getFamily(type);
-    const SelectionReg tmp = this->selReg(this->reg(family), type);
+    const GenRegister tmp = this->selReg(this->reg(family), type);
     const uint32_t simdWidth = ctx.getSimdWidth();
-
+    const Register pred = insn.getPredicate();
     this->push();
-      // Move the predicate into a flag register (TODO use cmp:w with blockIP)
-      this->curr.predicate = GEN_PREDICATE_NONE;
-      this->curr.execWidth = 1;
-      this->curr.noMask = 1;
-      this->MOV(SelectionReg::flag(0,1), pred);
-
-      // Perform the selection
       this->curr.predicate = GEN_PREDICATE_NORMAL;
       this->curr.execWidth = simdWidth;
+      this->curr.physicalFlag = 0;
+      this->curr.flagIndex = uint16_t(pred);
       this->curr.noMask = 0;
-      this->curr.flag = 0;
-      this->curr.subFlag = 1;
       this->SEL(tmp, src0, src1);
     this->pop();
 
@@ -667,27 +667,27 @@ namespace gbe
     using namespace ir;
     const Type type = insn.getType();
     const Immediate imm = insn.getImmediate();
-    const SelectionReg dst = this->selReg(insn.getDst(0), type);
+    const GenRegister dst = this->selReg(insn.getDst(0), type);
 
     switch (type) {
-      case TYPE_U32: this->MOV(dst, SelectionReg::immud(imm.data.u32)); break;
-      case TYPE_S32: this->MOV(dst, SelectionReg::immd(imm.data.s32)); break;
-      case TYPE_U16: this->MOV(dst, SelectionReg::immuw(imm.data.u16)); break;
-      case TYPE_S16: this->MOV(dst, SelectionReg::immw(imm.data.s16)); break;
-      case TYPE_U8:  this->MOV(dst, SelectionReg::immuw(imm.data.u8)); break;
-      case TYPE_S8:  this->MOV(dst, SelectionReg::immw(imm.data.s8)); break;
-      case TYPE_FLOAT: this->MOV(dst, SelectionReg::immf(imm.data.f32)); break;
+      case TYPE_U32: this->MOV(dst, GenRegister::immud(imm.data.u32)); break;
+      case TYPE_S32: this->MOV(dst, GenRegister::immd(imm.data.s32)); break;
+      case TYPE_U16: this->MOV(dst, GenRegister::immuw(imm.data.u16)); break;
+      case TYPE_S16: this->MOV(dst, GenRegister::immw(imm.data.s16)); break;
+      case TYPE_U8:  this->MOV(dst, GenRegister::immuw(imm.data.u8)); break;
+      case TYPE_S8:  this->MOV(dst, GenRegister::immw(imm.data.s8)); break;
+      case TYPE_FLOAT: this->MOV(dst, GenRegister::immf(imm.data.f32)); break;
       default: NOT_SUPPORTED;
     }
   }
 
-  void SimpleSelection::emitUntypedRead(const ir::LoadInstruction &insn, SelectionReg addr)
+  void SimpleSelection::emitUntypedRead(const ir::LoadInstruction &insn, GenRegister addr)
   {
     using namespace ir;
     const uint32_t valueNum = insn.getValueNum();
-    SelectionReg dst[valueNum];
+    GenRegister dst[valueNum];
     for (uint32_t dstID = 0; dstID < valueNum; ++dstID)
-      dst[dstID] = SelectionReg::retype(this->selReg(insn.getValue(dstID)), GEN_TYPE_F);
+      dst[dstID] = GenRegister::retype(this->selReg(insn.getValue(dstID)), GEN_TYPE_F);
     this->UNTYPED_READ(addr, dst, valueNum, 0);
   }
 
@@ -710,8 +710,8 @@ namespace gbe
   }
 
   void SimpleSelection::emitByteGather(const ir::LoadInstruction &insn,
-                                       SelectionReg address,
-                                       SelectionReg value)
+                                       GenRegister address,
+                                       GenRegister value)
   {
     using namespace ir;
     GBE_ASSERT(insn.getValueNum() == 1);
@@ -724,31 +724,26 @@ namespace gbe
     if (elemSize == GEN_BYTE_SCATTER_WORD ||
         elemSize == GEN_BYTE_SCATTER_BYTE) {
       dst = this->reg(FAMILY_DWORD);
-      if (simdWidth == 8)
-        this->BYTE_GATHER(SelectionReg::f8grf(dst), address, elemSize, 0);
-      else if (simdWidth == 16)
-        this->BYTE_GATHER(SelectionReg::f16grf(dst), address, elemSize, 0);
-      else
-        NOT_IMPLEMENTED;
+      this->BYTE_GATHER(GenRegister::fxgrf(simdWidth, dst), address, elemSize, 0);
     }
 
     // Repack bytes or words using a converting mov instruction
     if (elemSize == GEN_BYTE_SCATTER_WORD)
-      this->MOV(SelectionReg::retype(value, GEN_TYPE_UW), SelectionReg::unpacked_uw(dst));
+      this->MOV(GenRegister::retype(value, GEN_TYPE_UW), GenRegister::unpacked_uw(dst));
     else if (elemSize == GEN_BYTE_SCATTER_BYTE)
-      this->MOV(SelectionReg::retype(value, GEN_TYPE_UB), SelectionReg::unpacked_ub(dst));
+      this->MOV(GenRegister::retype(value, GEN_TYPE_UB), GenRegister::unpacked_ub(dst));
   }
 
   void SimpleSelection::emitLoadInstruction(const ir::LoadInstruction &insn) {
     using namespace ir;
-    const SelectionReg address = this->selReg(insn.getAddress());
+    const GenRegister address = this->selReg(insn.getAddress());
     GBE_ASSERT(insn.getAddressSpace() == MEM_GLOBAL ||
                insn.getAddressSpace() == MEM_PRIVATE);
     GBE_ASSERT(ctx.isScalarReg(insn.getValue(0)) == false);
     if (insn.isAligned() == true)
       this->emitUntypedRead(insn, address);
     else {
-      const SelectionReg value = this->selReg(insn.getValue(0));
+      const GenRegister value = this->selReg(insn.getValue(0));
       this->emitByteGather(insn, address, value);
     }
   }
@@ -758,44 +753,32 @@ namespace gbe
     using namespace ir;
     const uint32_t valueNum = insn.getValueNum();
     const uint32_t addrID = ir::StoreInstruction::addressIndex;
-    SelectionReg addr, value[valueNum];
+    GenRegister addr, value[valueNum];
 
-    addr = SelectionReg::retype(this->selReg(insn.getSrc(addrID)), GEN_TYPE_F);;
+    addr = GenRegister::retype(this->selReg(insn.getSrc(addrID)), GEN_TYPE_F);;
     for (uint32_t valueID = 0; valueID < valueNum; ++valueID)
-      value[valueID] = SelectionReg::retype(this->selReg(insn.getValue(valueID)), GEN_TYPE_F);
+      value[valueID] = GenRegister::retype(this->selReg(insn.getValue(valueID)), GEN_TYPE_F);
     this->UNTYPED_WRITE(addr, value, valueNum, 0);
   }
 
   void SimpleSelection::emitByteScatter(const ir::StoreInstruction &insn,
-                                        SelectionReg addr,
-                                        SelectionReg value)
+                                        GenRegister addr,
+                                        GenRegister value)
   {
     using namespace ir;
     const Type type = insn.getValueType();
     const uint32_t elemSize = getByteScatterGatherSize(type);
     const uint32_t simdWidth = ctx.getSimdWidth();
-    const SelectionReg dst = value;
+    const GenRegister dst = value;
 
     GBE_ASSERT(insn.getValueNum() == 1);
-    if (simdWidth == 8) {
-      if (elemSize == GEN_BYTE_SCATTER_WORD) {
-        value = SelectionReg::ud8grf(this->reg(FAMILY_DWORD));
-        this->MOV(value, SelectionReg::retype(dst, GEN_TYPE_UW));
-      } else if (elemSize == GEN_BYTE_SCATTER_BYTE) {
-        value = SelectionReg::ud8grf(this->reg(FAMILY_DWORD));
-        this->MOV(value, SelectionReg::retype(dst, GEN_TYPE_UB));
-      }
-    } else if (simdWidth == 16) {
-      if (elemSize == GEN_BYTE_SCATTER_WORD) {
-        value = SelectionReg::ud16grf(this->reg(FAMILY_DWORD));
-        this->MOV(value, SelectionReg::retype(dst, GEN_TYPE_UW));
-      } else if (elemSize == GEN_BYTE_SCATTER_BYTE) {
-        value = SelectionReg::ud16grf(this->reg(FAMILY_DWORD));
-        this->MOV(value, SelectionReg::retype(dst, GEN_TYPE_UB));
-      }
-    } else
-      NOT_IMPLEMENTED;
-
+    if (elemSize == GEN_BYTE_SCATTER_WORD) {
+      value = GenRegister::udxgrf(simdWidth, this->reg(FAMILY_DWORD));
+      this->MOV(value, GenRegister::retype(dst, GEN_TYPE_UW));
+    } else if (elemSize == GEN_BYTE_SCATTER_BYTE) {
+      value = GenRegister::udxgrf(simdWidth, this->reg(FAMILY_DWORD));
+      this->MOV(value, GenRegister::retype(dst, GEN_TYPE_UB));
+    }
     this->BYTE_SCATTER(addr, value, elemSize, 1);
   }
 
@@ -804,8 +787,8 @@ namespace gbe
     if (insn.isAligned() == true)
       this->emitUntypedWrite(insn);
     else {
-      const SelectionReg address = this->selReg(insn.getAddress());
-      const SelectionReg value = this->selReg(insn.getValue(0));
+      const GenRegister address = this->selReg(insn.getAddress());
+      const GenRegister value = this->selReg(insn.getValue(0));
       this->emitByteScatter(insn, address, value);
     }
   }
@@ -815,7 +798,7 @@ namespace gbe
                                           ir::LabelIndex src)
   {
     using namespace ir;
-    const SelectionReg ip = this->selReg(ocl::blockip, TYPE_U16);
+    const GenRegister ip = this->selReg(ocl::blockip, TYPE_U16);
     const LabelIndex jip = ctx.getLabelIndex(&insn);
     const uint32_t simdWidth = ctx.getSimdWidth();
 
@@ -827,21 +810,13 @@ namespace gbe
     // Inefficient code. If the instruction is predicated, we build the flag
     // register from the boolean vector
     if (insn.isPredicated() == true) {
-      const SelectionReg pred = this->selReg(insn.getPredicateIndex(), TYPE_U16);
-
-      // Reset the flag register
-      this->push();
-        this->curr.predicate = GEN_PREDICATE_NONE;
-        this->curr.execWidth = 1;
-        this->curr.noMask = 1;
-        this->MOV(SelectionReg::flag(0,1), pred);
-      this->pop();
+      const Register pred = insn.getPredicateIndex();
 
       // Update the PcIPs
       this->push();
-        this->curr.flag = 0;
-        this->curr.subFlag = 1;
-        this->MOV(ip, SelectionReg::immuw(uint16_t(dst)));
+        this->curr.physicalFlag = 0;
+        this->curr.flagIndex = uint16_t(pred);
+        this->MOV(ip, GenRegister::immuw(uint16_t(dst)));
       this->pop();
 
       if (nextLabel == jip) return;
@@ -850,10 +825,10 @@ namespace gbe
       // all PcIPs are greater than the next block IP to be sure that we can
       // jump
       this->push();
+        this->curr.physicalFlag = 0;
+        this->curr.flagIndex = uint16_t(pred);
         this->curr.predicate = GEN_PREDICATE_NONE;
-        this->curr.flag = 0;
-        this->curr.subFlag = 1;
-        this->CMP(GEN_CONDITIONAL_G, ip, SelectionReg::immuw(nextLabel));
+        this->CMP(GEN_CONDITIONAL_G, ip, GenRegister::immuw(nextLabel));
 
         // Branch to the jump target
         if (simdWidth == 8)
@@ -864,12 +839,12 @@ namespace gbe
           NOT_SUPPORTED;
         this->curr.execWidth = 1;
         this->curr.noMask = 1;
-        this->JMPI(SelectionReg::immd(0), jip);
+        this->JMPI(GenRegister::immd(0), jip);
       this->pop();
 
     } else {
       // Update the PcIPs
-      this->MOV(ip, SelectionReg::immuw(uint16_t(dst)));
+      this->MOV(ip, GenRegister::immuw(uint16_t(dst)));
 
       // Do not emit branch when we go to the next block anyway
       if (nextLabel == jip) return;
@@ -877,7 +852,7 @@ namespace gbe
         this->curr.execWidth = 1;
         this->curr.noMask = 1;
         this->curr.predicate = GEN_PREDICATE_NONE;
-        this->JMPI(SelectionReg::immd(0), jip);
+        this->JMPI(GenRegister::immd(0), jip);
       this->pop();
     }
   }
@@ -887,7 +862,7 @@ namespace gbe
                                            ir::LabelIndex src)
   {
     using namespace ir;
-    const SelectionReg ip = this->selReg(ocl::blockip, TYPE_U16);
+    const GenRegister ip = this->selReg(ocl::blockip, TYPE_U16);
     const Function &fn = ctx.getFunction();
     const BasicBlock &bb = fn.getBlock(src);
     const LabelIndex jip = ctx.getLabelIndex(&insn);
@@ -896,28 +871,19 @@ namespace gbe
 
     // Inefficient code: we make a GRF to flag conversion
     if (insn.isPredicated() == true) {
-      const SelectionReg pred = this->selReg(insn.getPredicateIndex(), TYPE_U16);
+      const Register pred = insn.getPredicateIndex();
 
       // Update the PcIPs for all the branches. Just put the IPs of the next
       // block. Next instruction will properly reupdate the IPs of the lanes
       // that actually take the branch
       const LabelIndex next = bb.getNextBlock()->getLabelIndex();
-      this->MOV(ip, SelectionReg::immuw(uint16_t(next)));
-
-      // Rebuild the flag register by comparing the boolean with 1s
-      this->push();
-        this->curr.noMask = 1;
-        this->curr.execWidth = 1;
-        this->curr.predicate = GEN_PREDICATE_NONE;
-        this->MOV(SelectionReg::flag(0,1), pred);
-      this->pop();
+      this->MOV(ip, GenRegister::immuw(uint16_t(next)));
 
       this->push();
-        this->curr.flag = 0;
-        this->curr.subFlag = 1;
-
         // Re-update the PcIPs for the branches that takes the backward jump
-        this->MOV(ip, SelectionReg::immuw(uint16_t(dst)));
+        this->curr.physicalFlag = 0;
+        this->curr.flagIndex = uint16_t(pred);
+        this->MOV(ip, GenRegister::immuw(uint16_t(dst)));
 
         // Branch to the jump target
         if (simdWidth == 8)
@@ -928,55 +894,49 @@ namespace gbe
           NOT_SUPPORTED;
         this->curr.execWidth = 1;
         this->curr.noMask = 1;
-        this->JMPI(SelectionReg::immd(0), jip);
+        this->JMPI(GenRegister::immd(0), jip);
       this->pop();
 
     } else {
 
       // Update the PcIPs
-      this->MOV(ip, SelectionReg::immuw(uint16_t(dst)));
+      this->MOV(ip, GenRegister::immuw(uint16_t(dst)));
 
       // Branch to the jump target
       this->push();
         this->curr.execWidth = 1;
         this->curr.noMask = 1;
         this->curr.predicate = GEN_PREDICATE_NONE;
-        this->JMPI(SelectionReg::immd(0), jip);
+        this->JMPI(GenRegister::immd(0), jip);
       this->pop();
     }
   }
 
-
   void SimpleSelection::emitCompareInstruction(const ir::CompareInstruction &insn) {
     using namespace ir;
     const Opcode opcode = insn.getOpcode();
     const Type type = insn.getType();
     const uint32_t genCmp = getGenCompare(opcode);
-    const SelectionReg dst  = this->selReg(insn.getDst(0), TYPE_BOOL);
-    const SelectionReg src0 = this->selReg(insn.getSrc(0), type);
-    const SelectionReg src1 = this->selReg(insn.getSrc(1), type);
+    const Register dst  = insn.getDst(0);
+    const GenRegister src0 = this->selReg(insn.getSrc(0), type);
+    const GenRegister src1 = this->selReg(insn.getSrc(1), type);
 
-    // Copy the predicate to save it basically (TODO use cmp:w with blockIP)
+    // Limit the compare to the active lanes. Use the same compare as for f0.0
     this->push();
-      this->curr.noMask = 1;
-      this->curr.execWidth = 1;
+      const LabelIndex label = insn.getParent()->getLabelIndex();
+      const GenRegister blockip = this->selReg(ocl::blockip, TYPE_U16);
+      const GenRegister labelReg = GenRegister::immuw(label);
       this->curr.predicate = GEN_PREDICATE_NONE;
-      this->MOV(SelectionReg::flag(0,1), SelectionReg::flag(0,0));
+      this->curr.physicalFlag = 0;
+      this->curr.flagIndex = uint16_t(dst);
+      this->CMP(GEN_CONDITIONAL_LE, blockip, labelReg);
     this->pop();
 
-    // Emit the compare instruction itself
     this->push();
-      this->curr.flag = 0;
-      this->curr.subFlag = 1;
+      this->curr.physicalFlag = 0;
+      this->curr.flagIndex = uint16_t(dst);
       this->CMP(genCmp, src0, src1);
     this->pop();
-
-    // We emit an unoptimized code where we store the resulting mask in a GRF
-    this->push();
-      this->curr.execWidth = 1;
-      this->curr.predicate = GEN_PREDICATE_NONE;
-      this->MOV(dst, SelectionReg::flag(0,1));
-    this->pop();
   }
 
   void SimpleSelection::emitConvertInstruction(const ir::ConvertInstruction &insn) {
@@ -985,22 +945,22 @@ namespace gbe
     const Type srcType = insn.getSrcType();
     const RegisterFamily dstFamily = getFamily(dstType);
     const RegisterFamily srcFamily = getFamily(srcType);
-    const SelectionReg dst = this->selReg(insn.getDst(0), dstType);
-    const SelectionReg src = this->selReg(insn.getSrc(0), srcType);
+    const GenRegister dst = this->selReg(insn.getDst(0), dstType);
+    const GenRegister src = this->selReg(insn.getSrc(0), srcType);
 
     GBE_ASSERT(dstFamily != FAMILY_QWORD && srcFamily != FAMILY_QWORD);
 
     // We need two instructions to make the conversion
     if (dstFamily != FAMILY_DWORD && srcFamily == FAMILY_DWORD) {
-      SelectionReg unpacked;
+      GenRegister unpacked;
       if (dstFamily == FAMILY_WORD) {
         const uint32_t type = TYPE_U16 ? GEN_TYPE_UW : GEN_TYPE_W;
-        unpacked = SelectionReg::unpacked_uw(this->reg(FAMILY_DWORD));
-        unpacked = SelectionReg::retype(unpacked, type);
+        unpacked = GenRegister::unpacked_uw(this->reg(FAMILY_DWORD));
+        unpacked = GenRegister::retype(unpacked, type);
       } else {
         const uint32_t type = TYPE_U8 ? GEN_TYPE_UB : GEN_TYPE_B;
-        unpacked = SelectionReg::unpacked_ub(this->reg(FAMILY_DWORD));
-        unpacked = SelectionReg::retype(unpacked, type);
+        unpacked = GenRegister::unpacked_ub(this->reg(FAMILY_DWORD));
+        unpacked = GenRegister::retype(unpacked, type);
       }
       this->MOV(unpacked, src);
       this->MOV(dst, unpacked);
@@ -1030,8 +990,8 @@ namespace gbe
   void SimpleSelection::emitLabelInstruction(const ir::LabelInstruction &insn) {
     using namespace ir;
     const LabelIndex label = insn.getLabelIndex();
-    const SelectionReg src0 = this->selReg(ocl::blockip);
-    const SelectionReg src1 = SelectionReg::immuw(label);
+    const GenRegister src0 = this->selReg(ocl::blockip);
+    const GenRegister src1 = GenRegister::immuw(label);
     const uint32_t simdWidth = ctx.getSimdWidth();
     this->LABEL(label);
 
@@ -1039,7 +999,8 @@ namespace gbe
     this->push();
       this->curr.predicate = GEN_PREDICATE_NONE;
       this->curr.flag = 0;
-      this->CMP(GEN_CONDITIONAL_LE, SelectionReg::retype(src0, GEN_TYPE_UW), src1);
+      this->curr.subFlag = 0;
+      this->CMP(GEN_CONDITIONAL_LE, GenRegister::retype(src0, GEN_TYPE_UW), src1);
     this->pop();
 
     // If it is required, insert a JUMP to bypass the block
@@ -1057,7 +1018,7 @@ namespace gbe
         this->curr.flag = 0;
         this->curr.subFlag = 0;
         this->curr.noMask = 1;
-        this->JMPI(SelectionReg::immd(0), jip);
+        this->JMPI(GenRegister::immd(0), jip);
       this->pop();
     }
   }
@@ -1066,14 +1027,14 @@ namespace gbe
     using namespace ir;
 
     // Two destinations: one is the real destination, one is a temporary
-    SelectionReg dst0 = this->selReg(insn.getDst(0)), dst1;
+    GenRegister dst0 = this->selReg(insn.getDst(0)), dst1;
     if (ctx.getSimdWidth() == 8)
-      dst1 = SelectionReg::ud8grf(this->reg(FAMILY_DWORD));
+      dst1 = GenRegister::ud8grf(this->reg(FAMILY_DWORD));
     else
-      dst1 = SelectionReg::ud16grf(this->reg(FAMILY_DWORD));
+      dst1 = GenRegister::ud16grf(this->reg(FAMILY_DWORD));
 
     // Get all the sources
-    SelectionReg src[SelectionInstruction::MAX_SRC_NUM];
+    GenRegister src[SelectionInstruction::MAX_SRC_NUM];
     const uint32_t srcNum = insn.getSrcNum();
     GBE_ASSERT(srcNum <= SelectionInstruction::MAX_SRC_NUM);
     for (uint32_t srcID = 0; srcID < insn.getSrcNum(); ++srcID)
@@ -1090,16 +1051,18 @@ namespace gbe
   void SimpleSelection::emitVoteInstruction(const ir::VoteInstruction &insn) {
     using namespace ir;
     const uint32_t simdWidth = ctx.getSimdWidth();
-    const SelectionReg dst = this->selReg(insn.getDst(0), TYPE_U16);
-    const SelectionReg src = this->selReg(insn.getSrc(0), TYPE_U16);
+    const GenRegister dst = this->selReg(insn.getDst(0), TYPE_U16);
+    const GenRegister src = this->selReg(insn.getSrc(0), TYPE_U16);
 
-    // Limit the vote to the active lanes
+    // Limit the vote to the active lanes. Use the same compare as for f0.0
     this->push();
-      // Move the predicate into a flag register (TODO use cmp:w with blockIP)
+      const LabelIndex label = insn.getParent()->getLabelIndex();
+      const GenRegister blockip = this->selReg(ocl::blockip, TYPE_U16);
+      const GenRegister labelReg = GenRegister::immuw(label);
       this->curr.predicate = GEN_PREDICATE_NONE;
-      this->curr.execWidth = 1;
-      this->curr.noMask = 1;
-      this->MOV(SelectionReg::flag(0,1), SelectionReg::flag(0,0));
+      this->curr.flag = 0;
+      this->curr.subFlag = 1;
+      this->CMP(GEN_CONDITIONAL_LE, blockip, labelReg);
     this->pop();
 
     // Emit the compare instruction to get the flag register
@@ -1108,18 +1071,18 @@ namespace gbe
       const uint32_t genCmp = vote == VOTE_ANY ? GEN_CONDITIONAL_NEQ : GEN_CONDITIONAL_EQ;
       this->curr.flag = 0;
       this->curr.subFlag = 1;
-      this->CMP(genCmp, src, SelectionReg::immuw(0));
+      this->CMP(genCmp, src, GenRegister::immuw(0));
     this->pop();
 
     // Broadcast the result to the destination
     if (vote == VOTE_ANY)
-        this->MOV(dst, SelectionReg::flag(0,1));
+      this->MOV(dst, GenRegister::flag(0,1));
     else {
-      const SelectionReg tmp = this->selReg(this->reg(FAMILY_WORD), TYPE_U16);
+      const GenRegister tmp = this->selReg(this->reg(FAMILY_WORD), TYPE_U16);
       this->push();
         // Set all lanes of tmp to zero
         this->curr.predicate = GEN_PREDICATE_NONE;
-        this->MOV(tmp, SelectionReg::immuw(0));
+        this->MOV(tmp, GenRegister::immuw(0));
 
         // Compute the short values with no mask
         this->curr.flag = 0;
@@ -1128,7 +1091,7 @@ namespace gbe
         this->curr.predicate = simdWidth == 8 ?
           GEN_PREDICATE_ALIGN1_ANY8H :
           GEN_PREDICATE_ALIGN1_ANY16H;
-        this->MOV(tmp, SelectionReg::immuw(1));
+        this->MOV(tmp, GenRegister::immuw(1));
       this->pop();
 
       // Update the destination with the proper mask
@@ -1139,10 +1102,10 @@ namespace gbe
   void SimpleSelection::emitRGatherInstruction(const ir::RGatherInstruction &insn) {
     using namespace ir;
     // Two destinations: one is the real destination, one is a temporary
-    const SelectionReg dst = this->selReg(insn.getDst(0)), dst1;
+    const GenRegister dst = this->selReg(insn.getDst(0)), dst1;
 
     // Get all the sources
-    SelectionReg src[SelectionInstruction::MAX_SRC_NUM];
+    GenRegister src[SelectionInstruction::MAX_SRC_NUM];
     const uint32_t srcNum = insn.getSrcNum();
     GBE_ASSERT(srcNum <= SelectionInstruction::MAX_SRC_NUM);
     for (uint32_t srcID = 0; srcID < insn.getSrcNum(); ++srcID)
@@ -1154,18 +1117,18 @@ namespace gbe
 
   void SimpleSelection::emitOBReadInstruction(const ir::OBReadInstruction &insn) {
     using namespace ir;
-    const SelectionReg header = this->selReg(this->reg(FAMILY_DWORD), TYPE_U32);
-    const SelectionReg addr = this->selReg(insn.getAddress(), TYPE_U32);
-    const SelectionReg value = this->selReg(insn.getValue(), TYPE_U32);
+    const GenRegister header = this->selReg(this->reg(FAMILY_DWORD), TYPE_U32);
+    const GenRegister addr = this->selReg(insn.getAddress(), TYPE_U32);
+    const GenRegister value = this->selReg(insn.getValue(), TYPE_U32);
     const uint32_t simdWidth = ctx.getSimdWidth();
     this->OBREAD(value, addr, header, 0xff, simdWidth * sizeof(int));
   }
 
   void SimpleSelection::emitOBWriteInstruction(const ir::OBWriteInstruction &insn) {
     using namespace ir;
-    const SelectionReg header = this->selReg(this->reg(FAMILY_DWORD), TYPE_U32);
-    const SelectionReg addr = this->selReg(insn.getAddress(), TYPE_U32);
-    const SelectionReg value = this->selReg(insn.getValue(), TYPE_U32);
+    const GenRegister header = this->selReg(this->reg(FAMILY_DWORD), TYPE_U32);
+    const GenRegister addr = this->selReg(insn.getAddress(), TYPE_U32);
+    const GenRegister value = this->selReg(insn.getValue(), TYPE_U32);
     const uint32_t simdWidth = ctx.getSimdWidth();
     this->OBWRITE(addr, value, header, 0xff, simdWidth * sizeof(int));
   }
index 935dd95..9336fd0 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ir/register.hpp"
 #include "ir/instruction.hpp"
-#include "backend/gen_defs.hpp"
+#include "backend/gen_register.hpp"
 #include "backend/gen_encoder.hpp"
 #include "backend/gen_context.hpp"
 #include "sys/vector.hpp"
@@ -64,418 +64,6 @@ namespace gbe
     };
   }
 
-  /*! The state of each instruction */
-  class SelectionState
-  {
-  public:
-    INLINE SelectionState(uint32_t simdWidth = 8) {
-      this->execWidth = simdWidth;
-      this->quarterControl = GEN_COMPRESSION_Q1;
-      this->noMask = 0;
-      this->flag = 0;
-      this->subFlag = 0;
-      this->predicate = GEN_PREDICATE_NORMAL;
-      this->inversePredicate = 0;
-    }
-    uint32_t execWidth:6;
-    uint32_t quarterControl:2;
-    uint32_t noMask:1;
-    uint32_t flag:1;
-    uint32_t subFlag:1;
-    uint32_t predicate:4;
-    uint32_t inversePredicate:1;
-  };
-
-  /*! This is a book-keeping structure that is not exactly a virtual register
-   *  and not exactly a physical register. Basically, it is a Gen register
-   *  *before* the register allocation i.e. it contains the info to get it
-   *  properly encoded later but it is not associated to a GRF, a flag or
-   *  anything Gen related yet.
-   */
-  class SelectionReg
-  {
-  public:
-    /*! Empty constructor */
-    INLINE SelectionReg(void) {}
-
-    /*! General constructor */
-    INLINE SelectionReg(uint32_t file,
-                        ir::Register reg,
-                        uint32_t type,
-                        uint32_t vstride,
-                        uint32_t width,
-                        uint32_t hstride)
-    {
-      this->type = type;
-      this->file = file;
-      this->reg = reg;
-      this->negation = 0;
-      this->absolute = 0;
-      this->vstride = vstride;
-      this->width = width;
-      this->hstride = hstride;
-      this->quarter = 0;
-      this->nr = this->subnr = 0;
-    }
-
-    /*! For specific physical registers only (acc, null) */
-    INLINE SelectionReg(uint32_t file,
-                        uint32_t nr,
-                        uint32_t subnr,
-                        uint32_t type,
-                        uint32_t vstride,
-                        uint32_t width,
-                        uint32_t hstride)
-    {
-      this->type = type;
-      this->file = file;
-      this->nr = nr;
-      this->subnr = subnr * typeSize(type);
-      this->negation = 0;
-      this->absolute = 0;
-      this->vstride = vstride;
-      this->width = width;
-      this->hstride = hstride;
-      this->quarter = 0;
-    }
-
-    /*! Associated virtual register */
-    ir::Register reg;
-
-    /*! For immediates */
-    union {
-      float f;
-      int32_t d;
-      uint32_t ud;
-    } immediate;
-
-    uint32_t nr:8;        //!< Just for some physical registers (acc, null)
-    uint32_t subnr:5;     //!< Idem
-    uint32_t type:4;      //!< Gen type
-    uint32_t file:2;      //!< Register file
-    uint32_t negation:1;  //!< For source
-    uint32_t absolute:1;  //!< For source
-    uint32_t vstride:4;   //!< Vertical stride
-    uint32_t width:3;     //!< Width
-    uint32_t hstride:2;   //!< Horizontal stride
-    uint32_t quarter:2;   //!< To choose which part we want
-
-    static INLINE SelectionReg Qn(SelectionReg reg, uint32_t quarter) {
-      if (reg.hstride == GEN_HORIZONTAL_STRIDE_0) // scalar register
-        return reg;
-      else {
-        reg.quarter = quarter;
-        return reg;
-      }
-    }
-
-    static INLINE SelectionReg vec16(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_8,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg vec8(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_8,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg vec4(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_4,
-                          GEN_WIDTH_4,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg vec2(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_2,
-                          GEN_WIDTH_2,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg vec1(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_0,
-                          GEN_WIDTH_1,
-                          GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE SelectionReg retype(SelectionReg reg, uint32_t type) {
-      reg.type = type;
-      return reg;
-    }
-
-    static INLINE SelectionReg ud16(uint32_t file, ir::Register reg) {
-      return retype(vec16(file, reg), GEN_TYPE_UD);
-    }
-
-    static INLINE SelectionReg ud8(uint32_t file, ir::Register reg) {
-      return retype(vec8(file, reg), GEN_TYPE_UD);
-    }
-
-    static INLINE SelectionReg ud1(uint32_t file, ir::Register reg) {
-      return retype(vec1(file, reg), GEN_TYPE_UD);
-    }
-
-    static INLINE SelectionReg d8(uint32_t file, ir::Register reg) {
-      return retype(vec8(file, reg), GEN_TYPE_D);
-    }
-
-    static INLINE SelectionReg uw16(uint32_t file, ir::Register reg) {
-      return retype(vec16(file, reg), GEN_TYPE_UW);
-    }
-
-    static INLINE SelectionReg uw8(uint32_t file, ir::Register reg) {
-      return retype(vec8(file, reg), GEN_TYPE_UW);
-    }
-
-    static INLINE SelectionReg uw1(uint32_t file, ir::Register reg) {
-      return retype(vec1(file, reg), GEN_TYPE_UW);
-    }
-
-    static INLINE SelectionReg ub16(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_UB,
-                          GEN_VERTICAL_STRIDE_16,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_2);
-    }
-
-    static INLINE SelectionReg ub8(uint32_t file, ir::Register reg) {
-      return SelectionReg(file,
-                          reg,
-                          GEN_TYPE_UB,
-                          GEN_VERTICAL_STRIDE_16,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_2);
-    }
-
-    static INLINE SelectionReg ub1(uint32_t file, ir::Register reg) {
-      return retype(vec1(file, reg), GEN_TYPE_UB);
-    }
-
-    static INLINE SelectionReg unpacked_uw(ir::Register reg) {
-        return SelectionReg(GEN_GENERAL_REGISTER_FILE,
-                            reg,
-                            GEN_TYPE_UW,
-                            GEN_VERTICAL_STRIDE_16,
-                            GEN_WIDTH_8,
-                            GEN_HORIZONTAL_STRIDE_2);
-    }
-
-    static INLINE SelectionReg unpacked_ub(ir::Register reg) {
-      return SelectionReg(GEN_GENERAL_REGISTER_FILE,
-                          reg,
-                          GEN_TYPE_UB,
-                          GEN_VERTICAL_STRIDE_32,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_4);
-    }
-
-    static INLINE SelectionReg imm(uint32_t type) {
-      return SelectionReg(GEN_IMMEDIATE_VALUE,
-                          ir::Register(),
-                          type,
-                          GEN_VERTICAL_STRIDE_0,
-                          GEN_WIDTH_1,
-                          GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE SelectionReg immf(float f) {
-      SelectionReg immediate = imm(GEN_TYPE_F);
-      immediate.immediate.f = f;
-      return immediate;
-    }
-
-    static INLINE SelectionReg immd(int d) {
-      SelectionReg immediate = imm(GEN_TYPE_D);
-      immediate.immediate.d = d;
-      return immediate;
-    }
-
-    static INLINE SelectionReg immud(uint32_t ud) {
-      SelectionReg immediate = imm(GEN_TYPE_UD);
-      immediate.immediate.ud = ud;
-      return immediate;
-    }
-
-    static INLINE SelectionReg immuw(uint16_t uw) {
-      SelectionReg immediate = imm(GEN_TYPE_UW);
-      immediate.immediate.ud = uw | (uw << 16);
-      return immediate;
-    }
-
-    static INLINE SelectionReg immw(int16_t w) {
-      SelectionReg immediate = imm(GEN_TYPE_W);
-      immediate.immediate.d = w | (w << 16);
-      return immediate;
-    }
-
-    static INLINE SelectionReg immv(uint32_t v) {
-      SelectionReg immediate = imm(GEN_TYPE_V);
-      immediate.vstride = GEN_VERTICAL_STRIDE_0;
-      immediate.width = GEN_WIDTH_8;
-      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
-      immediate.immediate.ud = v;
-      return immediate;
-    }
-
-    static INLINE SelectionReg immvf(uint32_t v) {
-      SelectionReg immediate = imm(GEN_TYPE_VF);
-      immediate.vstride = GEN_VERTICAL_STRIDE_0;
-      immediate.width = GEN_WIDTH_4;
-      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
-      immediate.immediate.ud = v;
-      return immediate;
-    }
-
-    static INLINE SelectionReg immvf4(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
-      SelectionReg immediate = imm(GEN_TYPE_VF);
-      immediate.vstride = GEN_VERTICAL_STRIDE_0;
-      immediate.width = GEN_WIDTH_4;
-      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
-      immediate.immediate.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
-      return immediate;
-    }
-
-    static INLINE SelectionReg f1grf(ir::Register reg) {
-      return vec1(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg f2grf(ir::Register reg) {
-      return vec2(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg f4grf(ir::Register reg) {
-      return vec4(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg f8grf(ir::Register reg) {
-      return vec8(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg f16grf(ir::Register reg) {
-      return vec16(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ud16grf(ir::Register reg) {
-      return ud16(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ud8grf(ir::Register reg) {
-      return ud8(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ud1grf(ir::Register reg) {
-      return ud1(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg uw1grf(ir::Register reg) {
-      return uw1(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg uw8grf(ir::Register reg) {
-      return uw8(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg uw16grf(ir::Register reg) {
-      return uw16(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ub1grf(ir::Register reg) {
-      return ub1(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ub8grf(ir::Register reg) {
-      return ub8(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg ub16grf(ir::Register reg) {
-      return ub16(GEN_GENERAL_REGISTER_FILE, reg);
-    }
-
-    static INLINE SelectionReg null(void) {
-      return SelectionReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                          GEN_ARF_NULL,
-                          0,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_8,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg acc(void) {
-      return SelectionReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                          GEN_ARF_ACCUMULATOR,
-                          0,
-                          GEN_TYPE_F,
-                          GEN_VERTICAL_STRIDE_8,
-                          GEN_WIDTH_8,
-                          GEN_HORIZONTAL_STRIDE_1);
-    }
-
-    static INLINE SelectionReg ip(void) {
-      return SelectionReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                          GEN_ARF_IP,
-                          0,
-                          GEN_TYPE_D,
-                          GEN_VERTICAL_STRIDE_4,
-                          GEN_WIDTH_1,
-                          GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE SelectionReg notification1(void) {
-      return SelectionReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                          GEN_ARF_NOTIFICATION_COUNT,
-                          1,
-                          GEN_TYPE_UD,
-                          GEN_VERTICAL_STRIDE_0,
-                          GEN_WIDTH_1,
-                          GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE SelectionReg flag(uint32_t nr, uint32_t subnr) {
-      return SelectionReg(GEN_ARCHITECTURE_REGISTER_FILE,
-                          GEN_ARF_FLAG | nr,
-                          subnr,
-                          GEN_TYPE_UW,
-                          GEN_VERTICAL_STRIDE_0,
-                          GEN_WIDTH_1,
-                          GEN_HORIZONTAL_STRIDE_0);
-    }
-
-    static INLINE SelectionReg next(SelectionReg reg) {
-      reg.quarter++;
-      return reg;
-    }
-
-    static INLINE SelectionReg negate(SelectionReg reg) {
-      reg.negation ^= 1;
-      return reg;
-    }
-
-    static INLINE SelectionReg abs(SelectionReg reg) {
-      reg.absolute = 1;
-      reg.negation = 0;
-      return reg;
-    }
-  };
-
   /*! Selection opcodes properly encoded from 0 to n for fast jump tables
    *  generations
    */
@@ -499,16 +87,20 @@ namespace gbe
     SelectionBlock *parent;
     /*! Instruction are chained in the block */
     SelectionInstruction *prev, *next;
+    /*! Append an instruction before this one */
+    void appendBefore(const SelectionInstruction &insn);
+    /*! Append an instruction after this one */
+    void appendAfter(const SelectionInstruction &insn);
     /*! No more than 6 sources (used by typed writes) */
     enum { MAX_SRC_NUM = 8 };
     /*! No more than 4 destinations (used by samples and untyped reads) */
     enum { MAX_DST_NUM = 4 };
     /*! All destinations */
-    SelectionReg dst[MAX_DST_NUM];
+    GenRegister dst[MAX_DST_NUM];
     /*! All sources */
-    SelectionReg src[MAX_SRC_NUM];
+    GenRegister src[MAX_SRC_NUM];
     /*! State of the instruction (extra fields neeed for the encoding) */
-    SelectionState state;
+    GenInstructionState state;
     /*! Gen opcode */
     uint8_t opcode;
     union {
@@ -550,7 +142,7 @@ namespace gbe
     /*! We chain the selection vectors together */
     SelectionVector *next;
     /*! Directly points to the selection instruction registers */
-    SelectionReg *reg;
+    GenRegister *reg;
     /*! Number of registers in the vector */
     uint16_t regNum;
     /*! Indicate if this a destination or a source vector */
@@ -660,6 +252,10 @@ namespace gbe
     INLINE ir::RegisterData getRegisterData(ir::Register reg) const {
       return file.get(reg);
     }
+    /*! Get the family for the given register */
+    INLINE ir::RegisterFamily getRegisterFamily(ir::Register reg) const {
+      return file.get(reg).family;
+    }
     /*! Registers in the register file */
     INLINE uint32_t regNum(void) const { return file.regNum(); }
   protected:
@@ -691,9 +287,9 @@ namespace gbe
     /*! Append a new vector of registers in the current block */
     SelectionVector *appendVector(void);
     /*! Return the selection register from the GenIR one */
-    SelectionReg selReg(ir::Register, ir::Type type = ir::TYPE_FLOAT);
+    GenRegister selReg(ir::Register, ir::Type type = ir::TYPE_FLOAT);
     /*! Compute the nth register part when using SIMD8 with Qn (n in 2,3,4) */
-    SelectionReg selRegQn(ir::Register, uint32_t quarter, ir::Type type = ir::TYPE_FLOAT);
+    GenRegister selRegQn(ir::Register, uint32_t quarter, ir::Type type = ir::TYPE_FLOAT);
     /*! To handle selection block allocation */
     DECL_POOL(SelectionBlock, blockPool);
     /*! To handle selection instruction allocation */
@@ -707,9 +303,9 @@ namespace gbe
     /*! Currently processed block */
     SelectionBlock *block;
     /*! Current instruction state to use */
-    SelectionState curr;
+    GenInstructionState curr;
     /*! State used to encode the instructions */
-    SelectionState stack[MAX_STATE_NUM];
+    GenInstructionState stack[MAX_STATE_NUM];
     /*! We append new registers so we duplicate the function register file */
     ir::RegisterFile file;
     /*! Number of states currently pushed */
@@ -717,7 +313,7 @@ namespace gbe
     /*! Number of vector allocated */
     uint32_t vectorNum;
     /*! To make function prototypes more readable */
-    typedef const SelectionReg &Reg;
+    typedef const GenRegister &Reg;
 
 #define ALU1(OP) \
   INLINE void OP(Reg dst, Reg src) { ALU1(SEL_OP_##OP, dst, src); }
@@ -758,9 +354,9 @@ namespace gbe
     /*! Wait instruction (used for the barrier) */
     void WAIT(void);
     /*! Untyped read (up to 4 elements) */
-    void UNTYPED_READ(Reg addr, const SelectionReg *dst, uint32_t elemNum, uint32_t bti);
+    void UNTYPED_READ(Reg addr, const GenRegister *dst, uint32_t elemNum, uint32_t bti);
     /*! Untyped write (up to 4 elements) */
-    void UNTYPED_WRITE(Reg addr, const SelectionReg *src, uint32_t elemNum, uint32_t bti);
+    void UNTYPED_WRITE(Reg addr, const GenRegister *src, uint32_t elemNum, uint32_t bti);
     /*! Byte gather (for unaligned bytes, shorts and ints) */
     void BYTE_GATHER(Reg dst, Reg addr, uint32_t elemSize, uint32_t bti);
     /*! Byte scatter (for unaligned bytes, shorts and ints) */
@@ -776,11 +372,13 @@ namespace gbe
     /*! Encode binary instructions */
     void ALU2(uint32_t opcode, Reg dst, Reg src0, Reg src1);
     /*! Encode regioning */
-    void REGION(Reg dst0, Reg dst1, const SelectionReg *src, uint32_t offset, uint32_t vstride, uint32_t width, uint32_t hstride, uint32_t srcNum);
+    void REGION(Reg dst0, Reg dst1, const GenRegister *src, uint32_t offset, uint32_t vstride, uint32_t width, uint32_t hstride, uint32_t srcNum);
     /*! Encode regioning */
-    void RGATHER(Reg dst, const SelectionReg *src, uint32_t srcNum);
+    void RGATHER(Reg dst, const GenRegister *src, uint32_t srcNum);
     /*! Use custom allocators */
     GBE_CLASS(Selection);
+    friend class SelectionBlock;
+    friend class SelectionInstruction;
   };
 
   /*! This is a simple one-to-many instruction selection */
index 3c4ff0c..6ec8bdf 100644 (file)
@@ -26,6 +26,7 @@
 #include "ir/function.hpp"
 #include "backend/gen_insn_selection.hpp"
 #include "backend/gen_reg_allocation.hpp"
+#include "backend/gen_register.hpp"
 #include "backend/program.hpp"
 #include <algorithm>
 #include <climits>
@@ -50,16 +51,6 @@ namespace gbe
   GenRegAllocator::GenRegAllocator(GenContext &ctx) : ctx(ctx) {}
   GenRegAllocator::~GenRegAllocator(void) {}
 
-#define INSERT_REG(SIMD16, SIMD8, SIMD1) \
-  if (ctx.sel->isScalarOrBool(reg) == true) \
-    RA.insert(std::make_pair(reg, GenReg::SIMD1(nr, subnr))); \
-  else if (simdWidth == 8) \
-    RA.insert(std::make_pair(reg, GenReg::SIMD8(nr, subnr))); \
-  else if (simdWidth == 16) \
-    RA.insert(std::make_pair(reg, GenReg::SIMD16(nr, subnr))); \
-  else \
-    NOT_SUPPORTED;
-
   void GenRegAllocator::allocatePayloadReg(gbe_curbe_type value,
                                            ir::Register reg,
                                            uint32_t subValue,
@@ -67,24 +58,10 @@ namespace gbe
   {
     using namespace ir;
     const Kernel *kernel = ctx.getKernel();
-    const Function &fn = ctx.getFunction();
-    const uint32_t simdWidth = ctx.getSimdWidth();
     const int32_t curbeOffset = kernel->getCurbeOffset(value, subValue);
     if (curbeOffset >= 0) {
-      const uint32_t offset = curbeOffset + subOffset;
-      const ir::RegisterData data = fn.getRegisterData(reg);
-      const ir::RegisterFamily family = data.family;
-      const bool isScalar = ctx.sel->isScalarOrBool(reg);
-      const uint32_t typeSize = isScalar ? familyScalarSize[family] : familyVectorSize[family];
-      const uint32_t nr = (offset + GEN_REG_SIZE) / GEN_REG_SIZE;
-      const uint32_t subnr = ((offset + GEN_REG_SIZE) % GEN_REG_SIZE) / typeSize;
-      switch (family) {
-        case FAMILY_BOOL: INSERT_REG(uw1grf, uw1grf, uw1grf); break;
-        case FAMILY_WORD: INSERT_REG(uw16grf, uw8grf, uw1grf); break;
-        case FAMILY_BYTE: INSERT_REG(ub16grf, ub8grf, ub1grf); break;
-        case FAMILY_DWORD: INSERT_REG(f16grf, f8grf, f1grf); break;
-        default: NOT_SUPPORTED;
-      }
+      const uint32_t offset = GEN_REG_SIZE + curbeOffset + subOffset;
+      RA.insert(std::make_pair(reg, offset));
       this->intervals[reg].minID = 0;
     }
   }
@@ -102,25 +79,13 @@ namespace gbe
     const uint32_t regSize = simdWidth*typeSize;
     uint32_t grfOffset;
     while ((grfOffset = ctx.allocate(regSize, regSize)) == 0) {
-      IF_DEBUG(const bool success =) this->expire(interval);
+      IF_DEBUG(const bool success =) this->expireGRF(interval);
       GBE_ASSERTM(success, "Register allocation failed");
     }
-    if (grfOffset != 0) {
-      const uint32_t nr = grfOffset / GEN_REG_SIZE;
-      const uint32_t subnr = (grfOffset % GEN_REG_SIZE) / typeSize;
-      switch (family) {
-        case FAMILY_BOOL: INSERT_REG(uw1grf, uw1grf, uw1grf); break;
-        case FAMILY_WORD: INSERT_REG(uw16grf, uw8grf, uw1grf); break;
-        case FAMILY_BYTE: INSERT_REG(ub16grf, ub8grf, ub1grf); break;
-        case FAMILY_DWORD: INSERT_REG(f16grf, f8grf, f1grf); break;
-        default: NOT_SUPPORTED;
-      }
-    } else
-      GBE_ASSERTM(false, "Unable to register allocate");
+    GBE_ASSERTM(grfOffset != 0, "Unable to register allocate");
+    RA.insert(std::make_pair(reg, grfOffset));
   }
 
-#undef INSERT_REG
-
   bool GenRegAllocator::isAllocated(const SelectionVector *vector) const {
     const ir::Register first = vector->reg[0].reg;
     const auto it = vectorMap.find(first);
@@ -219,19 +184,25 @@ namespace gbe
     return sortStartingPoint ? i0->minID < i1->minID : i0->maxID < i1->maxID;
   }
 
-  bool GenRegAllocator::expire(const GenRegInterval &limit) {
+  bool GenRegAllocator::expireGRF(const GenRegInterval &limit) {
     while (this->expiringID != ending.size()) {
       const GenRegInterval *toExpire = this->ending[this->expiringID];
       const ir::Register reg = toExpire->reg;
-      if (toExpire->minID >= limit.maxID)
+
+      // Ignore booleans that were allocated with flags
+      // if (ctx.getRegisterFamily(reg) == ir::FAMILY_BOOL && !grfBooleans.contains(reg)) {
+      if (ctx.sel->getRegisterFamily(reg) == ir::FAMILY_BOOL) {
+        this->expiringID++;
+        continue;
+      }
+      if (toExpire->maxID >= limit.minID)
         return false;
       auto it = RA.find(reg);
       GBE_ASSERT(it != RA.end());
 
       // Case 1 - it does not belong to a vector. Just remove it
       if (vectorMap.contains(reg) == false) {
-        const uint32_t offset = it->second.nr * GEN_REG_SIZE + it->second.subnr;
-        ctx.deallocate(offset);
+        ctx.deallocate(it->second);
         this->expiringID++;
         return true;
       // Case 2 - check that the vector has not been already removed. If not,
@@ -246,8 +217,7 @@ namespace gbe
           const ir::Register first = vector->reg[0].reg;
           auto it = RA.find(first);
           GBE_ASSERT(it != RA.end());
-          const uint32_t offset = it->second.nr * GEN_REG_SIZE + it->second.subnr;
-          ctx.deallocate(offset);
+          ctx.deallocate(it->second);
           expired.insert(vector);
           this->expiringID++;
           return true;
@@ -259,11 +229,188 @@ namespace gbe
     return false;
   }
 
+  void GenRegAllocator::allocateFlags(Selection &selection) {
+
+    // Store the registers allocated in the map
+    map<ir::Register, uint32_t> allocatedFlags;
+    GenRegInterval spill = ir::Register(ir::RegisterFile::MAX_INDEX);
+
+    // we have two flags we use for booleans f1.0 and f1.1
+    const uint32_t flagNum = 2;
+    uint32_t freeFlags[] = {0,1};
+    uint32_t freeNum = flagNum;
+
+    // Perform the linear scan allocator on the flag registers only. We only use
+    // two flags registers for the booleans right now: f1.0 and f1.1 
+    const uint32_t regNum = ctx.sel->regNum();
+    uint32_t endID = 0; // interval to expire
+    for (uint32_t startID = 0; startID < regNum; ++startID) {
+      const GenRegInterval &interval = *this->starting[startID];
+      const ir::Register reg = interval.reg;
+      if (ctx.sel->getRegisterFamily(reg) != ir::FAMILY_BOOL)
+        continue; // Not a flag. We don't care
+      if (grfBooleans.contains(reg))
+        continue; // Cannot use a flag register
+      if (interval.maxID == -INT_MAX)
+        continue; // Unused register
+      if (freeNum != 0) {
+        spill = interval;
+        allocatedFlags.insert(std::make_pair(reg, freeFlags[--freeNum]));
+      }
+      else {
+        // Try to expire one register
+        while (endID != ending.size()) {
+          const GenRegInterval *toExpire = this->ending[endID];
+          const ir::Register reg = toExpire->reg;
+          // We cannot expire this interval and the next ones
+          if (toExpire->maxID >= interval.minID)
+            break;
+          // Must be a boolean allocated with a flag register
+          if (ctx.sel->getRegisterFamily(reg) != ir::FAMILY_BOOL || grfBooleans.contains(reg)) {
+            endID++;
+            continue;
+          }
+          // We reuse a flag from a previous interval (the oldest one)
+          auto it = allocatedFlags.find(toExpire->reg);
+          GBE_ASSERT(it != allocatedFlags.end());
+          freeFlags[freeNum++] = it->second;
+          break;
+        }
+
+        // We need to spill one of the previous boolean values
+        if (freeNum == 0) {
+          GBE_ASSERT(uint16_t(spill.reg) != ir::RegisterFile::MAX_INDEX);
+          // We spill the last inserted boolean and use its flag instead for
+          // this one
+          if (spill.maxID > interval.maxID) {
+            auto it = allocatedFlags.find(spill.reg);
+            GBE_ASSERT(it != allocatedFlags.end());
+            allocatedFlags.insert(std::make_pair(reg, it->second));
+            allocatedFlags.erase(spill.reg);
+            grfBooleans.insert(spill.reg);
+            spill = interval;
+          }
+          // We will a grf for the current register
+          else
+            grfBooleans.insert(reg);
+        }
+        else
+          allocatedFlags.insert(std::make_pair(reg, freeFlags[--freeNum]));
+      }
+    }
+
+    // Now, we traverse all the selection instructions and we patch them to make
+    // them use flag registers
+    selection.foreachInstruction([&](SelectionInstruction &insn) {
+      const uint32_t srcNum = insn.srcNum, dstNum = insn.dstNum;
+
+      // Patch the source booleans
+      for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
+        const GenRegister selReg = insn.src[srcID];
+        const ir::Register reg = selReg.reg;
+        if (selReg.physical || ctx.sel->getRegisterFamily(reg) != ir::FAMILY_BOOL)
+          continue;
+        auto it = allocatedFlags.find(reg);
+        if (it == allocatedFlags.end())
+          continue;
+        // Use a flag register for it now
+        insn.src[srcID] = GenRegister::flag(1,it->second);
+      }
+
+      // Patch the destination booleans
+      for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
+        const GenRegister selReg = insn.dst[dstID];
+        const ir::Register reg = selReg.reg;
+        if (selReg.physical || ctx.sel->getRegisterFamily(reg) != ir::FAMILY_BOOL)
+          continue;
+        auto it = allocatedFlags.find(reg);
+        if (it == allocatedFlags.end())
+          continue;
+        // Use a flag register for it now
+        insn.dst[dstID] = GenRegister::flag(1,it->second);
+      }
+
+      // Patch the predicate now. Note that only compares actually modify it (it
+      // is called a "conditional modifier"). The other instructions just read
+      // it
+      if (insn.state.physicalFlag == 0) {
+        auto it = allocatedFlags.find(ir::Register(insn.state.flagIndex));
+        // Just patch it if we can use a flag directly
+        if (it != allocatedFlags.end()) {
+          insn.state.flag = 1;
+          insn.state.subFlag = it->second;
+          insn.state.physicalFlag = 1;
+        }
+        // When we let the boolean in a GRF, use f0.1 as a temporary
+        else {
+          // Mov the GRF to the flag such that the flag can be read
+          SelectionInstruction mov;
+          mov.opcode = SEL_OP_MOV;
+          mov.state = GenInstructionState(1);
+          mov.state.predicate = GEN_PREDICATE_NONE;
+          mov.state.noMask = 1;
+          mov.dstNum = mov.srcNum = 1;
+          mov.src[0] = GenRegister::uw1grf(ir::Register(insn.state.flagIndex));
+          mov.dst[0] = GenRegister::flag(0,1);
+          insn.appendBefore(mov);
+
+          // We can use f0.1 (our "backdoor" flag)
+          insn.state.flag = 0;
+          insn.state.subFlag = 1;
+          insn.state.physicalFlag = 1;
+
+          // Compare instructions update the flags so we must copy it back to
+          // the GRF
+          if (insn.opcode == SEL_OP_CMP) {
+            std::swap(mov.src[0], mov.dst[0]);
+            insn.appendAfter(mov);
+          }
+        }
+      }
+    });
+  }
+
+  void GenRegAllocator::allocateGRFs(Selection &selection) {
+
+    // Perform the linear scan allocator
+    const uint32_t regNum = ctx.sel->regNum();
+    for (uint32_t startID = 0; startID < regNum; ++startID) {
+      const GenRegInterval &interval = *this->starting[startID];
+      const ir::Register reg = interval.reg;
+      if (interval.maxID == -INT_MAX)
+        continue; // Unused register
+      if (RA.contains(reg))
+        continue; // already allocated
+
+      // Case 1: the register belongs to a vector, allocate all the registers in
+      // one piece
+      auto it = vectorMap.find(reg);
+      if (it != vectorMap.end()) {
+        const SelectionVector *vector = it->second.first;
+        const uint32_t simdWidth = ctx.getSimdWidth();
+        const uint32_t alignment = simdWidth * sizeof(uint32_t);
+        const uint32_t size = vector->regNum * alignment;
+        uint32_t grfOffset;
+        while ((grfOffset = ctx.allocate(size, alignment)) == 0) {
+          IF_DEBUG(const bool success =) this->expireGRF(interval);
+          GBE_ASSERTM(success, "Register allocation failed");
+        }
+        for (uint32_t regID = 0; regID < vector->regNum; ++regID, grfOffset += alignment) {
+          const ir::Register reg = vector->reg[regID].reg;
+          GBE_ASSERT(RA.contains(reg) == false);
+          RA.insert(std::make_pair(reg, grfOffset));
+        }
+      }
+      // Case 2: This is a regular scalar register, allocate it alone
+      else
+        this->createGenReg(interval);
+    }
+  }
+
   void GenRegAllocator::allocate(Selection &selection) {
     using namespace ir;
     const Kernel *kernel = ctx.getKernel();
     const Function &fn = ctx.getFunction();
-    const uint32_t simdWidth = ctx.getSimdWidth();
     GBE_ASSERT(fn.getProfile() == PROFILE_OCL);
 
     // Allocate all the vectors first since they need to be contiguous
@@ -292,20 +439,14 @@ namespace gbe
     allocatePayloadReg(GBE_CURBE_STACK_POINTER, ocl::stackptr);
 
     // Group IDs are always allocated by the hardware in r0
-    RA.insert(std::make_pair(ocl::groupid0, GenReg::f1grf(0, 1)));
-    RA.insert(std::make_pair(ocl::groupid1, GenReg::f1grf(0, 6)));
-    RA.insert(std::make_pair(ocl::groupid2, GenReg::f1grf(0, 7)));
+    RA.insert(std::make_pair(ocl::groupid0, 1*sizeof(float))); // r0.1
+    RA.insert(std::make_pair(ocl::groupid1, 6*sizeof(float))); // r0.6
+    RA.insert(std::make_pair(ocl::groupid2, 7*sizeof(float))); // r0.7
 
     // block IP used to handle the mask in SW is always allocated
-    int32_t blockIPOffset = GEN_REG_SIZE + kernel->getCurbeOffset(GBE_CURBE_BLOCK_IP,0);
+    const int32_t blockIPOffset = GEN_REG_SIZE + kernel->getCurbeOffset(GBE_CURBE_BLOCK_IP,0);
     GBE_ASSERT(blockIPOffset >= 0 && blockIPOffset % GEN_REG_SIZE == 0);
-    blockIPOffset /= GEN_REG_SIZE;
-    if (simdWidth == 8)
-      RA.insert(std::make_pair(ocl::blockip, GenReg::uw8grf(blockIPOffset, 0)));
-    else if (simdWidth == 16)
-      RA.insert(std::make_pair(ocl::blockip, GenReg::uw16grf(blockIPOffset, 0)));
-    else
-      NOT_SUPPORTED;
+    RA.insert(std::make_pair(ocl::blockip, blockIPOffset));
     this->intervals[ocl::blockip].minID = 0;
 
     // Allocate all (non-structure) argument parameters
@@ -337,7 +478,7 @@ namespace gbe
       block.foreach([&](const SelectionInstruction &insn) {
         const uint32_t srcNum = insn.srcNum, dstNum = insn.dstNum;
         for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
-          const SelectionReg &selReg = insn.src[srcID];
+          const GenRegister &selReg = insn.src[srcID];
           const ir::Register reg = selReg.reg;
           if (selReg.file != GEN_GENERAL_REGISTER_FILE ||
               reg == ir::ocl::groupid0 ||
@@ -348,7 +489,7 @@ namespace gbe
           this->intervals[reg].maxID = max(this->intervals[reg].maxID, insnID);
         }
         for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
-          const SelectionReg &selReg = insn.dst[dstID];
+          const GenRegister &selReg = insn.dst[dstID];
           const ir::Register reg = selReg.reg;
           if (selReg.file != GEN_GENERAL_REGISTER_FILE ||
               reg == ir::ocl::groupid0 ||
@@ -358,6 +499,21 @@ namespace gbe
           this->intervals[reg].minID = min(this->intervals[reg].minID, insnID);
           this->intervals[reg].maxID = max(this->intervals[reg].maxID, insnID);
         }
+
+        // Flag registers can only go to src[0]
+        const SelectionOpcode opcode = SelectionOpcode(insn.opcode);
+        if (opcode == SEL_OP_AND || opcode == SEL_OP_OR) {
+          const ir::Register reg = insn.src[1].reg;
+          if (ctx.sel->getRegisterFamily(reg) == ir::FAMILY_BOOL)
+            grfBooleans.insert(reg);
+        }
+
+        // OK, a flag is used as a predicate or a conditional modifier
+        if (insn.state.physicalFlag == 0) {
+          const ir::Register reg = ir::Register(insn.state.flagIndex);
+          this->intervals[reg].minID = min(this->intervals[reg].minID, insnID);
+          this->intervals[reg].maxID = max(this->intervals[reg].maxID, insnID);
+        }
         lastID = insnID;
         insnID++;
       });
@@ -394,7 +550,7 @@ namespace gbe
     }
 
     // Sort both intervals in starting point and ending point increasing orders
-    uint32_t regNum = ctx.sel->regNum();
+    const uint32_t regNum = ctx.sel->regNum();
     this->starting.resize(regNum);
     this->ending.resize(regNum);
     for (uint32_t regID = 0; regID < regNum; ++regID)
@@ -412,78 +568,37 @@ namespace gbe
         break;
     }
 
-    // Perform the linear scan allocator
-    for (uint32_t startID = 0; startID < regNum; ++startID) {
-      const GenRegInterval &interval = *this->starting[startID];
-      const ir::Register reg = interval.reg;
-      if (interval.maxID == -INT_MAX)
-        continue; // Unused register
-      if (RA.contains(reg))
-        continue; // already allocated
+    // First we try to put all booleans registers into flags
+    this->allocateFlags(selection);
 
-      // Case 1: the register belongs to a vector, allocate all the registers in
-      // one piece
-      auto it = vectorMap.find(reg);
-      if (it != vectorMap.end()) {
-        const SelectionVector *vector = it->second.first;
-        const uint32_t simdWidth = ctx.getSimdWidth();
-        const uint32_t alignment = simdWidth * sizeof(uint32_t);
-        const uint32_t size = vector->regNum * alignment;
-        uint32_t grfOffset;
-        while ((grfOffset = ctx.allocate(size, alignment)) == 0) {
-          IF_DEBUG(const bool success =) this->expire(interval);
-          GBE_ASSERTM(success, "Register allocation failed");
-        }
-        //GBE_ASSERTM(grfOffset != 0, "Unable to register allocate");
-        for (uint32_t regID = 0; regID < vector->regNum; ++regID, grfOffset += alignment) {
-          const ir::Register reg = vector->reg[regID].reg;
-          const uint32_t nr = grfOffset / GEN_REG_SIZE;
-          const uint32_t subnr = (grfOffset % GEN_REG_SIZE) / sizeof(uint32_t);
-          GBE_ASSERT(RA.contains(reg) == false);
-          if (simdWidth == 16)
-            RA.insert(std::make_pair(reg, GenReg::f16grf(nr, subnr)));
-          else if (simdWidth == 8)
-            RA.insert(std::make_pair(reg, GenReg::f8grf(nr, subnr)));
-          else
-            NOT_SUPPORTED;
-        }
-      }
-      // Case 2: This is a regular scalar register, allocate it alone
-      else
-        this->createGenReg(interval);
-    }
+    // Allocate all the GRFs now (regular register and boolean that are not in
+    // flag registers)
+    this->allocateGRFs(selection);
   }
 
-  INLINE void setGenReg(GenReg &dst, const SelectionReg &src) {
-    dst.type = src.type;
-    dst.file = src.file;
-    dst.negation = src.negation;
-    dst.absolute = src.absolute;
-    dst.vstride = src.vstride;
-    dst.width = src.width;
-    dst.hstride = src.hstride;
-    dst.address_mode = GEN_ADDRESS_DIRECT;
-    dst.dw1.ud = src.immediate.ud;
+  INLINE GenRegister setGenReg(const GenRegister &src, uint32_t grfOffset) {
+    GenRegister dst;
+    dst = src;
+    dst.physical = 1;
+    dst.nr = grfOffset / GEN_REG_SIZE;
+    dst.subnr = grfOffset % GEN_REG_SIZE;
+    return dst;
   }
 
-  GenReg GenRegAllocator::genReg(const SelectionReg &reg) {
+  GenRegister GenRegAllocator::genReg(const GenRegister &reg) {
     // Right now, only GRF are allocated (TODO bool) ...
     if (reg.file == GEN_GENERAL_REGISTER_FILE) {
       GBE_ASSERT(RA.contains(reg.reg) != false);
-      GenReg dst = RA.find(reg.reg)->second;
-      setGenReg(dst, reg);
+      const uint32_t grfOffset = RA.find(reg.reg)->second;
+      const GenRegister dst = setGenReg(reg, grfOffset);
       if (reg.quarter != 0)
-        dst = GenReg::Qn(dst, reg.quarter);
-      return dst;
+        return GenRegister::Qn(dst, reg.quarter);
+      else
+        return dst;
     }
     // Other registers are already physical registers
-    else {
-      GenReg dst;
-      setGenReg(dst, reg);
-      dst.nr = reg.nr;
-      dst.subnr = reg.subnr;
-      return dst;
-    }
+    else
+      return reg;
   }
 
 } /* namespace gbe */
index 3c29cfb..7d3a225 100644 (file)
 
 #include "ir/register.hpp"
 #include "backend/gen_context.hpp"
+#include "backend/gen_register.hpp"
 #include "backend/program.h"
 
 namespace gbe
 {
   class Selection;      // Pre-register allocation code generation
-  class SelectionReg;   // Pre-register allocation Gen register
+  class GenRegister;   // Pre-register allocation Gen register
   class GenRegInterval; // Liveness interval for each register
 
   /*! Provides the location of a register in a vector */
@@ -52,14 +53,18 @@ namespace gbe
     /*! Perform the register allocation */
     void allocate(Selection &selection);
     /*! Return the Gen register from the selection register */
-    GenReg genReg(const SelectionReg &reg);
+    GenRegister genReg(const GenRegister &reg);
     /*! Return the Gen register from the GenIR one */
-    GenReg genReg(ir::Register, ir::Type type = ir::TYPE_FLOAT);
+    GenRegister genReg(ir::Register, ir::Type type = ir::TYPE_FLOAT);
   private:
-    /*! Expire one interval upto interval limit. Return true if one interval was
-     *  successfully expired
-     */
-    bool expire(const GenRegInterval &limit);
+    /*! Expire one GRF interval. Return true if one was successfully expired */
+    bool expireGRF(const GenRegInterval &limit);
+    /*! Expire a flag register. Return true if one was successfully expired */
+    bool expireFlag(const GenRegInterval &limit);
+    /*! Allocate the virtual boolean (== flags) registers */
+    void allocateFlags(Selection &selection);
+    /*! Allocate the GRF registers */
+    void allocateGRFs(Selection &selection);
     /*! Create a Gen register from a register set in the payload */
     void allocatePayloadReg(gbe_curbe_type, ir::Register, uint32_t subValue = 0, uint32_t subOffset = 0);
     /*! Create the intervals for each register */
@@ -75,14 +80,16 @@ namespace gbe
     void coalesce(Selection &selection, SelectionVector *vector);
     /*! The context owns the register allocator */
     GenContext &ctx;
-    /*! Map virtual registers to physical registers */
-    map<ir::Register, GenReg> RA;
+    /*! Map virtual registers to offset in the (physical) register file */
+    map<ir::Register, uint32_t> RA;
     /*! Provides the position of each register in a vector */
     map<ir::Register, VectorLocation> vectorMap;
     /*! All vectors used in the selection */
     vector<SelectionVector*> vectors;
     /*! All vectors that are already expired */
     set<SelectionVector*> expired;
+    /*! The set of booleans that will go to GRF (cannot be kept into flags) */
+    set<ir::Register> grfBooleans;
     /*! All the register intervals */
     vector<GenRegInterval> intervals;
     /*! Intervals sorting based on starting point positions */
diff --git a/backend/src/backend/gen_register.hpp b/backend/src/backend/gen_register.hpp
new file mode 100644 (file)
index 0000000..47629e8
--- /dev/null
@@ -0,0 +1,737 @@
+/*
+ * Copyright 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file gen_reg.hpp
+ * \author Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __GEN_REGISTER_HPP__
+#define __GEN_REGISTER_HPP__
+
+#include "backend/gen_defs.hpp"
+#include "ir/register.hpp"
+#include "sys/platform.hpp"
+
+namespace gbe
+{
+
+  /*! Type size in bytes for each Gen type */
+  INLINE int typeSize(uint32_t type) {
+    switch(type) {
+      case GEN_TYPE_UD:
+      case GEN_TYPE_D:
+      case GEN_TYPE_F:
+        return 4;
+      case GEN_TYPE_HF:
+      case GEN_TYPE_UW:
+      case GEN_TYPE_W:
+        return 2;
+      case GEN_TYPE_UB:
+      case GEN_TYPE_B:
+        return 1;
+      default:
+        assert(0);
+        return 0;
+    }
+  }
+
+  /*! Convert a hstride to a number of element */
+  INLINE uint32_t stride(uint32_t stride) {
+    switch (stride) {
+      case 0: return 0;
+      case 1: return 1;
+      case 2: return 2;
+      case 3: return 4;
+      case 4: return 8;
+      case 5: return 16;
+      default: assert(0); return 0;
+    }
+  }
+
+  /*! Encode the instruction state. Note that the flag register can be either
+   *  physical (i.e. a real Gen flag) or a virtual boolean register. The flag
+   *  register allocation will turn all virtual boolean registers into flag
+   *  registers
+   */
+  class GenInstructionState
+  {
+  public:
+    INLINE GenInstructionState(uint32_t simdWidth = 8) {
+      this->execWidth = simdWidth;
+      this->quarterControl = GEN_COMPRESSION_Q1;
+      this->noMask = 0;
+      this->flag = 0;
+      this->subFlag = 0;
+      this->predicate = GEN_PREDICATE_NORMAL;
+      this->inversePredicate = 0;
+      this->physicalFlag = 1;
+      this->flagIndex = 0;
+    }
+    uint32_t physicalFlag:1; //!< Physical or virtual flag register
+    uint32_t flag:1;         //!< Only if physical flag
+    uint32_t subFlag:1;      //!< Only if physical flag
+    uint32_t flagIndex:16;   //!< Only if virtual flag (index of the register)
+    uint32_t execWidth:5;
+    uint32_t quarterControl:2;
+    uint32_t noMask:1;
+    uint32_t predicate:4;
+    uint32_t inversePredicate:1;
+  };
+
+  static_assert(sizeof(GenInstructionState) == sizeof(uint32_t), "Invalid state size");
+
+  /*! This is a book-keeping structure used to encode both virtual and physical
+   *  registers
+   */
+  class GenRegister
+  {
+  public:
+    /*! Empty constructor */
+    INLINE GenRegister(void) {}
+
+    /*! General constructor */
+    INLINE GenRegister(uint32_t file,
+                       ir::Register reg,
+                       uint32_t type,
+                       uint32_t vstride,
+                       uint32_t width,
+                       uint32_t hstride)
+    {
+      this->type = type;
+      this->file = file;
+      this->physical = 0;
+      this->reg = reg;
+      this->negation = 0;
+      this->absolute = 0;
+      this->vstride = vstride;
+      this->width = width;
+      this->hstride = hstride;
+      this->quarter = 0;
+      this->nr = this->subnr = 0;
+      this->address_mode = GEN_ADDRESS_DIRECT;
+    }
+
+    /*! For specific physical registers only */
+    INLINE GenRegister(uint32_t file,
+                       uint32_t nr,
+                       uint32_t subnr,
+                       uint32_t type,
+                       uint32_t vstride,
+                       uint32_t width,
+                       uint32_t hstride)
+    {
+      this->type = type;
+      this->file = file;
+      this->nr = nr;
+      this->physical = 1;
+      this->subnr = subnr * typeSize(type);
+      this->negation = 0;
+      this->absolute = 0;
+      this->vstride = vstride;
+      this->width = width;
+      this->hstride = hstride;
+      this->quarter = 0;
+      this->address_mode = GEN_ADDRESS_DIRECT;
+    }
+
+    /*! Associated virtual register */
+    ir::Register reg;
+
+    /*! For immediates */
+    union {
+      float f;
+      int32_t d;
+      uint32_t ud;
+    } immediate;
+
+    uint32_t nr:7;         //!< Just for some physical registers (acc, null)
+    uint32_t subnr:5;      //!< Idem
+    uint32_t physical:1;   //!< 1 if physical, 0 otherwise
+    uint32_t type:4;       //!< Gen type
+    uint32_t file:2;       //!< Register file
+    uint32_t negation:1;   //!< For source
+    uint32_t absolute:1;   //!< For source
+    uint32_t vstride:4;    //!< Vertical stride
+    uint32_t width:3;      //!< Width
+    uint32_t hstride:2;    //!< Horizontal stride
+    uint32_t quarter:1;    //!< To choose which part we want (Q1 / Q2)
+    uint32_t address_mode; //!< direct or indirec2t
+
+    static INLINE GenRegister QnVirtual(GenRegister reg, uint32_t quarter) {
+      GBE_ASSERT(reg.physical == 0);
+      if (reg.hstride == GEN_HORIZONTAL_STRIDE_0) // scalar register
+        return reg;
+      else {
+        reg.quarter = quarter;
+        return reg;
+      }
+    }
+
+    static INLINE GenRegister QnPhysical(GenRegister reg, uint32_t quarter) {
+      GBE_ASSERT(reg.physical);
+      if (reg.hstride == GEN_HORIZONTAL_STRIDE_0) // scalar register
+        return reg;
+      else {
+        const uint32_t typeSz = typeSize(reg.type);
+        const uint32_t horizontal = stride(reg.hstride);
+        const uint32_t grfOffset = reg.nr*GEN_REG_SIZE + reg.subnr;
+        const uint32_t nextOffset = grfOffset + 8*quarter*horizontal*typeSz;
+        reg.nr = nextOffset / GEN_REG_SIZE;
+        reg.subnr = (nextOffset % GEN_REG_SIZE);
+        return reg;
+      }
+    }
+
+    static INLINE GenRegister Qn(GenRegister reg, uint32_t quarter) {
+      if (reg.physical)
+        return QnPhysical(reg, quarter);
+      else
+        return QnVirtual(reg, quarter);
+    }
+
+    static INLINE GenRegister vec16(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec8(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec4(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_4,
+                         GEN_WIDTH_4,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec2(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_2,
+                         GEN_WIDTH_2,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec1(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_0,
+                         GEN_WIDTH_1,
+                         GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister retype(GenRegister reg, uint32_t type) {
+      reg.type = type;
+      return reg;
+    }
+
+    static INLINE GenRegister ud16(uint32_t file, ir::Register reg) {
+      return retype(vec16(file, reg), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister ud8(uint32_t file, ir::Register reg) {
+      return retype(vec8(file, reg), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister ud1(uint32_t file, ir::Register reg) {
+      return retype(vec1(file, reg), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister d8(uint32_t file, ir::Register reg) {
+      return retype(vec8(file, reg), GEN_TYPE_D);
+    }
+
+    static INLINE GenRegister uw16(uint32_t file, ir::Register reg) {
+      return retype(vec16(file, reg), GEN_TYPE_UW);
+    }
+
+    static INLINE GenRegister uw8(uint32_t file, ir::Register reg) {
+      return retype(vec8(file, reg), GEN_TYPE_UW);
+    }
+
+    static INLINE GenRegister uw1(uint32_t file, ir::Register reg) {
+      return retype(vec1(file, reg), GEN_TYPE_UW);
+    }
+
+    static INLINE GenRegister ub16(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_UB,
+                         GEN_VERTICAL_STRIDE_16,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_2);
+    }
+
+    static INLINE GenRegister ub8(uint32_t file, ir::Register reg) {
+      return GenRegister(file,
+                         reg,
+                         GEN_TYPE_UB,
+                         GEN_VERTICAL_STRIDE_16,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_2);
+    }
+
+    static INLINE GenRegister ub1(uint32_t file, ir::Register reg) {
+      return retype(vec1(file, reg), GEN_TYPE_UB);
+    }
+
+    static INLINE GenRegister unpacked_uw(ir::Register reg) {
+        return GenRegister(GEN_GENERAL_REGISTER_FILE,
+                           reg,
+                           GEN_TYPE_UW,
+                           GEN_VERTICAL_STRIDE_16,
+                           GEN_WIDTH_8,
+                           GEN_HORIZONTAL_STRIDE_2);
+    }
+
+    static INLINE GenRegister unpacked_ub(ir::Register reg) {
+      return GenRegister(GEN_GENERAL_REGISTER_FILE,
+                         reg,
+                         GEN_TYPE_UB,
+                         GEN_VERTICAL_STRIDE_32,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_4);
+    }
+
+    static INLINE GenRegister imm(uint32_t type) {
+      return GenRegister(GEN_IMMEDIATE_VALUE,
+                         0,
+                         0,
+                         type,
+                         GEN_VERTICAL_STRIDE_0,
+                         GEN_WIDTH_1,
+                         GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister immf(float f) {
+      GenRegister immediate = imm(GEN_TYPE_F);
+      immediate.immediate.f = f;
+      return immediate;
+    }
+
+    static INLINE GenRegister immd(int d) {
+      GenRegister immediate = imm(GEN_TYPE_D);
+      immediate.immediate.d = d;
+      return immediate;
+    }
+
+    static INLINE GenRegister immud(uint32_t ud) {
+      GenRegister immediate = imm(GEN_TYPE_UD);
+      immediate.immediate.ud = ud;
+      return immediate;
+    }
+
+    static INLINE GenRegister immuw(uint16_t uw) {
+      GenRegister immediate = imm(GEN_TYPE_UW);
+      immediate.immediate.ud = uw | (uw << 16);
+      return immediate;
+    }
+
+    static INLINE GenRegister immw(int16_t w) {
+      GenRegister immediate = imm(GEN_TYPE_W);
+      immediate.immediate.d = w | (w << 16);
+      return immediate;
+    }
+
+    static INLINE GenRegister immv(uint32_t v) {
+      GenRegister immediate = imm(GEN_TYPE_V);
+      immediate.vstride = GEN_VERTICAL_STRIDE_0;
+      immediate.width = GEN_WIDTH_8;
+      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
+      immediate.immediate.ud = v;
+      return immediate;
+    }
+
+    static INLINE GenRegister immvf(uint32_t v) {
+      GenRegister immediate = imm(GEN_TYPE_VF);
+      immediate.vstride = GEN_VERTICAL_STRIDE_0;
+      immediate.width = GEN_WIDTH_4;
+      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
+      immediate.immediate.ud = v;
+      return immediate;
+    }
+
+    static INLINE GenRegister immvf4(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
+      GenRegister immediate = imm(GEN_TYPE_VF);
+      immediate.vstride = GEN_VERTICAL_STRIDE_0;
+      immediate.width = GEN_WIDTH_4;
+      immediate.hstride = GEN_HORIZONTAL_STRIDE_1;
+      immediate.immediate.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
+      return immediate;
+    }
+
+    static INLINE GenRegister f1grf(ir::Register reg) {
+      return vec1(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister f2grf(ir::Register reg) {
+      return vec2(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister f4grf(ir::Register reg) {
+      return vec4(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister f8grf(ir::Register reg) {
+      return vec8(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister f16grf(ir::Register reg) {
+      return vec16(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ud16grf(ir::Register reg) {
+      return ud16(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ud8grf(ir::Register reg) {
+      return ud8(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ud1grf(ir::Register reg) {
+      return ud1(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister uw1grf(ir::Register reg) {
+      return uw1(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister uw8grf(ir::Register reg) {
+      return uw8(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister uw16grf(ir::Register reg) {
+      return uw16(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ub1grf(ir::Register reg) {
+      return ub1(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ub8grf(ir::Register reg) {
+      return ub8(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister ub16grf(ir::Register reg) {
+      return ub16(GEN_GENERAL_REGISTER_FILE, reg);
+    }
+
+    static INLINE GenRegister null(void) {
+      return GenRegister(GEN_ARCHITECTURE_REGISTER_FILE,
+                         GEN_ARF_NULL,
+                         0,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister acc(void) {
+      return GenRegister(GEN_ARCHITECTURE_REGISTER_FILE,
+                         GEN_ARF_ACCUMULATOR,
+                         0,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister ip(void) {
+      return GenRegister(GEN_ARCHITECTURE_REGISTER_FILE,
+                         GEN_ARF_IP,
+                         0,
+                         GEN_TYPE_D,
+                         GEN_VERTICAL_STRIDE_4,
+                         GEN_WIDTH_1,
+                         GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister notification1(void) {
+      return GenRegister(GEN_ARCHITECTURE_REGISTER_FILE,
+                         GEN_ARF_NOTIFICATION_COUNT,
+                         1,
+                         GEN_TYPE_UD,
+                         GEN_VERTICAL_STRIDE_0,
+                         GEN_WIDTH_1,
+                         GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister flag(uint32_t nr, uint32_t subnr) {
+      return GenRegister(GEN_ARCHITECTURE_REGISTER_FILE,
+                         GEN_ARF_FLAG | nr,
+                         subnr,
+                         GEN_TYPE_UW,
+                         GEN_VERTICAL_STRIDE_0,
+                         GEN_WIDTH_1,
+                         GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister next(GenRegister reg) {
+      if (reg.physical)
+        reg.nr++;
+      else
+        reg.quarter++;
+      return reg;
+    }
+
+    /*! Build an indirectly addressed source */
+    static INLINE GenRegister indirect(uint32_t type, uint32_t subnr, uint32_t width) {
+      GenRegister reg;
+      reg.type = type;
+      reg.file = GEN_GENERAL_REGISTER_FILE;
+      reg.address_mode = GEN_ADDRESS_REGISTER_INDIRECT_REGISTER;
+      reg.width = width;
+      reg.subnr = subnr;
+      reg.nr = 0;
+      reg.negation = 0;
+      reg.absolute = 0;
+      reg.vstride = 0;
+      reg.hstride = 0;
+      return reg;
+    }
+
+    static INLINE GenRegister vec16(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                         nr,
+                         subnr,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec8(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                         nr,
+                         subnr,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_8,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec4(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                         nr,
+                         subnr,
+                         GEN_TYPE_F,
+                         GEN_VERTICAL_STRIDE_4,
+                         GEN_WIDTH_4,
+                         GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec2(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                    nr,
+                    subnr,
+                    GEN_TYPE_F,
+                    GEN_VERTICAL_STRIDE_2,
+                    GEN_WIDTH_2,
+                    GEN_HORIZONTAL_STRIDE_1);
+    }
+
+    static INLINE GenRegister vec1(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                    nr,
+                    subnr,
+                    GEN_TYPE_F,
+                    GEN_VERTICAL_STRIDE_0,
+                    GEN_WIDTH_1,
+                    GEN_HORIZONTAL_STRIDE_0);
+    }
+
+    static INLINE GenRegister suboffset(GenRegister reg, uint32_t delta) {
+      reg.subnr += delta * typeSize(reg.type);
+      return reg;
+    }
+
+    static INLINE GenRegister ud16(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return retype(vec16(file, nr, subnr), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister ud8(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return retype(vec8(file, nr, subnr), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister ud1(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return retype(vec1(file, nr, subnr), GEN_TYPE_UD);
+    }
+
+    static INLINE GenRegister d8(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return retype(vec8(file, nr, subnr), GEN_TYPE_D);
+    }
+
+    static INLINE GenRegister uw16(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return suboffset(retype(vec16(file, nr, 0), GEN_TYPE_UW), subnr);
+    }
+
+    static INLINE GenRegister uw8(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return suboffset(retype(vec8(file, nr, 0), GEN_TYPE_UW), subnr);
+    }
+
+    static INLINE GenRegister uw1(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UW), subnr);
+    }
+
+    static INLINE GenRegister ub16(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                         nr,
+                         subnr,
+                         GEN_TYPE_UB,
+                         GEN_VERTICAL_STRIDE_16,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_2);
+    }
+
+    static INLINE GenRegister ub8(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return GenRegister(file,
+                         nr,
+                         subnr,
+                         GEN_TYPE_UB,
+                         GEN_VERTICAL_STRIDE_16,
+                         GEN_WIDTH_8,
+                         GEN_HORIZONTAL_STRIDE_2);
+    }
+
+    static INLINE GenRegister ub1(uint32_t file, uint32_t nr, uint32_t subnr) {
+      return suboffset(retype(vec1(file, nr, 0), GEN_TYPE_UB), subnr);
+    }
+
+    static INLINE GenRegister f1grf(uint32_t nr, uint32_t subnr) {
+      return vec1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister f2grf(uint32_t nr, uint32_t subnr) {
+      return vec2(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister f4grf(uint32_t nr, uint32_t subnr) {
+      return vec4(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister f8grf(uint32_t nr, uint32_t subnr) {
+      return vec8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister f16grf(uint32_t nr, uint32_t subnr) {
+      return vec16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ud16grf(uint32_t nr, uint32_t subnr) {
+      return ud16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ud8grf(uint32_t nr, uint32_t subnr) {
+      return ud8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ud1grf(uint32_t nr, uint32_t subnr) {
+      return ud1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister uw1grf(uint32_t nr, uint32_t subnr) {
+      return uw1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister uw8grf(uint32_t nr, uint32_t subnr) {
+      return uw8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister uw16grf(uint32_t nr, uint32_t subnr) {
+      return uw16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ub1grf(uint32_t nr, uint32_t subnr) {
+      return ub1(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ub8grf(uint32_t nr, uint32_t subnr) {
+      return ub8(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister ub16grf(uint32_t nr, uint32_t subnr) {
+      return ub16(GEN_GENERAL_REGISTER_FILE, nr, subnr);
+    }
+
+    static INLINE GenRegister mask(uint32_t subnr) {
+      return uw1(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_MASK, subnr);
+    }
+
+    static INLINE GenRegister addr1(uint32_t subnr) {
+      return uw1(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_ADDRESS, subnr);
+    }
+
+    static INLINE GenRegister addr8(uint32_t subnr) {
+      return uw8(GEN_ARCHITECTURE_REGISTER_FILE, GEN_ARF_ADDRESS, subnr);
+    }
+
+    static INLINE GenRegister negate(GenRegister reg) {
+      reg.negation ^= 1;
+      return reg;
+    }
+
+    static INLINE GenRegister abs(GenRegister reg) {
+      reg.absolute = 1;
+      reg.negation = 0;
+      return reg;
+    }
+
+    /*! Generate register encoding with run-time simdWidth */
+#define DECL_REG_ENCODER(NAME, SIMD16, SIMD8, SIMD1) \
+    template <typename... Args> \
+    static INLINE GenRegister NAME(uint32_t simdWidth, Args... values) { \
+      if (simdWidth == 16) \
+        return SIMD16(values...); \
+      else if (simdWidth == 8) \
+        return SIMD8(values...); \
+      else if (simdWidth == 1) \
+        return SIMD1(values...); \
+      else { \
+        NOT_IMPLEMENTED; \
+        return SIMD1(values...); \
+      } \
+    }
+    DECL_REG_ENCODER(fxgrf, f16grf, f8grf, f1grf);
+    DECL_REG_ENCODER(uwxgrf, uw16grf, uw8grf, uw1grf);
+    DECL_REG_ENCODER(udxgrf, ud16grf, ud8grf, ud1grf);
+#undef DECL_REG_ENCODER
+  };
+} /* namespace gbe */
+
+#endif /* __GEN_REGISTER_HPP__ */
+