[Beignet] [PATCH 1/4] Add atomic help functions.

Zhigang Gong zhigang.gong at linux.intel.com
Thu Jun 27 03:57:35 PDT 2013


This patchset LGTM, pushed, thanks.

On Thu, Jun 27, 2013 at 04:47:55PM +0800, Yang Rong wrote:
> Use the data port message "Untyped Atomic Operation" to implement openCL atomic functions.
> This message can handle both global memory and SLM.
> For all atomic functions, the operands will be treated as unsigned int, except imax/imin.
> Only add one opcode Atomic for all atomic functions in ir, and identify the atomic function
> by ir::AtomicOps.
> 
> 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         |   44 +++++++++++
>  backend/src/backend/gen_insn_selection.hpp         |    4 +-
>  backend/src/backend/gen_insn_selection.hxx         |    1 +
>  backend/src/ir/instruction.cpp                     |   77 +++++++++++++++++++-
>  backend/src/ir/instruction.hpp                     |   36 ++++++++-
>  backend/src/ir/instruction.hxx                     |    1 +
>  12 files changed, 247 insertions(+), 14 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..3c3ddd8 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); }
> @@ -2015,6 +2036,28 @@ 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 AtomicOps atomicOp = insn.getAtomicOpcode();
> +      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 genAtomicOp = (GenAtomicOpCode)atomicOp;
> +      sel.ATOMIC(dst, genAtomicOp, srcNum, src0, src1, src2, bti);
> +      return true;
> +    }
> +    DECL_CTOR(AtomicInstruction, 1, 1);
> +  };
> +
>    /*! Select instruction pattern */
>    class SelectInstructionPattern : public SelectionPattern
>    {
> @@ -2361,6 +2404,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/instruction.cpp b/backend/src/ir/instruction.cpp
> index a57c204..db47c4d 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,40 @@ namespace ir {
>        Type srcType; //!< Type to convert from
>      };
>  
> +    class ALIGNED_INSTRUCTION AtomicInstruction :
> +      public BasePolicy,
> +      public TupleSrcPolicy<AtomicInstruction>,
> +      public NDstPolicy<AtomicInstruction, 1>
> +    {
> +    public:
> +      AtomicInstruction(AtomicOps atomicOp,
> +                         Register dst,
> +                         AddressSpace addrSpace,
> +                         Tuple src)
> +      {
> +        this->opcode = OP_ATOMIC;
> +        this->atomicOp = atomicOp;
> +        this->dst[0] = dst;
> +        this->src = src;
> +        this->addrSpace = addrSpace;
> +        srcNum = 2;
> +        if((atomicOp == ATOMIC_OP_INC) ||
> +          (atomicOp == ATOMIC_OP_DEC))
> +          srcNum = 1;
> +        if(atomicOp == ATOMIC_OP_CMPXCHG)
> +          srcNum = 3;
> +      }
> +      INLINE AddressSpace getAddressSpace(void) const { return this->addrSpace; }
> +      INLINE AtomicOps getAtomicOpcode(void) const { return this->atomicOp; }
> +      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:2;     //!<Source Number
> +      AtomicOps atomicOp:6;     //!<Source Number
> +    };
> +
>      class ALIGNED_INSTRUCTION BranchInstruction :
>        public BasePolicy,
>        public NDstPolicy<BranchInstruction, 0>
> @@ -738,6 +772,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 +931,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 +1066,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,9 +1241,10 @@ END_FUNCTION(Instruction, Register)
>    }
>  
>    bool Instruction::hasSideEffect(void) const {
> -    return opcode == OP_STORE || 
> +    return opcode == OP_STORE ||
>             opcode == OP_TYPED_WRITE ||
> -           opcode == OP_SYNC;
> +           opcode == OP_SYNC ||
> +           opcode == OP_ATOMIC;
>    }
>  
>  #define DECL_MEM_FN(CLASS, RET, PROTOTYPE, CALL) \
> @@ -1197,6 +1259,8 @@ 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(AtomicInstruction, AtomicOps, getAtomicOpcode(void), getAtomicOpcode())
>  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 +1366,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(AtomicOps atomicOp, Register dst, AddressSpace space, Tuple src) {
> +    return internal::AtomicInstruction(atomicOp, 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..1b2b532 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
> @@ -53,6 +53,23 @@ namespace ir {
>      MEM_INVALID
>    };
>  
> +  enum AtomicOps {
> +    ATOMIC_OP_AND       = 1,
> +    ATOMIC_OP_OR        = 2,
> +    ATOMIC_OP_XOR       = 3,
> +    ATOMIC_OP_XCHG      = 4,
> +    ATOMIC_OP_INC       = 5,
> +    ATOMIC_OP_DEC       = 6,
> +    ATOMIC_OP_ADD       = 7,
> +    ATOMIC_OP_SUB       = 8,
> +    ATOMIC_OP_IMAX      = 10,
> +    ATOMIC_OP_IMIN      = 11,
> +    ATOMIC_OP_UMAX      = 12,
> +    ATOMIC_OP_UMIN      = 13,
> +    ATOMIC_OP_CMPXCHG   = 14,
> +    ATOMIC_OP_INVALID
> +  };
> +
>    /* Vote function per hardware thread */
>    enum VotePredicate : uint8_t {
>      VOTE_ALL = 0,
> @@ -228,6 +245,21 @@ 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 atomic function code */
> +    AtomicOps getAtomicOpcode(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 +583,8 @@ 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(AtomicOps opcode, Register dst, AddressSpace space, Tuple src);
>    /*! 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..c3a0b2f 100644
> --- a/backend/src/ir/instruction.hxx
> +++ b/backend/src/ir/instruction.hxx
> @@ -61,6 +61,7 @@ DECL_INSN(LT, CompareInstruction)
>  DECL_INSN(GE, CompareInstruction)
>  DECL_INSN(GT, CompareInstruction)
>  DECL_INSN(CVT, ConvertInstruction)
> +DECL_INSN(ATOMIC, 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