[Beignet] [PATCH 1/3] Add atomic help functions. Support global and local buffer.

Zhigang Gong zhigang.gong at linux.intel.com
Wed Jun 26 19:58:46 PDT 2013


On Wed, Jun 26, 2013 at 03:29:21PM +0800, Yang Rong wrote:
> 
> Signed-off-by: Yang Rong <rong.r.yang at intel.com>
> ---
>  backend/src/backend/gen_context.cpp                |    9 +++
>  backend/src/backend/gen_context.hpp                |    1 +
>  backend/src/backend/gen_defs.hpp                   |   49 ++++++++++++--
>  backend/src/backend/gen_encoder.cpp                |   35 ++++++++++
>  backend/src/backend/gen_encoder.hpp                |    2 +
>  .../src/backend/gen_insn_gen7_schedule_info.hxx    |    2 +-
>  backend/src/backend/gen_insn_selection.cpp         |   61 +++++++++++++++++
>  backend/src/backend/gen_insn_selection.hpp         |    4 +-
>  backend/src/backend/gen_insn_selection.hxx         |    1 +
>  backend/src/ir/context.hpp                         |    6 ++
>  backend/src/ir/instruction.cpp                     |   70 +++++++++++++++++++-
>  backend/src/ir/instruction.hpp                     |   43 +++++++++++-
>  backend/src/ir/instruction.hxx                     |   13 ++++
>  13 files changed, 283 insertions(+), 13 deletions(-)
> 
> diff --git a/backend/src/backend/gen_context.cpp b/backend/src/backend/gen_context.cpp
> index 53ba73c..d122b7a 100644
> --- a/backend/src/backend/gen_context.cpp
> +++ b/backend/src/backend/gen_context.cpp
> @@ -224,6 +224,15 @@ namespace gbe
>      }
>    }
>  
> +  void GenContext::emitAtomicInstruction(const SelectionInstruction &insn) {
> +    const GenRegister src = ra->genReg(insn.src(0));
> +    const GenRegister dst = ra->genReg(insn.dst(0));
> +    const uint32_t function = insn.extra.function;
> +    const uint32_t bti = insn.extra.elem;
> +
> +    p->ATOMIC(dst, function, src, bti, insn.srcNum);
> +  }
> +
>    void GenContext::emitIndirectMoveInstruction(const SelectionInstruction &insn) {
>      GenRegister src = ra->genReg(insn.src(0));
>      if(isScalarReg(src.reg()))
> diff --git a/backend/src/backend/gen_context.hpp b/backend/src/backend/gen_context.hpp
> index 804384d..5dfaef9 100644
> --- a/backend/src/backend/gen_context.hpp
> +++ b/backend/src/backend/gen_context.hpp
> @@ -91,6 +91,7 @@ namespace gbe
>      void emitWriteFloat64Instruction(const SelectionInstruction &insn);
>      void emitUntypedReadInstruction(const SelectionInstruction &insn);
>      void emitUntypedWriteInstruction(const SelectionInstruction &insn);
> +    void emitAtomicInstruction(const SelectionInstruction &insn);
>      void emitByteGatherInstruction(const SelectionInstruction &insn);
>      void emitByteScatterInstruction(const SelectionInstruction &insn);
>      void emitSampleInstruction(const SelectionInstruction &insn);
> diff --git a/backend/src/backend/gen_defs.hpp b/backend/src/backend/gen_defs.hpp
> index 9d8db5b..01abf9a 100644
> --- a/backend/src/backend/gen_defs.hpp
> +++ b/backend/src/backend/gen_defs.hpp
> @@ -1,4 +1,4 @@
> -/* 
> +/*
>   * Copyright © 2012 Intel Corporation
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -21,7 +21,7 @@
>   Copyright (C) Intel Corp.  2006.  All Rights Reserved.
>   Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
>   develop this 3D driver.
> - 
> +
>   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
> @@ -29,11 +29,11 @@
>   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.
> @@ -41,7 +41,7 @@
>   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.
> - 
> +
>   **********************************************************************/
>   /*
>    * Authors:
> @@ -167,6 +167,28 @@ enum opcode {
>    GEN_OPCODE_NOP = 126,
>  };
>  
> +#define GEN_ATOMIC_SIMD16   0
> +#define GEN_ATOMIC_SIMD8    1
> +
> +enum GenAtomicOpCode {
> +  GEN_ATOMIC_OP_CMPWR8B   = 0,
> +  GEN_ATOMIC_OP_AND       = 1,
> +  GEN_ATOMIC_OP_OR        = 2,
> +  GEN_ATOMIC_OP_XOR       = 3,
> +  GEN_ATOMIC_OP_MOV       = 4,
> +  GEN_ATOMIC_OP_INC       = 5,
> +  GEN_ATOMIC_OP_DEC       = 6,
> +  GEN_ATOMIC_OP_ADD       = 7,
> +  GEN_ATOMIC_OP_SUB       = 8,
> +  GEN_ATOMIC_OP_REVSUB    = 9,
> +  GEN_ATOMIC_OP_IMAX      = 10,
> +  GEN_ATOMIC_OP_IMIN      = 11,
> +  GEN_ATOMIC_OP_UMAX      = 12,
> +  GEN_ATOMIC_OP_UMIN      = 13,
> +  GEN_ATOMIC_OP_CMPWR     = 14,
> +  GEN_ATOMIC_OP_PREDEC    = 15
> +};
> +
>  /*! Gen SFID */
>  enum GenMessageTarget {
>    GEN_SFID_NULL                     = 0,
> @@ -770,7 +792,7 @@ struct GenInstruction
>      /*! Memory fence */
>      struct {
>        uint32_t bti:8;
> -      uint32_t ingored:5;
> +      uint32_t pad:5;
>        uint32_t commit_enable:1;
>        uint32_t msg_type:4;
>        uint32_t pad2:1;
> @@ -781,6 +803,21 @@ struct GenInstruction
>        uint32_t end_of_thread:1;
>      } gen7_memory_fence;
>  
> +    /*! atomic messages */
> +    struct {
> +      uint32_t bti:8;
> +      uint32_t aop_type:4;
> +      uint32_t simd_mode:1;
> +      uint32_t return_data:1;
> +      uint32_t msg_type:4;
> +      uint32_t category:1;
> +      uint32_t header_present:1;
> +      uint32_t response_length:5;
> +      uint32_t msg_length:4;
> +      uint32_t pad3:2;
> +      uint32_t end_of_thread:1;
> +    } gen7_atomic_op;
> +
>      struct {
>        uint32_t src1_subreg_nr_high:1;
>        uint32_t src1_reg_nr:8;
> diff --git a/backend/src/backend/gen_encoder.cpp b/backend/src/backend/gen_encoder.cpp
> index ae981b2..b843c43 100644
> --- a/backend/src/backend/gen_encoder.cpp
> +++ b/backend/src/backend/gen_encoder.cpp
> @@ -558,6 +558,41 @@ namespace gbe
>                             response_length);
>    }
>  
> +  void GenEncoder::ATOMIC(GenRegister dst, uint32_t function, GenRegister src, uint32_t bti, uint32_t srcNum) {
> +    GenInstruction *insn = this->next(GEN_OPCODE_SEND);
> +    uint32_t msg_length = 0;
> +    uint32_t response_length = 0;
> +
> +    if (this->curr.execWidth == 8) {
> +      msg_length = srcNum;
> +      response_length = 1;
> +    } else if (this->curr.execWidth == 16) {
> +      msg_length = 2*srcNum;
> +      response_length = 2;
> +    } else
> +      NOT_IMPLEMENTED;
> +
> +    this->setHeader(insn);
> +    this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
> +    this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
> +    this->setSrc1(insn, GenRegister::immud(0));
> +
> +    const GenMessageTarget sfid = GEN_SFID_DATAPORT_DATA_CACHE;
> +    setMessageDescriptor(this, insn, sfid, msg_length, response_length);
> +    insn->bits3.gen7_atomic_op.msg_type = GEN_UNTYPED_ATOMIC_READ;
> +    insn->bits3.gen7_atomic_op.bti = bti;
> +    insn->bits3.gen7_atomic_op.return_data = 1;
> +    insn->bits3.gen7_atomic_op.aop_type = function;
> +
> +    if (this->curr.execWidth == 8)
> +      insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD8;
> +    else if (this->curr.execWidth == 16)
> +      insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD16;
> +    else
> +      NOT_SUPPORTED;
> +
> +  }
> +
>    GenInstruction *GenEncoder::next(uint32_t opcode) {
>       GenInstruction insn;
>       std::memset(&insn, 0, sizeof(GenInstruction));
> diff --git a/backend/src/backend/gen_encoder.hpp b/backend/src/backend/gen_encoder.hpp
> index 1a5dcf9..415414c 100644
> --- a/backend/src/backend/gen_encoder.hpp
> +++ b/backend/src/backend/gen_encoder.hpp
> @@ -134,6 +134,8 @@ namespace gbe
>      void NOP(void);
>      /*! Wait instruction (used for the barrier) */
>      void WAIT(void);
> +    /*! Atomic instructions */
> +    void ATOMIC(GenRegister dst, uint32_t function, GenRegister src, uint32_t bti, uint32_t srcNum);
>      /*! Read 64-bits float arrays */
>      void READ_FLOAT64(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemNum);
>      /*! Write 64-bits float arrays */
> diff --git a/backend/src/backend/gen_insn_gen7_schedule_info.hxx b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
> index a3b4621..f3f4a25 100644
> --- a/backend/src/backend/gen_insn_gen7_schedule_info.hxx
> +++ b/backend/src/backend/gen_insn_gen7_schedule_info.hxx
> @@ -21,4 +21,4 @@ DECL_GEN7_SCHEDULE(ByteScatter,     80,        1,        1)
>  DECL_GEN7_SCHEDULE(Sample,          80,        1,        1)
>  DECL_GEN7_SCHEDULE(TypedWrite,      80,        1,        1)
>  DECL_GEN7_SCHEDULE(GetImageInfo,    20,        4,        2)
> -
> +DECL_GEN7_SCHEDULE(Atomic,          80,        1,        1)
> diff --git a/backend/src/backend/gen_insn_selection.cpp b/backend/src/backend/gen_insn_selection.cpp
> index 1e5f514..990c15b 100644
> --- a/backend/src/backend/gen_insn_selection.cpp
> +++ b/backend/src/backend/gen_insn_selection.cpp
> @@ -168,12 +168,14 @@ namespace gbe
>    bool SelectionInstruction::isRead(void) const {
>      return this->opcode == SEL_OP_UNTYPED_READ ||
>             this->opcode == SEL_OP_READ_FLOAT64 ||
> +           this->opcode == SEL_OP_ATOMIC       ||
>             this->opcode == SEL_OP_BYTE_GATHER;
>    }
>  
>    bool SelectionInstruction::isWrite(void) const {
>      return this->opcode == SEL_OP_UNTYPED_WRITE ||
>             this->opcode == SEL_OP_WRITE_FLOAT64 ||
> +           this->opcode == SEL_OP_ATOMIC        ||
>             this->opcode == SEL_OP_BYTE_SCATTER;
>    }
>  
> @@ -454,6 +456,8 @@ namespace gbe
>      void NOP(void);
>      /*! Wait instruction (used for the barrier) */
>      void WAIT(void);
> +    /*! Atomic instruction */
> +    void ATOMIC(Reg dst, uint32_t function, uint32_t srcNum, Reg src0, Reg src1, Reg src2, uint32_t bti);
>      /*! Read 64 bits float array */
>      void READ_FLOAT64(Reg addr, const GenRegister *dst, uint32_t elemNum, uint32_t bti);
>      /*! Write 64 bits float array */
> @@ -728,6 +732,23 @@ namespace gbe
>      insn->src(0) = src;
>    }
>  
> +  void Selection::Opaque::ATOMIC(Reg dst, uint32_t function,
> +                                     uint32_t srcNum, Reg src0,
> +                                     Reg src1, Reg src2, uint32_t bti) {
> +    SelectionInstruction *insn = this->appendInsn(SEL_OP_ATOMIC, 1, srcNum);
> +    insn->dst(0) = dst;
> +    insn->src(0) = src0;
> +    if(srcNum > 1) insn->src(1) = src1;
> +    if(srcNum > 2) insn->src(2) = src2;
> +    insn->extra.function = function;
> +    insn->extra.elem     = bti;
> +    SelectionVector *vector = this->appendVector();
> +
> +    vector->regNum = srcNum;
> +    vector->reg = &insn->src(0);
> +    vector->isSrc = 1;
> +  }
> +
>    void Selection::Opaque::EOT(void) { this->appendInsn(SEL_OP_EOT, 0, 0); }
>    void Selection::Opaque::NOP(void) { this->appendInsn(SEL_OP_NOP, 0, 0); }
>    void Selection::Opaque::WAIT(void) { this->appendInsn(SEL_OP_WAIT, 0, 0); }
> @@ -914,6 +935,7 @@ namespace gbe
>    bool Selection::Opaque::isRoot(const ir::Instruction &insn) const {
>      if (insn.getDstNum() > 1 ||
>          insn.hasSideEffect() ||
> +        insn.isMemberOf<ir::AtomicInstruction>() ||

Maybe it's better to add those ATOMIC instructions to hasSideEffect group.

>          insn.isMemberOf<ir::BranchInstruction>() ||
>          insn.isMemberOf<ir::LabelInstruction>())
>      return true;
> @@ -2015,6 +2037,44 @@ namespace gbe
>      DECL_CTOR(ConvertInstruction, 1, 1);
>    };
>  
> +  /*! Convert instruction pattern */
> +  DECL_PATTERN(AtomicInstruction)
> +  {
> +    INLINE bool emitOne(Selection::Opaque &sel, const ir::AtomicInstruction &insn) const
> +    {
> +      using namespace ir;
> +      const Opcode opcode = insn.getOpcode();
> +      const AddressSpace space = insn.getAddressSpace();
> +      const uint32_t bti = space == MEM_LOCAL ? 0xfe : 0x01;
> +      const uint32_t srcNum = insn.getSrcNum();
> +      const GenRegister src0 = sel.selReg(insn.getSrc(0), TYPE_U32);   //address
> +      GenRegister src1 = src0, src2 = src0;
> +      if(srcNum > 1) src1 = sel.selReg(insn.getSrc(1), TYPE_U32);
> +      if(srcNum > 2) src2 = sel.selReg(insn.getSrc(2), TYPE_U32);
> +      GenRegister dst  = sel.selReg(insn.getDst(0), TYPE_U32);
> +      GenAtomicOpCode aop = GEN_ATOMIC_OP_CMPWR8B;
> +      switch (opcode) {
> +        case OP_ATOMIC_ADD:     aop = GEN_ATOMIC_OP_ADD; break;
> +        case OP_ATOMIC_SUB:     aop = GEN_ATOMIC_OP_SUB; break;
> +        case OP_ATOMIC_AND:     aop = GEN_ATOMIC_OP_AND; break;
> +        case OP_ATOMIC_OR :     aop = GEN_ATOMIC_OP_OR;  break;
> +        case OP_ATOMIC_XOR:     aop = GEN_ATOMIC_OP_XOR; break;
> +        case OP_ATOMIC_XCHG:    aop = GEN_ATOMIC_OP_MOV; break;
> +        case OP_ATOMIC_UMIN:    aop = GEN_ATOMIC_OP_UMIN; break;
> +        case OP_ATOMIC_UMAX:    aop = GEN_ATOMIC_OP_UMAX; break;
> +        case OP_ATOMIC_IMIN:    aop = GEN_ATOMIC_OP_IMIN; break;
> +        case OP_ATOMIC_IMAX:    aop = GEN_ATOMIC_OP_IMAX; break;
> +        case OP_ATOMIC_INC:     aop = GEN_ATOMIC_OP_INC; break;
> +        case OP_ATOMIC_DEC:     aop = GEN_ATOMIC_OP_DEC; break;
> +        case OP_ATOMIC_CMPXCHG: aop = GEN_ATOMIC_OP_CMPWR; break;
> +        default: NOT_SUPPORTED;
As all of the defined ATOMIC OPs are handled at the above cases, I prefer
to add an assert at default case rather than NOT_SUPPORTED.

> +      }
> +      sel.ATOMIC(dst, aop, srcNum, src0, src1, src2, bti);
> +      return true;
> +    }
> +    DECL_CTOR(AtomicInstruction, 1, 1);
> +  };
> +
>    /*! Select instruction pattern */
>    class SelectInstructionPattern : public SelectionPattern
>    {
> @@ -2361,6 +2421,7 @@ namespace gbe
>      this->insert<SelectInstructionPattern>();
>      this->insert<CompareInstructionPattern>();
>      this->insert<ConvertInstructionPattern>();
> +    this->insert<AtomicInstructionPattern>();
>      this->insert<LabelInstructionPattern>();
>      this->insert<BranchInstructionPattern>();
>      this->insert<Int32x32MulInstructionPattern>();
> diff --git a/backend/src/backend/gen_insn_selection.hpp b/backend/src/backend/gen_insn_selection.hpp
> index 778eb1f..5ae6e42 100644
> --- a/backend/src/backend/gen_insn_selection.hpp
> +++ b/backend/src/backend/gen_insn_selection.hpp
> @@ -92,9 +92,9 @@ namespace gbe
>      GenInstructionState state;
>      union {
>        struct {
> -        /*! Store bti for loads/stores and function for math and compares */
> +        /*! Store bti for loads/stores and function for math, atomic and compares */
>          uint16_t function:8;
> -        /*! elemSize for byte scatters / gathers, elemNum for untyped msg */
> +        /*! elemSize for byte scatters / gathers, elemNum for untyped msg, bti for atomic */
>          uint16_t elem:8;
>        };
>        struct {
> diff --git a/backend/src/backend/gen_insn_selection.hxx b/backend/src/backend/gen_insn_selection.hxx
> index 4b5525b..4869975 100644
> --- a/backend/src/backend/gen_insn_selection.hxx
> +++ b/backend/src/backend/gen_insn_selection.hxx
> @@ -20,6 +20,7 @@ DECL_SELECTION_IR(RSL, BinaryInstruction)
>  DECL_SELECTION_IR(ASR, BinaryInstruction)
>  DECL_SELECTION_IR(ADD, BinaryInstruction)
>  DECL_SELECTION_IR(MUL, BinaryInstruction)
> +DECL_SELECTION_IR(ATOMIC, AtomicInstruction)
>  DECL_SELECTION_IR(MACH, BinaryInstruction)
>  DECL_SELECTION_IR(CMP, CompareInstruction)
>  DECL_SELECTION_IR(SEL_CMP, CompareInstruction)
> diff --git a/backend/src/ir/context.hpp b/backend/src/ir/context.hpp
> index c286f1d..55e76f2 100644
> --- a/backend/src/ir/context.hpp
> +++ b/backend/src/ir/context.hpp
> @@ -150,6 +150,12 @@ namespace ir {
>        this->append(insn);
>      }
>  
> +    /*! For all atomic functions */
> +    void ATOMIC(Opcode opcode, Register dst, AddressSpace space, Tuple src) {
> +      const Instruction insn = gbe::ir::ATOMIC(opcode, dst, space, src);
> +      this->append(insn);
> +    }
> +
>      /*! LOAD with the destinations directly specified */
>      template <typename... Args>
>      void LOAD(Type type, Register offset, AddressSpace space, bool dwAligned, Args...values)
> diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
> index a57c204..052b295 100644
> --- a/backend/src/ir/instruction.cpp
> +++ b/backend/src/ir/instruction.cpp
> @@ -1,4 +1,4 @@
> -/* 
> +/*
>   * Copyright © 2012 Intel Corporation
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -56,7 +56,7 @@ namespace ir {
>      };
>  
>      /*! For regular n source instructions */
> -    template <typename T, uint32_t srcNum> 
> +    template <typename T, uint32_t srcNum>
>      struct NSrcPolicy {
>        INLINE uint32_t getSrcNum(void) const { return srcNum; }
>        INLINE Register getSrc(const Function &fn, uint32_t ID) const {
> @@ -246,6 +246,37 @@ namespace ir {
>        Type srcType; //!< Type to convert from
>      };
>  
> +    class ALIGNED_INSTRUCTION AtomicInstruction :
> +      public BasePolicy,
> +      public TupleSrcPolicy<AtomicInstruction>,
> +      public NDstPolicy<AtomicInstruction, 1>
> +    {
> +    public:
> +      AtomicInstruction(Opcode opcode,
> +                         Register dst,
> +                         AddressSpace addrSpace,
> +                         Tuple src)
> +      {
> +        this->opcode = opcode;
> +        this->dst[0] = dst;
> +        this->src = src;
> +        this->addrSpace = addrSpace;
> +        srcNum = 2;
> +        if((opcode == OP_ATOMIC_INC) ||
> +          (opcode == OP_ATOMIC_DEC))
> +          srcNum = 1;
> +        if(opcode == OP_ATOMIC_CMPXCHG)
> +          srcNum = 3;
> +      }
> +      INLINE AddressSpace getAddressSpace(void) const { return this->addrSpace; }
> +      INLINE bool wellFormed(const Function &fn, std::string &whyNot) const;
> +      INLINE void out(std::ostream &out, const Function &fn) const;
> +      Register dst[1];
> +      Tuple src;
> +      AddressSpace addrSpace; //!< Address space
> +      uint8_t srcNum;         //!<Source Number
> +    };
> +
>      class ALIGNED_INSTRUCTION BranchInstruction :
>        public BasePolicy,
>        public NDstPolicy<BranchInstruction, 0>
> @@ -738,6 +769,20 @@ namespace ir {
>        return true;
>      }
>  
> +    // We can convert anything to anything, but types and families must match
> +    INLINE bool AtomicInstruction::wellFormed(const Function &fn, std::string &whyNot) const
> +    {
> +      if (UNLIKELY(checkSpecialRegForWrite(dst[0], fn, whyNot) == false))
> +        return false;
> +      if (UNLIKELY(checkRegisterData(FAMILY_DWORD, dst[0], fn, whyNot) == false))
> +        return false;
> +      for (uint32_t srcID = 0; srcID < srcNum; ++srcID)
> +        if (UNLIKELY(checkRegisterData(FAMILY_DWORD, getSrc(fn, srcID), fn, whyNot) == false))
> +          return false;
> +
> +      return true;
> +    }
> +
>      /*! Loads and stores follow the same restrictions */
>      template <typename T>
>      INLINE bool wellFormedLoadStore(const T &insn, const Function &fn, std::string &whyNot)
> @@ -883,6 +928,15 @@ namespace ir {
>        ternaryOrSelectOut(*this, out, fn);
>      }
>  
> +    INLINE void AtomicInstruction::out(std::ostream &out, const Function &fn) const {
> +      this->outOpcode(out);
> +      out << "." << addrSpace;
> +      out << " %" << this->getDst(fn, 0);
> +      out << " {" << "%" << this->getSrc(fn, 0) << "}";
> +      for (uint32_t i = 1; i < srcNum; ++i)
> +        out << " %" << this->getSrc(fn, i);
> +    }
> +
>      INLINE void ConvertInstruction::out(std::ostream &out, const Function &fn) const {
>        this->outOpcode(out);
>        out << "." << this->getDstType()
> @@ -1009,6 +1063,10 @@ START_INTROSPECTION(ConvertInstruction)
>  #include "ir/instruction.hxx"
>  END_INTROSPECTION(ConvertInstruction)
>  
> +START_INTROSPECTION(AtomicInstruction)
> +#include "ir/instruction.hxx"
> +END_INTROSPECTION(AtomicInstruction)
> +
>  START_INTROSPECTION(SelectInstruction)
>  #include "ir/instruction.hxx"
>  END_INTROSPECTION(SelectInstruction)
> @@ -1180,7 +1238,7 @@ END_FUNCTION(Instruction, Register)
>    }
>  
>    bool Instruction::hasSideEffect(void) const {
> -    return opcode == OP_STORE || 
> +    return opcode == OP_STORE ||
So did you try to add ATOMIC here? :)
>             opcode == OP_TYPED_WRITE ||
>             opcode == OP_SYNC;
>    }
> @@ -1197,6 +1255,7 @@ DECL_MEM_FN(SelectInstruction, Type, getType(void), getType())
>  DECL_MEM_FN(CompareInstruction, Type, getType(void), getType())
>  DECL_MEM_FN(ConvertInstruction, Type, getSrcType(void), getSrcType())
>  DECL_MEM_FN(ConvertInstruction, Type, getDstType(void), getDstType())
> +DECL_MEM_FN(AtomicInstruction, AddressSpace, getAddressSpace(void), getAddressSpace())
>  DECL_MEM_FN(StoreInstruction, Type, getValueType(void), getValueType())
>  DECL_MEM_FN(StoreInstruction, uint32_t, getValueNum(void), getValueNum())
>  DECL_MEM_FN(StoreInstruction, AddressSpace, getAddressSpace(void), getAddressSpace())
> @@ -1302,6 +1361,11 @@ DECL_MEM_FN(GetImageInfoInstruction, uint32_t, getInfoType(void), getInfoType())
>      return internal::ConvertInstruction(dstType, srcType, dst, src).convert();
>    }
>  
> +  // For all unary functions with given opcode
> +  Instruction ATOMIC(Opcode opcode, Register dst, AddressSpace space, Tuple src) {
> +    return internal::AtomicInstruction(opcode, dst, space, src).convert();
> +  }
> +
>    // BRA
>    Instruction BRA(LabelIndex labelIndex) {
>      return internal::BranchInstruction(OP_BRA, labelIndex).convert();
> diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp
> index 7662b6a..e8b34d0 100644
> --- a/backend/src/ir/instruction.hpp
> +++ b/backend/src/ir/instruction.hpp
> @@ -1,4 +1,4 @@
> -/* 
> +/*
>   * Copyright © 2012 Intel Corporation
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -228,6 +228,19 @@ namespace ir {
>      static bool isClassOf(const Instruction &insn);
>    };
>  
> +  /*! Atomic instruction */
> +  class AtomicInstruction : public Instruction {
> +  public:
> +    /*! Where the address register goes */
> +    static const uint32_t addressIndex = 0;
> +    /*! Address space that is manipulated here */
> +    AddressSpace getAddressSpace(void) const;
> +    /*! Return the register that contains the addresses */
> +    INLINE Register getAddress(void) const { return this->getSrc(addressIndex); }
> +    /*! Return true if the given instruction is an instance of this class */
> +    static bool isClassOf(const Instruction &insn);
> +  };
> +
>    /*! Store instruction. First source is the address. Next sources are the
>     *  values to store contiguously at the given address
>     */
> @@ -551,6 +564,34 @@ namespace ir {
>    Instruction GT(Type type, Register dst, Register src0, Register src1);
>    /*! cvt.{dstType <- srcType} dst src */
>    Instruction CVT(Type dstType, Type srcType, Register dst, Register src);
> +  /*! atomic dst addr.space {src1 {src2}} */
> +  Instruction ATOMIC(Opcode opcode, Register dst, AddressSpace space, Tuple src);
> +  /*! atomic_add dst addr.space src1 */
> +  Instruction ATOMIC_ADD(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_sub dst addr.space src1 */
> +  Instruction ATOMIC_SUB(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_and dst addr.space src1 */
> +  Instruction ATOMIC_AND(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_or dst addr.space src1 */
> +  Instruction ATOMIC_OR(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_xor dst addr.space src1 */
> +  Instruction ATOMIC_XOR(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_xchg dst addr.space src1 */
> +  Instruction ATOMIC_XCHG(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_imin dst addr.space src1 */
> +  Instruction ATOMIC_IMIN(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_imax dst addr.space src1 */
> +  Instruction ATOMIC_IMAX(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_umin dst addr.space src1 */
> +  Instruction ATOMIC_UMIN(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_umax dst addr.space src1 */
> +  Instruction ATOMIC_UMAX(Register dst, Register addr, AddressSpace space, Register src1);
> +  /*! atomic_inc dst addr.space */
> +  Instruction ATOMIC_INC(Register dst, Register addr, AddressSpace space);
> +  /*! atomic_dec dst addr.space */
> +  Instruction ATOMIC_DEC(Register dst, Register addr, AddressSpace space);
> +  /*! atomic_cmpxchg dst addr.space src1 src2 */
> +  Instruction ATOMIC_CMPXCHG(Register dst, Register addr, AddressSpace space, Register src1, Register src2);

It seems you not really use the above ATOMIC_XXX instruction at IR/llvm level.
You only use the ATOMIC instruction, and the above ATOMIC_XXX definitions and
the following DECL_INSN(ATOMIC_XXX,...) only provide the valid OP_ATOMIC_XXX
definitions. Right? I'd prefer not to define so many ATOMIC_XXX instructions.
Just define those OP_ATOMIC_XXX code in instructions.hpp's AtomicInstruction
scope directly. Then we only need to add one ATOMIC instruction in the IR layer.
Any thoughts?

- Zhigang

>    /*! bra labelIndex */
>    Instruction BRA(LabelIndex labelIndex);
>    /*! (pred) bra labelIndex */
> diff --git a/backend/src/ir/instruction.hxx b/backend/src/ir/instruction.hxx
> index 5cf37d2..a8d1665 100644
> --- a/backend/src/ir/instruction.hxx
> +++ b/backend/src/ir/instruction.hxx
> @@ -61,6 +61,19 @@ DECL_INSN(LT, CompareInstruction)
>  DECL_INSN(GE, CompareInstruction)
>  DECL_INSN(GT, CompareInstruction)
>  DECL_INSN(CVT, ConvertInstruction)
> +DECL_INSN(ATOMIC_ADD, AtomicInstruction)
> +DECL_INSN(ATOMIC_SUB, AtomicInstruction)
> +DECL_INSN(ATOMIC_AND, AtomicInstruction)
> +DECL_INSN(ATOMIC_OR, AtomicInstruction)
> +DECL_INSN(ATOMIC_XOR, AtomicInstruction)
> +DECL_INSN(ATOMIC_XCHG, AtomicInstruction)
> +DECL_INSN(ATOMIC_UMIN, AtomicInstruction)
> +DECL_INSN(ATOMIC_UMAX, AtomicInstruction)
> +DECL_INSN(ATOMIC_IMIN, AtomicInstruction)
> +DECL_INSN(ATOMIC_IMAX, AtomicInstruction)
> +DECL_INSN(ATOMIC_INC, AtomicInstruction)
> +DECL_INSN(ATOMIC_DEC, AtomicInstruction)
> +DECL_INSN(ATOMIC_CMPXCHG, AtomicInstruction)
>  DECL_INSN(BRA, BranchInstruction)
>  DECL_INSN(RET, BranchInstruction)
>  DECL_INSN(LOADI, LoadImmInstruction)
> -- 
> 1.7.10.4
> 
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet


More information about the Beignet mailing list