Fixed instruction size in the instruction definitions Added more tests for the contex...
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Mon, 20 Feb 2012 04:05:28 +0000 (04:05 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:22 +0000 (16:15 -0700)
backend/src/ir/context.cpp
backend/src/ir/context.hpp
backend/src/ir/instruction.cpp
backend/src/ir/instruction.hpp
backend/src/ir/instruction.hxx
backend/src/utest/utest_context.cpp

index 5822c04..d08c50d 100644 (file)
@@ -30,17 +30,17 @@ namespace ir {
   Context::Context(Unit &unit) : unit(unit), fn(NULL), bb(NULL) {}
 
   void Context::startFunction(const std::string &name) {
-    if (fn != NULL) fnStack.push_back(fn);
+    fnStack.push_back(StackElem(fn,bb));
     fn = unit.newFunction(name);
   }
 
   void Context::endFunction(void) {
     GBE_ASSERTM(fn != NULL, "No function to end");
-    if (fnStack.size() != 0) {
-      fn = fnStack.back();
-      fnStack.pop_back();
-    } else
-      fn = NULL;
+    GBE_ASSERT(fnStack.size() != 0);
+    const StackElem elem = fnStack.back();
+    fnStack.pop_back();
+    fn = elem.fn;
+    bb = elem.bb;
   }
 
   Register Context::reg(RegisterData::Family family) {
@@ -48,6 +48,11 @@ namespace ir {
     return fn->file.append(family);
   }
 
+  LabelIndex Context::label(void) {
+    GBE_ASSERTM(fn != NULL, "No function currently defined");
+    return fn->newLabel();
+  }
+
   void Context::input(Register reg) {
     GBE_ASSERTM(fn != NULL, "No function currently defined");
     GBE_ASSERTM(reg < fn->file.regNum(), "Out-of-bound register");
index 4bf4fd6..da37e40 100644 (file)
@@ -48,8 +48,10 @@ namespace ir {
     void startFunction(const std::string &name);
     /*! Close the function */
     void endFunction(void);
-    /*! Create a new register for the given family */
+    /*! Create a new register with the given family for the current function */
     Register reg(RegisterData::Family family);
+    /*! Create a new label for the current function */
+    LabelIndex label(void);
     /*! Append a new input register for the function */
     void input(Register reg);
     /*! Append a new output register for the function */
@@ -93,22 +95,6 @@ namespace ir {
       this->STORE(type, index, offset, space, valueNum);
     }
 
-#define DECL_CMP(NAME)                              \
-    void NAME(Type type,                            \
-              Register dst,                         \
-              Register src0,                        \
-              Register src1)                        \
-    {                                               \
-      this->CMP(type, CMP_##NAME, dst, src0, src1); \
-    }
-DECL_CMP(EQ)
-DECL_CMP(NE)
-DECL_CMP(LT)
-DECL_CMP(LE)
-DECL_CMP(GT)
-DECL_CMP(GE)
-#undef DECL_CMP
-
   private:
     /*! A block must be started with a label */
     void startBlock(void);
@@ -116,10 +102,16 @@ DECL_CMP(GE)
     void endBlock(void);
     /*! Append the instruction in the current basic block */
     void append(const Instruction &insn);
-    Unit &unit;               //!< A unit is associated to a contect
-    Function *fn;             //!< Current function we are processing
-    BasicBlock *bb;           //!< Current basic block we are filling
-    vector<Function*> fnStack;//!< Stack of functions still to finish
+    Unit &unit;                 //!< A unit is associated to a contect
+    Function *fn;               //!< Current function we are processing
+    BasicBlock *bb;             //!< Current basic block we are filling
+    /*! Functions can be defined recursiely */
+    struct StackElem {
+      INLINE StackElem(Function *fn, BasicBlock *bb) : fn(fn), bb(bb) {}
+      Function *fn;
+      BasicBlock *bb;
+    };
+    vector<StackElem> fnStack;  //!< Stack of functions still to finish
     GBE_CLASS(Context);
   };
 
index 9393848..ba8006f 100644 (file)
@@ -54,7 +54,7 @@ namespace ir {
     };
 
     /*! Policy shared by all the internal instructions */
-    struct ALIGNED_INSTRUCTION BasePolicy {
+    struct BasePolicy {
       /*! Create an instruction from its internal representation */
       Instruction convert(void) const {
         return Instruction(reinterpret_cast<const char *>(&this->opcode));
@@ -86,7 +86,8 @@ namespace ir {
     };
 
     /*! All 1-source arithmetic instructions */
-    class UnaryInstruction : public NaryInstruction<1>
+    class ALIGNED_INSTRUCTION UnaryInstruction :
+      public NaryInstruction<1>
     {
     public:
       UnaryInstruction(Opcode opcode,
@@ -101,7 +102,8 @@ namespace ir {
     };
 
     /*! All 2-source arithmetic instructions */
-    class BinaryInstruction : public NaryInstruction<2>
+    class ALIGNED_INSTRUCTION BinaryInstruction :
+      public NaryInstruction<2>
     {
     public:
       BinaryInstruction(Opcode opcode,
@@ -120,7 +122,8 @@ namespace ir {
     /*! This is for MADs mostly. Since three sources cannot be encoded in 64
      *  bytes, we use tuples of registers
      */
-    class TernaryInstruction : public BasePolicy
+    class ALIGNED_INSTRUCTION TernaryInstruction :
+      public BasePolicy
     {
     public:
       TernaryInstruction(Opcode opcode,
@@ -155,21 +158,22 @@ namespace ir {
      *  steal all the methods from it, except wellFormed (dst register is always
      *  a boolean value)
      */
-    class CompareInstruction : public BinaryInstruction
+    class ALIGNED_INSTRUCTION CompareInstruction : public NaryInstruction<2>
     {
     public:
-      CompareInstruction(Type type,
-                         CompareOperation operation,
+      CompareInstruction(Opcode opcode,
+                         Type type,
                          Register dst,
                          Register src0,
-                         Register src1) :
-        BinaryInstruction(OP_CMP, type, dst, src0, src1)
+                         Register src1)
       {
-        this->operation = operation;
+        this->opcode = opcode;
+        this->type = type;
+        this->dst = dst;
+        this->src[0] = src0;
+        this->src[1] = src1;
       }
-      INLINE CompareOperation getOperation(void) const { return operation; }
       INLINE bool wellFormed(const Function &fn, std::string &whyNot) const;
-      CompareOperation operation;
     };
 
     class ConvertInstruction : public BasePolicy
@@ -232,15 +236,17 @@ namespace ir {
       bool hasPredicate;     //!< Is it predicated?
     };
 
-    class LoadInstruction : public BasePolicy
+    class ALIGNED_INSTRUCTION LoadInstruction :
+      public BasePolicy
     {
     public:
       LoadInstruction(Type type,
                       Tuple dstValues,
                       Register offset,
                       MemorySpace memSpace,
-                      uint16_t valueNum)
+                      uint32_t valueNum)
       {
+        GBE_ASSERT(valueNum < 255);
         this->opcode = OP_STORE;
         this->type = type;
         this->offset = offset;
@@ -266,18 +272,20 @@ namespace ir {
       Register offset;      //!< First source is the offset where to store
       Tuple values;         //!< Values to load
       MemorySpace memSpace; //!< Where to store
-      uint16_t valueNum;    //!< Number of values to store
+      uint8_t valueNum;     //!< Number of values to store
     };
 
-    class StoreInstruction : public BasePolicy, public NoDstPolicy
+    class ALIGNED_INSTRUCTION StoreInstruction :
+      public BasePolicy, public NoDstPolicy
     {
     public:
       StoreInstruction(Type type,
                        Tuple values,
                        Register offset,
                        MemorySpace memSpace,
-                       uint16_t valueNum)
+                       uint32_t valueNum)
       {
+        GBE_ASSERT(valueNum < 255);
         this->opcode = OP_STORE;
         this->type = type;
         this->offset = offset;
@@ -301,17 +309,19 @@ namespace ir {
       Register offset;      //!< First source is the offset where to store
       Tuple values;         //!< Values to store
       MemorySpace memSpace; //!< Where to store
-      uint16_t valueNum;    //!< Number of values to store
+      uint8_t valueNum;     //!< Number of values to store
     };
 
-    class TextureInstruction : public BasePolicy, public NoDstPolicy, public NoSrcPolicy // TODO REMOVE THIS
+    class ALIGNED_INSTRUCTION TextureInstruction :
+      public BasePolicy, public NoDstPolicy, public NoSrcPolicy // TODO REMOVE THIS
     {
     public:
       INLINE TextureInstruction(void) { this->opcode = OP_TEX; }
       INLINE bool wellFormed(const Function &fn, std::string &why) const;
     };
 
-    class LoadImmInstruction : public BasePolicy, public NoSrcPolicy
+    class ALIGNED_INSTRUCTION LoadImmInstruction :
+      public BasePolicy, public NoSrcPolicy
     {
     public:
       INLINE LoadImmInstruction(Type type,
@@ -338,7 +348,8 @@ namespace ir {
       Type type;                     //!< Type of the immediate
     };
 
-    class FenceInstruction : public BasePolicy, public NoSrcPolicy, public NoDstPolicy
+    class ALIGNED_INSTRUCTION FenceInstruction :
+      public BasePolicy, public NoSrcPolicy, public NoDstPolicy
     {
     public:
       INLINE FenceInstruction(MemorySpace memSpace) {
@@ -349,7 +360,8 @@ namespace ir {
       MemorySpace memSpace; //!< The loads and stores to order
     };
 
-    class LabelInstruction : public BasePolicy, public NoDstPolicy, public NoSrcPolicy
+    class ALIGNED_INSTRUCTION LabelInstruction :
+      public BasePolicy, public NoDstPolicy, public NoSrcPolicy
     {
     public:
       INLINE LabelInstruction(LabelIndex labelIndex) {
@@ -546,22 +558,24 @@ namespace ir {
     return fn.getRegisterData(this->getSrcIndex(fn, ID));
   }
 
-#define DECL_INSN(OPCODE, CLASS)                           \
-  case OP_##OPCODE:                                        \
+#define DECL_INSN(OPCODE, CLASS)                                  \
+  case OP_##OPCODE:                                               \
   return HelperIntrospection<CLASS, RefClass>::value == 1;
 
-#define START_INTROSPECTION(CLASS)                                            \
-  static_assert(sizeof(CLASS)==sizeof(Instruction), "Bad instruction size");  \
-  bool CLASS::isClassOf(const Instruction &insn) {                            \
-    const Opcode op = insn.getOpcode();                                       \
-    typedef CLASS RefClass;                                                   \
+#define START_INTROSPECTION(CLASS)                                \
+  static_assert(sizeof(internal::CLASS) == sizeof(Instruction),   \
+                "Bad instruction size");                          \
+  static_assert(offsetof(internal::CLASS, opcode) == 0,           \
+                "Bad opcode offset");                             \
+  bool CLASS::isClassOf(const Instruction &insn) {                \
+    const Opcode op = insn.getOpcode();                           \
+    typedef CLASS RefClass;                                       \
     switch (op) {
 
-#define END_INTROSPECTION(CLASS)                                              \
-      default: return false;                                                  \
-    };                                                                        \
-  }                                                                           \
-  static_assert(offsetof(internal::CLASS, opcode)==0, "Bad opcode offset");
+#define END_INTROSPECTION(CLASS)                                  \
+      default: return false;                                      \
+    };                                                            \
+  }                                                               \
 
 START_INTROSPECTION(UnaryInstruction)
 #include "ir/instruction.hxx"
@@ -621,16 +635,16 @@ END_INTROSPECTION(LabelInstruction)
   ///////////////////////////////////////////////////////////////////////////
 
 #define DECL_INSN(OPCODE, CLASS)               \
-  case OP_##OPCODE: reinterpret_cast<const internal::CLASS*>(this)->CALL;
+  case OP_##OPCODE: return reinterpret_cast<const internal::CLASS*>(this)->CALL;
 
 #define START_FUNCTION(CLASS, RET, PROTOTYPE)  \
   RET CLASS::PROTOTYPE const {                 \
     const Opcode op = this->getOpcode();       \
     switch (op) {
 
-#define END_FUNCTION(CLASS, RET)              \
-    };                                        \
-    return RET();                             \
+#define END_FUNCTION(CLASS, RET)               \
+    };                                         \
+    return RET();                              \
   }
 
 #define CALL getSrcNum()
@@ -675,7 +689,6 @@ DECL_MEM_FN(UnaryInstruction, Type, getType(void), getType())
 DECL_MEM_FN(BinaryInstruction, Type, getType(void), getType())
 DECL_MEM_FN(TernaryInstruction, Type, getType(void), getType())
 DECL_MEM_FN(CompareInstruction, Type, getType(void), getType())
-DECL_MEM_FN(CompareInstruction, CompareOperation, getOperation(void), getOperation())
 DECL_MEM_FN(ConvertInstruction, Type, getSrcType(void), getSrcType())
 DECL_MEM_FN(ConvertInstruction, Type, getDstType(void), getDstType())
 DECL_MEM_FN(StoreInstruction, Type, getValueType(void), getValueType())
@@ -697,7 +710,7 @@ DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
 
   // All unary functions
 #define DECL_EMIT_FUNCTION(NAME)                                      \
-  Instruction NAME(Type type, Register dst, Register src) { \
+  Instruction NAME(Type type, Register dst, Register src) {           \
     const internal::UnaryInstruction insn(OP_##NAME, type, dst, src); \
     return insn.convert();                                            \
   }
@@ -714,9 +727,7 @@ DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
 
   // All binary functions
 #define DECL_EMIT_FUNCTION(NAME)                                              \
-  Instruction NAME(Type type, Register dst,                              \
-                   Register src0,                                        \
-                   Register src1) {                                      \
+  Instruction NAME(Type type, Register dst,  Register src0, Register src1) {  \
     const internal::BinaryInstruction insn(OP_##NAME, type, dst, src0, src1); \
     return insn.convert();                                                    \
   }
@@ -743,17 +754,22 @@ DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
     return insn.convert();
   }
 
-  // CMP
-  Instruction CMP(Type type,
-                  CompareOperation operation,
-                  Register dst,
-                  Register src0,
-                  Register src1)
-  {
-    internal::CompareInstruction insn(type, operation, dst, src0, src1);
-    return insn.convert();
+  // All compare functions
+#define DECL_EMIT_FUNCTION(NAME)                                              \
+  Instruction NAME(Type type, Register dst,  Register src0, Register src1) {  \
+    const internal::CompareInstruction insn(OP_##NAME, type, dst, src0, src1);\
+    return insn.convert();                                                    \
   }
 
+  DECL_EMIT_FUNCTION(EQ)
+  DECL_EMIT_FUNCTION(NE)
+  DECL_EMIT_FUNCTION(LE)
+  DECL_EMIT_FUNCTION(LT)
+  DECL_EMIT_FUNCTION(GE)
+  DECL_EMIT_FUNCTION(GT)
+
+#undef DECL_EMIT_FUNCTION
+
   // CVT
   Instruction CVT(Type dstType, Type srcType, Register dst, Register src) {
     internal::ConvertInstruction insn(dstType, srcType, dst, src);
@@ -779,8 +795,8 @@ DECL_MEM_FN(BranchInstruction, bool, isPredicated(void), isPredicated())
   // LOAD and STORE
 #define DECL_EMIT_FUNCTION(NAME, CLASS)                               \
   Instruction NAME(Type type,                                         \
-                   Tuple tuple,                                  \
-                   Register offset,                              \
+                   Tuple tuple,                                       \
+                   Register offset,                                   \
                    MemorySpace space,                                 \
                    uint16_t valueNum)                                 \
   {                                                                   \
index b140c81..f16eb1b 100644 (file)
@@ -135,16 +135,6 @@ namespace ir {
     static bool isClassOf(const Instruction &insn);
   };
 
-  /*! Operation done in comparison */
-  enum CompareOperation : uint8_t {
-    CMP_EQ = 0, // ==
-    CMP_NE,     // !=
-    CMP_LT,     // <
-    CMP_LE,     // <=
-    CMP_GT,     // >
-    CMP_GE      // >=
-  };
-
   /*! Compare instructions compare anything from the same type and return a
    *  boolean value
    */
@@ -152,8 +142,6 @@ namespace ir {
   public:
     /*! Get the type of the source registers */
     Type getType(void) const;
-    /*! Compare operation in the instruction */
-    CompareOperation getOperation(void) const;
     /*! Return true if the given instruction is an instance of this class */
     static bool isClassOf(const Instruction &insn);
   };
@@ -336,8 +324,18 @@ namespace ir {
   Instruction AND(Type type, Register dst, Register src0, Register src1);
   /*! mad.type dst {src0, src1, src2} == src */
   Instruction MAD(Type type, Register dst, Tuple src);
-  /*! cmp.type.op dst src0 src1 */
-  Instruction CMP(Type type, CompareOperation op, Register dst, Register src0, Register src1);
+  /*! eq.type dst src0 src1 */
+  Instruction EQ(Type type, Register dst, Register src0, Register src1);
+  /*! ne.type dst src0 src1 */
+  Instruction NE(Type type, Register dst, Register src0, Register src1);
+  /*! lt.type dst src0 src1 */
+  Instruction LE(Type type, Register dst, Register src0, Register src1);
+  /*! le.type dst src0 src1 */
+  Instruction LT(Type type, Register dst, Register src0, Register src1);
+  /*! gt.type dst src0 src1 */
+  Instruction GE(Type type, Register dst, Register src0, Register src1);
+  /*! ge.type dst src0 src1 */
+  Instruction GT(Type type, Register dst, Register src0, Register src1);
   /*! cvt.{dstType <- srcType} dst src */
   Instruction CVT(Type dstType, Type srcType, Register dst, Register src0, Register src1);
   /*! bra labelIndex */
index 2da6b2b..7858f0d 100644 (file)
@@ -23,7 +23,6 @@
 
 /**
  * \file instruction.hxx
- *
  * \author Benjamin Segovia <benjamin.segovia@intel.com>
  */
 DECL_INSN(MOV, UnaryInstruction)
@@ -48,7 +47,12 @@ DECL_INSN(OR, BinaryInstruction)
 DECL_INSN(XOR, BinaryInstruction)
 DECL_INSN(AND, BinaryInstruction)
 DECL_INSN(MAD, TernaryInstruction)
-DECL_INSN(CMP, CompareInstruction)
+DECL_INSN(EQ, CompareInstruction)
+DECL_INSN(NE, CompareInstruction)
+DECL_INSN(LE, CompareInstruction)
+DECL_INSN(LT, CompareInstruction)
+DECL_INSN(GE, CompareInstruction)
+DECL_INSN(GT, CompareInstruction)
 DECL_INSN(CVT, ConvertInstruction)
 DECL_INSN(BRA, BranchInstruction)
 DECL_INSN(TEX, TextureInstruction)
index 74f0504..69d8efd 100644 (file)
@@ -46,12 +46,43 @@ namespace gbe
       ctx.MAD(TYPE_FLOAT, reg0, reg0, reg1, reg2);
     ctx.endFunction();
   }
+  static void noStartFunction(void) {
+    Unit unit;
+    Context ctx(unit);
+    ctx.endFunction();
+  }
+  static void recursiveDefinition(void) {
+    Unit unit;
+    Context ctx(unit);
+    ctx.startFunction("hop");
+      const Register reg0 = ctx.reg(RegisterData::DWORD);
+      const Register reg1 = ctx.reg(RegisterData::DWORD);
+      const Register reg2 = ctx.reg(RegisterData::DWORD);
+      ctx.MAD(TYPE_FLOAT, reg0, reg0, reg1, reg2);
+      ctx.startFunction("bip");
+        const LabelIndex label = ctx.label();
+        ctx.BRA(label);
+      ctx.endFunction();
+    ctx.endFunction();
+  }
+  static void labelUsedTwice(void) {
+    Unit unit;
+    Context ctx(unit);
+    ctx.startFunction("hop");
+      const LabelIndex label = ctx.label();
+      ctx.LABEL(label);
+      ctx.LABEL(label);
+    ctx.endFunction();
+  }
 } /* namespace gbe */
 
 static void utestContext(void)
 {
   UTEST_EXPECT_SUCCESS(gbe::emptyFunction());
   UTEST_EXPECT_SUCCESS(gbe::oneInstruction());
+  UTEST_EXPECT_FAILED(gbe::noStartFunction());
+  UTEST_EXPECT_SUCCESS(gbe::recursiveDefinition());
+  UTEST_EXPECT_FAILED(gbe::labelUsedTwice());
 }
 
 UTEST_REGISTER(utestContext)