[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