Finished first implementation of the boiler plate code to separate instruction select...
authorBenjamin Segovia <devnull@localhost>
Tue, 5 Jun 2012 00:07:51 +0000 (00:07 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:18:06 +0000 (16:18 -0700)
backend/src/backend/gen_context.cpp
backend/src/backend/gen_context.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

index 4afcd0a..982c89d 100644 (file)
@@ -592,7 +592,10 @@ namespace gbe
     }
   }
 
-  void GenContext::emitFenceInstruction(const ir::FenceInstruction &insn) {}
+  void GenContext::emitFenceInstruction(const ir::FenceInstruction &insn) {
+    NOT_IMPLEMENTED;
+  }
+
   void GenContext::emitLabelInstruction(const ir::LabelInstruction &insn) {
     using namespace ir;
     const LabelIndex label = insn.getLabelIndex();
@@ -691,6 +694,19 @@ namespace gbe
     });
   }
 
+  void GenContext::emitInstructionStream2(void) {
+    // Emit Gen ISA
+    sel->foreachInstruction([&](const SelectionInstruction &insn) {
+      const uint32_t opcode = insn.opcode;
+      switch (opcode) {
+#define DECL_SELECTION_IR(OPCODE, FAMILY) \
+  case SEL_OP_##OPCODE: this->emit##FAMILY(insn); break;
+#include "backend/gen_insn_selection.hxx"
+#undef DECL_INSN
+      }
+    });
+  }
+
   void GenContext::patchBranches(void) {
     using namespace ir;
     for (auto pair : branchPos) {
@@ -702,28 +718,156 @@ namespace gbe
     }
   }
 
+  void GenContext::patchBranches2(void) {
+    using namespace ir;
+    for (auto pair : branchPos2) {
+      const LabelIndex label = pair.first;
+      const int32_t insnID = pair.second;
+      const int32_t targetID = labelPos.find(label)->second;
+      p->patchJMPI(insnID, (targetID-insnID-1) * 2);
+    }
+  }
+
   ///////////////////// XXX ///////////////////////
   void GenContext::emitLabelInstruction(const SelectionInstruction &insn) {
     const ir::LabelIndex label(insn.index);
     this->labelPos.insert(std::make_pair(label, p->insnNum));
   }
 
+  /*! 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::emitUnaryInstruction(const SelectionInstruction &insn) {
+    const GenReg dst = ra->genReg(insn.dst[0]);
+    const GenReg src = ra->genReg(insn.src[0]);
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    switch (insn.opcode) {
+      case SEL_OP_MOV: p->MOV(dst, src); break;
+      default: NOT_IMPLEMENTED;
+    }
+    p->pop();
+  }
+
+  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]);
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    switch (insn.opcode) {
+      case SEL_OP_AND:  p->AND(dst, src0, src1); break;
+      case SEL_OP_OR:   p->OR(dst, src0, src1);  break;
+      case SEL_OP_XOR:  p->XOR(dst, src0, src1); break;
+      case SEL_OP_SHR:  p->SHR(dst, src0, src1); break;
+      case SEL_OP_SHL:  p->SHL(dst, src0, src1); break;
+      case SEL_OP_RSR:  p->RSR(dst, src0, src1); break;
+      case SEL_OP_RSL:  p->RSL(dst, src0, src1); break;
+      case SEL_OP_ASR:  p->ASR(dst, src0, src1); break;
+      case SEL_OP_ADD:  p->ADD(dst, src0, src1); break;
+      case SEL_OP_MUL:  p->MUL(dst, src0, src1); break;
+      case SEL_OP_MACH: p->MACH(dst, src0, src1); break;
+      default: NOT_IMPLEMENTED;
+    }
+    p->pop();
+  }
 
+  void GenContext::emitSelectInstruction(const SelectionInstruction &insn) {
+    NOT_IMPLEMENTED;
   }
 
-  void GenContext::emitBinaryInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitSelectInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitCompareInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitJumpInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitEotInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitNoOpInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitWaitInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitMathInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitUntypedReadInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitUntypedWriteInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitByteGatherInstruction(const SelectionInstruction &insn){}
-  void GenContext::emitByteScatterInstruction(const SelectionInstruction &insn){}
+  void GenContext::emitNoOpInstruction(const SelectionInstruction &insn) {
+    NOT_IMPLEMENTED;
+  }
+
+  void GenContext::emitWaitInstruction(const SelectionInstruction &insn) {
+    NOT_IMPLEMENTED;
+  }
+
+  void GenContext::emitMathInstruction(const SelectionInstruction &insn) {
+    NOT_IMPLEMENTED;
+  }
+
+  void GenContext::emitCompareInstruction(const SelectionInstruction &insn) {
+    const GenReg src0 = ra->genReg(insn.src[0]);
+    const GenReg src1 = ra->genReg(insn.src[1]);
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->CMP(insn.function, src0, src1);
+    p->pop();
+  }
+
+  void GenContext::emitJumpInstruction(const SelectionInstruction &insn) {
+    const ir::LabelIndex label(insn.index);
+    const GenReg src = ra->genReg(insn.src[0]);
+    this->branchPos2.push_back(std::make_pair(label, p->insnNum));
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->JMPI(src);
+    p->pop();
+  }
+
+  void GenContext::emitEotInstruction(const SelectionInstruction &insn) {
+    p->push();
+      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->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 uint32_t bti = insn.function;
+    const uint32_t elemNum = insn.elem;
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->UNTYPED_READ(dst, src, bti, elemNum);
+    p->pop();
+  }
+
+  void GenContext::emitUntypedWriteInstruction(const SelectionInstruction &insn) {
+    const GenReg src = ra->genReg(insn.src[0]);
+    const uint32_t bti = insn.function;
+    const uint32_t elemNum = insn.elem;
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->UNTYPED_WRITE(src, bti, elemNum);
+    p->pop();
+  }
+
+  void GenContext::emitByteGatherInstruction(const SelectionInstruction &insn) {
+    const GenReg dst = ra->genReg(insn.dst[0]);
+    const GenReg src = ra->genReg(insn.src[0]);
+    const uint32_t bti = insn.function;
+    const uint32_t elemSize = insn.elem;
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->BYTE_GATHER(dst, src, bti, elemSize);
+    p->pop();
+  }
+
+  void GenContext::emitByteScatterInstruction(const SelectionInstruction &insn) {
+    const GenReg src = ra->genReg(insn.src[0]);
+    const uint32_t bti = insn.function;
+    const uint32_t elemSize = insn.elem;
+    p->push();
+    setInstructionState(p->curr, insn.state);
+    p->BYTE_SCATTER(src, bti, elemSize);
+    p->pop();
+  }
 
   BVAR(OCL_OUTPUT_ASM, false);
   void GenContext::emitCode(void) {
index 67a76e0..cef3096 100644 (file)
@@ -38,7 +38,8 @@ namespace gbe
   class GenEmitter;           // Helps emitting Gen ISA
   class GenRegAllocator;      // Handle the register allocation
   class Selection;            // Performs instruction selection
-  class SelectionInstruction; // Pre-RA GEN instruction
+  class SelectionInstruction; // Pre-RA Gen instruction
+  class SelectionReg;         // Pre-RA Gen register
 
   /*! Context is the helper structure to build the Gen ISA or simulation code
    *  from GenIR
@@ -62,8 +63,12 @@ namespace gbe
     void emitStackPointer(void);
     /*! Emit the instructions */
     void emitInstructionStream(void);
+    /*! Emit the instructions */
+    void emitInstructionStream2(void);
     /*! Set the correct target values for the branches */
     void patchBranches(void);
+    /*! Set the correct target values for the branches */
+    void patchBranches2(void);
     /*! Bool registers will use scalar words. So we will consider them as
      *  scalars in Gen backend
      */
@@ -72,8 +77,6 @@ namespace gbe
     INLINE bool isSpecialReg(ir::Register reg) const {
       return fn.isSpecialReg(reg);
     }
-    /*! Build the final physical register */
-    GenReg getGenReg(ir::Register reg, const SelectionReg &selReg) const;
 
     /*! Emit instruction per family */
     void emitUnaryInstruction(const ir::UnaryInstruction &insn);
@@ -121,12 +124,12 @@ namespace gbe
 
     /*! Implements base class */
     virtual Kernel *allocateKernel(void);
-    /*! Simplistic allocation to start with */
-    // map<ir::Register, GenReg> RA;
     /*! Store the position of each label instruction in the Gen ISA stream */
     map<ir::LabelIndex, uint32_t> labelPos;
     /*! Store the position of each branch instruction in the Gen ISA stream */
     map<const ir::Instruction*, uint32_t> branchPos;
+    /*! Store the Gen instructions to patch */
+    vector<std::pair<ir::LabelIndex, uint32_t>> branchPos2;
     /*! Encode Gen ISA */
     GenEmitter *p;
     /*! Instruction selection on Gen ISA (pre-register allocation) */
index 2b236da..0dc6db8 100644 (file)
@@ -246,9 +246,8 @@ namespace gbe
     insn->dstNum = 0;
   }
 
-  void Selection::EOT(Reg src) {
+  void Selection::EOT(void) {
     SelectionInstruction *insn = this->appendInsn();
-    insn->src[0] = src;
     insn->opcode = SEL_OP_EOT;
     insn->state = this->curr;
     insn->srcNum = 1;
@@ -936,6 +935,7 @@ namespace gbe
         this->EOT(127);
       this->pop();
 #endif
+      this->EOT();
     } else if (opcode == OP_BRA) {
       const LabelIndex dst = insn.getLabelIndex();
       const LabelIndex src = insn.getParent()->getLabelIndex();
index 12553b8..5b9f007 100644 (file)
@@ -730,7 +730,7 @@ namespace gbe
     /*! Compare instructions */
     void CMP(uint32_t conditional, Reg src0, Reg src1);
     /*! EOT is used to finish GPGPU threads */
-    void EOT(Reg src);
+    void EOT(void);
     /*! No-op */
     void NOP(void);
     /*! Wait instruction (used for the barrier) */
index 67ff558..5e416e5 100644 (file)
@@ -351,6 +351,40 @@ namespace gbe
       grfOffset = this->createGenReg(reg, grfOffset);
   }
 
+  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;
+  }
+
+  GenReg GenRegAllocator::genReg(const SelectionReg &reg) {
+    // Right now, only GRF are allocated ...
+    if (reg.file == GEN_GENERAL_REGISTER_FILE) {
+      GBE_ASSERT(RA.contains(reg.reg) != false);
+      GenReg dst = RA.find(reg.reg)->second;
+      // XXX Fix that properly (ir::Type is *not* needed)
+      if (reg.quarter != 0)
+        dst = this->genRegQn(reg.reg, reg.quarter+1, ir::TYPE_S32);
+      else
+        setGenReg(dst, reg);
+      return dst;
+    }
+    // Other registers are already physical registers
+    else {
+      GenReg dst;
+      setGenReg(dst, reg);
+      dst.nr = reg.nr;
+      dst.subnr = reg.subnr;
+      return dst;
+    }
+  }
+
   GenReg GenRegAllocator::genReg(ir::Register reg, ir::Type type) {
     const uint32_t genType = getGenType(type);
     auto it = RA.find(reg);
index a408af2..eea06de 100644 (file)
@@ -31,7 +31,8 @@
 
 namespace gbe
 {
-  class Selection; // pre-register allocation code generation
+  class Selection;    // Pre-register allocation code generation
+  class SelectionReg; // Pre-register allocation Gen register
 
   /*! Provides the location of a register in a vector */
   typedef std::pair<SelectionVector*, uint32_t> VectorLocation;
@@ -43,6 +44,8 @@ namespace gbe
     GenRegAllocator(GenContext &ctx);
     /*! Perform the register allocation */
     void allocate(Selection &selection);
+    /*! Return the Gen register from the selection register */
+    GenReg genReg(const SelectionReg &reg);
     /*! Return the Gen register from the GenIR one */
     GenReg genReg(ir::Register, ir::Type type = ir::TYPE_FLOAT);
     /*! Compute the quarterth register part when using SIMD8 with Qn (n in 2,3,4) */