[Beignet] [PATCH OCL2.0 2/3] Backend: Add Pipe Builtin support

Pan Xiuli xiuli.pan at intel.com
Tue Jan 26 00:21:42 PST 2016


Add pipe builtin functions

Signed-off-by: Pan Xiuli <xiuli.pan at intel.com>
---
 backend/src/backend/context.cpp            |   5 +
 backend/src/backend/gen_reg_allocation.cpp |   3 +-
 backend/src/backend/program.h              |   1 +
 backend/src/ir/function.cpp                |   1 +
 backend/src/ir/function.hpp                |   9 +-
 backend/src/libocl/CMakeLists.txt          |   2 +-
 backend/src/libocl/include/ocl.h           |   1 +
 backend/src/libocl/include/ocl_pipe.h      |  51 +++++
 backend/src/libocl/src/ocl_pipe.cl         | 296 +++++++++++++++++++++++++++++
 backend/src/llvm/llvm_gen_backend.cpp      |  61 +++++-
 backend/src/llvm/llvm_gen_ocl_function.hxx |   5 +
 src/cl_command_queue.c                     |   2 +-
 src/cl_kernel.c                            |   5 +-
 13 files changed, 427 insertions(+), 15 deletions(-)
 create mode 100644 backend/src/libocl/include/ocl_pipe.h
 create mode 100644 backend/src/libocl/src/ocl_pipe.cl

diff --git a/backend/src/backend/context.cpp b/backend/src/backend/context.cpp
index 9236022..40b744f 100644
--- a/backend/src/backend/context.cpp
+++ b/backend/src/backend/context.cpp
@@ -466,6 +466,11 @@ namespace gbe
           kernel->args[argID].type = GBE_ARG_SAMPLER;
           kernel->args[argID].size = sizeof(void*);
           break;
+        case ir::FunctionArgument::PIPE:
+          kernel->args[argID].type = GBE_ARG_PIPE;
+          kernel->args[argID].size = sizeof(void*);
+          kernel->args[argID].bti = arg.bti;
+          break;
       }
     }
   }
diff --git a/backend/src/backend/gen_reg_allocation.cpp b/backend/src/backend/gen_reg_allocation.cpp
index a9338c5..9339f0f 100644
--- a/backend/src/backend/gen_reg_allocation.cpp
+++ b/backend/src/backend/gen_reg_allocation.cpp
@@ -1310,7 +1310,8 @@ namespace gbe
       const ir::FunctionArgument &arg = this->opaque->ctx.getFunction().getArg(subType);
       if (arg.type == ir::FunctionArgument::GLOBAL_POINTER ||
           arg.type == ir::FunctionArgument::LOCAL_POINTER  ||
-          arg.type == ir::FunctionArgument::CONSTANT_POINTER)
+          arg.type == ir::FunctionArgument::CONSTANT_POINTER||
+          arg.type == ir::FunctionArgument::PIPE)
         regSize = this->opaque->ctx.getPointerSize();
       else
         regSize = arg.size;
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index f6176db..1c0cfae 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -50,6 +50,7 @@ enum gbe_arg_type {
   GBE_ARG_LOCAL_PTR = 3,        // __local
   GBE_ARG_IMAGE = 4,            // image2d_t, image3d_t
   GBE_ARG_SAMPLER = 5,          // sampler_t
+  GBE_ARG_PIPE = 6,             // pipe
   GBE_ARG_INVALID = 0xffffffff
 };
 
diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp
index 00fe97c..f09cbe3 100644
--- a/backend/src/ir/function.cpp
+++ b/backend/src/ir/function.cpp
@@ -321,6 +321,7 @@ namespace ir {
           out << "structure." << input.size;
         break;
         case FunctionArgument::IMAGE: out << "image"; break;
+        case FunctionArgument::PIPE: out << "pipe"; break;
         default: break;
       }
       out << " %" << input.reg << " " << input.name << std::endl;
diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp
index ba589a3..4b076e6 100644
--- a/backend/src/ir/function.hpp
+++ b/backend/src/ir/function.hpp
@@ -170,8 +170,9 @@ namespace ir {
       LOCAL_POINTER     = 2, // __local
       VALUE             = 3, // int, float
       STRUCTURE         = 4, // struct foo
-      IMAGE             = 5,  // image*d_t
-      SAMPLER           = 6
+      IMAGE             = 5, // image*d_t
+      SAMPLER           = 6,
+      PIPE              = 7  // pipe
     };
 
     struct InfoFromLLVM { // All the info about passed by llvm, using -cl-kernel-arg-info
@@ -209,6 +210,10 @@ namespace ir {
         return typeName.compare("sampler_t") == 0;
       }
 
+      bool isPipeType() const {
+        return typeQual.compare("pipe") == 0;
+      }
+
     };
 
     /*! Create a function input argument */
diff --git a/backend/src/libocl/CMakeLists.txt b/backend/src/libocl/CMakeLists.txt
index 8bb4c1e..f17400a 100644
--- a/backend/src/libocl/CMakeLists.txt
+++ b/backend/src/libocl/CMakeLists.txt
@@ -53,7 +53,7 @@ FOREACH(M ${OCL_COPY_HEADERS})
 ENDFOREACH(M) 
 
 SET (OCL_COPY_MODULES ocl_workitem ocl_atom ocl_async ocl_sync ocl_memcpy
-                      ocl_memset ocl_misc ocl_vload ocl_geometric ocl_image ocl_work_group)
+                      ocl_memset ocl_misc ocl_vload ocl_geometric ocl_image ocl_work_group ocl_pipe)
 FOREACH(M ${OCL_COPY_MODULES})
     COPY_THE_HEADER(${M})
     COPY_THE_SOURCE(${M})
diff --git a/backend/src/libocl/include/ocl.h b/backend/src/libocl/include/ocl.h
index abb2bd4..e2918c6 100644
--- a/backend/src/libocl/include/ocl.h
+++ b/backend/src/libocl/include/ocl.h
@@ -40,6 +40,7 @@
 #include "ocl_workitem.h"
 #include "ocl_simd.h"
 #include "ocl_work_group.h"
+#include "ocl_pipe.h"
 #pragma OPENCL EXTENSION cl_khr_fp64 : disable
 #pragma OPENCL EXTENSION cl_khr_fp16 : disable
 #endif
diff --git a/backend/src/libocl/include/ocl_pipe.h b/backend/src/libocl/include/ocl_pipe.h
new file mode 100644
index 0000000..349b1dd
--- /dev/null
+++ b/backend/src/libocl/include/ocl_pipe.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2012 - 2014 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef __OCL_PIPE_H__
+#define __OCL_PIPE_H__
+
+#include "ocl_types.h"
+#include "ocl_work_group.h"
+#include "ocl_simd.h"
+
+/* The pipe read function. */
+int __read_pipe_2(pipe int p, __generic void* dst);
+int __read_pipe_4(pipe int p, reserve_id_t id, uint index, void* dst);
+reserve_id_t __reserve_read_pipe(pipe int p, uint num);
+void __commit_read_pipe(pipe int p, reserve_id_t rid);
+reserve_id_t __work_group_reserve_read_pipe(pipe int p, uint num);
+void __work_group_commit_read_pipe(pipe int p, reserve_id_t rid);
+reserve_id_t __sub_group_reserve_read_pipe(pipe int p, uint num);
+void __sub_group_commit_read_pipe(pipe int p, reserve_id_t rid);
+
+/* The pipe write function. */
+int __write_pipe_2(pipe int p, __generic void* src);
+int __write_pipe_4(pipe int p, reserve_id_t id, uint index, void* src);
+reserve_id_t __reserve_write_pipe(pipe int p, uint num);
+void __commit_write_pipe(pipe int p, reserve_id_t rid);
+reserve_id_t __work_group_reserve_write_pipe(pipe int p, uint num);
+void __work_group_commit_write_pipe(pipe int p, reserve_id_t rid);
+reserve_id_t __sub_group_reserve_write_pipe(pipe int p, uint num);
+void __sub_group_commit_write_pipe(pipe int p, reserve_id_t rid);
+
+/* The reserve_id_t function. */
+bool is_valid_reserve_id(reserve_id_t rid);
+
+/* The pipe query function. */
+uint __get_pipe_num_packets(pipe int p);
+uint __get_pipe_max_packets(pipe int p);
+#endif
diff --git a/backend/src/libocl/src/ocl_pipe.cl b/backend/src/libocl/src/ocl_pipe.cl
new file mode 100644
index 0000000..7bfd370
--- /dev/null
+++ b/backend/src/libocl/src/ocl_pipe.cl
@@ -0,0 +1,296 @@
+/*
+ * Copyright © 2012 - 2014 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "ocl_pipe.h"
+#include "ocl_atom.h"
+#include "ocl_workitem.h"
+
+#define PIPE_SUCCESS 0
+#define PIPE_EMPTY -2
+#define PIPE_FULL -3
+#define PIPE_HEADER_SZ 128
+#define PIPE_INDEX_OUTRANGE -4
+#define PIPE_RESERVE_FAIL -5
+#define RID_MAGIC 0xDE
+#define RIDT ushort
+#define DEAD_PTR 0xFFFFFFFF
+
+PURE CONST __global void* __gen_ocl_get_pipe(pipe int p);
+PURE CONST ulong __gen_ocl_get_rid(reserve_id_t rid);
+PURE CONST reserve_id_t __gen_ocl_make_rid(ulong rid);
+
+int __read_pipe_2(pipe int p, __generic void* dst)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int data_size = atomic_sub(pheader + 6, 1);
+  if(data_size < 0){
+    atomic_add(pheader + 6, 1);
+    return PIPE_EMPTY; //Check if element exist
+  }
+  __global char* psrc = (__global char*)pheader + PIPE_HEADER_SZ;
+  int pack_num = pheader[0];
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int read_ptr = atomic_add(pheader + 3, 1);
+  if(read_ptr == pack_num - 1)
+    atomic_sub(pheader + 3, pack_num);
+  read_ptr = read_ptr % pack_num;
+  for(int i = 0; i < pack_size ; i++)
+    ((char*)dst)[i] = psrc[i + read_ptr*pack_size];
+  return 0;
+}
+
+int __read_pipe_4(pipe int p, reserve_id_t id, uint index, void* dst)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  __global char* psrc = (__global char*)pheader + PIPE_HEADER_SZ;
+  ulong uid = __gen_ocl_get_rid(id);
+  RIDT* pid = (RIDT*)&uid;
+  RIDT start_pt = pid[0];
+  RIDT reserve_size = pid[1];
+  if(index > reserve_size) return PIPE_INDEX_OUTRANGE;
+  int pack_num = pheader[0];
+  int pack_size = pheader[1];
+  int read_ptr = (start_pt + index) % pack_num;
+  int offset = read_ptr * pack_size;
+  for(int i = 0; i < pack_size ; i++)
+    ((char*)dst)[i] = psrc[i + offset];
+  return 0;
+}
+
+
+int __write_pipe_2(pipe int p, __generic void* src)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int pack_num = pheader[0];
+  int data_size = atomic_add(pheader + 6, 1);
+  if(data_size >= pack_num){
+    atomic_sub(pheader + 6, 1);
+    return PIPE_FULL; //Check if pipe full
+  }
+  __global char* psrc = (__global char*)pheader + PIPE_HEADER_SZ;
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int write_ptr = atomic_add(pheader + 2, 1);
+  if(write_ptr == pack_num - 1)
+    atomic_sub(pheader + 2, pack_num);
+  write_ptr = write_ptr % pack_num;
+  for(int i = 0; i < pack_size ; i++)
+    psrc[i + write_ptr * pack_size] = ((char*)src)[i];
+  return 0;
+}
+
+int __write_pipe_4(pipe int p, reserve_id_t id, uint index, void* src)
+{
+  __global int* pheader = __gen_ocl_get_pipe(p);
+  __global char* psrc = (__global char*)pheader + PIPE_HEADER_SZ;
+  ulong uid = __gen_ocl_get_rid(id);
+  RIDT* pid = (RIDT*)&uid;
+  RIDT start_pt = pid[0];
+  RIDT reserve_size = pid[1];
+  if(index > reserve_size) return PIPE_INDEX_OUTRANGE;
+  int pack_num = pheader[0];
+  int pack_size = pheader[1];
+  int write_ptr = (start_pt + index) % pack_num;
+  int offset = write_ptr * pack_size;
+  for(int i = 0; i < pack_size ; i++)
+    psrc[i + offset] = ((char*)src)[i];
+  return pack_size;
+}
+
+reserve_id_t __reserve_read_pipe(pipe int p, uint num)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int data_size = atomic_sub(pheader + 6, num);
+  if(data_size < num){
+    atomic_add(pheader + 6, num);
+    return __gen_ocl_make_rid(0l);
+  }
+  int pack_num = pheader[0];
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int read_ptr = atomic_add(pheader + 3, num);
+  if(read_ptr == pack_num - num)
+    atomic_sub(pheader + 3, pack_num);
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  pid[0] = read_ptr % pack_num;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  return __gen_ocl_make_rid(uid);
+}
+
+void __commit_read_pipe(pipe int p, reserve_id_t rid) {}
+
+reserve_id_t __work_group_reserve_read_pipe(pipe int p, uint num)
+{
+  uint rid_ptr = DEAD_PTR;
+  int ret0 = 0;
+  if(get_local_linear_id()==0){
+    __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+    int data_size = atomic_sub(pheader + 6, num);
+    if(data_size < num){
+      atomic_add(pheader + 6, num);
+      int ret0 = 1;
+    }
+    int pack_num = pheader[0];
+    int pack_size = pheader[1];
+    int pipe_size = pack_num * pack_size;
+    int read_ptr = atomic_add(pheader + 3, num);
+    if(read_ptr == pack_num - num && !ret0)
+      atomic_sub(pheader + 3, pack_num);
+    if(!ret0)
+      rid_ptr = read_ptr % pack_num;
+  }
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  rid_ptr = work_group_broadcast(rid_ptr,0,0,0);
+  pid[0] = rid_ptr;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  if(rid_ptr == DEAD_PTR)
+    uid = 0l;
+  return __gen_ocl_make_rid(uid);
+}
+
+void __work_group_commit_read_pipe(pipe int p, reserve_id_t rid) {}
+
+reserve_id_t __sub_group_reserve_read_pipe(pipe int p, uint num)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int data_size = atomic_sub(pheader + 6, num);
+  if(data_size < num){
+    atomic_add(pheader + 6, num);
+    return __gen_ocl_make_rid(0l);
+  }
+  int pack_num = pheader[0];
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int read_ptr = atomic_add(pheader + 3, num);
+  if(read_ptr == pack_num - num)
+    atomic_sub(pheader + 3, pack_num);
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  pid[0] = read_ptr % pack_num;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  return __gen_ocl_make_rid(uid);
+}
+
+void __sub_group_commit_read_pipe(pipe int p, reserve_id_t rid) {}
+
+reserve_id_t __reserve_write_pipe(pipe int p, uint num)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int pack_num = pheader[0];
+  int data_size = atomic_add(pheader + 6, num);
+  if(data_size > pack_num - num){
+    atomic_sub(pheader + 6, num);
+    return __gen_ocl_make_rid(0l);
+  }
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int write_ptr = atomic_add(pheader + 2, num);
+  if(write_ptr == pack_num - num)
+    atomic_sub(pheader + 2, pack_num);
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  pid[0] = write_ptr % pack_num;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  return __gen_ocl_make_rid(uid);
+}
+void __commit_write_pipe(pipe int p, reserve_id_t rid) {}
+
+reserve_id_t __work_group_reserve_write_pipe(pipe int p, uint num)
+{
+  uint rid_ptr = DEAD_PTR;
+  int ret0 = 0;
+  if(get_local_linear_id()==0){
+    __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+    int pack_num = pheader[0];
+    int data_size = atomic_add(pheader + 6, num);
+    if(data_size > pack_num - num){
+      atomic_sub(pheader + 6, num);
+      ret0 = 1;
+    }
+    int pack_size = pheader[1];
+    int pipe_size = pack_num * pack_size;
+    int write_ptr = atomic_add(pheader + 2, num);
+    if(write_ptr == pack_num - num && !ret0)
+      atomic_sub(pheader + 2, pack_num);
+    if(!ret0)
+      rid_ptr = write_ptr % pack_num;
+  }
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  rid_ptr = work_group_broadcast(rid_ptr,0,0,0);
+  pid[0] = rid_ptr;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  if(rid_ptr == DEAD_PTR)
+    uid = 0l;
+  return __gen_ocl_make_rid(uid);
+}
+void __work_group_commit_write_pipe(pipe int p, reserve_id_t rid) {}
+
+
+reserve_id_t __sub_group_reserve_write_pipe(pipe int p, uint num)
+{
+  __global int* pheader = (__global int*)__gen_ocl_get_pipe(p);
+  int pack_num = pheader[0];
+  int data_size = atomic_add(pheader + 6, num);
+  if(data_size > pack_num - num){
+    atomic_sub(pheader + 6, num);
+    return __gen_ocl_make_rid(0l);
+  }
+  int pack_size = pheader[1];
+  int pipe_size = pack_num * pack_size;
+  int write_ptr = atomic_add(pheader + 2, num);
+  if(write_ptr == pack_num - num)
+    atomic_sub(pheader + 2, pack_num);
+  ulong uid = 0l;
+  RIDT* pid = (RIDT*)&uid;
+  pid[0] = write_ptr % pack_num;
+  pid[1] = num;
+  pid[2] = RID_MAGIC ;
+  return __gen_ocl_make_rid(uid);
+}
+
+void __sub_group_commit_write_pipe(pipe int p, reserve_id_t rid) {}
+
+bool is_valid_reserve_id(reserve_id_t rid)
+{
+  ulong uid = __gen_ocl_get_rid(rid);
+  RIDT* pid = (RIDT*)&uid;
+  if(pid[1] == 0) return false;
+  if(pid[2] != RID_MAGIC) return false;
+  return true;
+}
+
+/* Query Function */
+uint __get_pipe_max_packets(pipe int p)
+{
+  __global int* pheader = __gen_ocl_get_pipe(p);
+  return pheader[0];
+}
+
+uint __get_pipe_num_packets(pipe int p)
+{
+  __global int* pheader = __gen_ocl_get_pipe(p);
+  return pheader[6];
+}
diff --git a/backend/src/llvm/llvm_gen_backend.cpp b/backend/src/llvm/llvm_gen_backend.cpp
index 93a2833..874206b 100644
--- a/backend/src/llvm/llvm_gen_backend.cpp
+++ b/backend/src/llvm/llvm_gen_backend.cpp
@@ -843,12 +843,25 @@ namespace gbe
         visited.insert(theUser);
 
         if (isa<LoadInst>(theUser) || isa<StoreInst>(theUser) || isa<CallInst>(theUser)) {
+          Value *pointer = NULL;
           if (isa<CallInst>(theUser)) {
             Function *F = dyn_cast<CallInst>(theUser)->getCalledFunction();
-            if (!F || F->getIntrinsicID() != 0) continue;
+            if(!F) continue;
+            // get pipe function to convert pipe to ptr
+            const std::string fnName = F->getName();
+            auto genIntrinsicID = intrinsicMap.find(fnName);
+            if(genIntrinsicID == GEN_OCL_GET_PIPE){
+              pointer = theUser;
+              revisit.push_back(theUser);
+            }
+            else if (F->getIntrinsicID() != 0) continue;
+            else{
+              // atomic/read(write)image
+              CallInst *ci = dyn_cast<CallInst>(theUser);
+              pointer = ci->getArgOperand(0);
+            }
           }
-          Value *pointer = NULL;
-          if (isa<LoadInst>(theUser)) {
+          else if (isa<LoadInst>(theUser)) {
             ptrCandidate.insert(cast<LoadInst>(theUser));
             pointer = dyn_cast<LoadInst>(theUser)->getPointerOperand();
           } else if (isa<StoreInst>(theUser)) {
@@ -858,10 +871,6 @@ namespace gbe
             if (addrStoreInst.find(theUser) != addrStoreInst.end()) {
               isPointerArray = true;
             }
-          } else if (isa<CallInst>(theUser)) {
-            // atomic/read(write)image
-            CallInst *ci = dyn_cast<CallInst>(theUser);
-            pointer = ci->getArgOperand(0);
           } else {
             theUser->dump();
             GBE_ASSERT(0 && "Unknown instruction operating on pointers\n");
@@ -1150,6 +1159,7 @@ namespace gbe
       BtiMap.insert(std::make_pair(&v, getNewBti(&v, false)));
     }
     MDNode *typeNameNode = NULL;
+    MDNode *typeQualNode = NULL;
     MDNode *node = getKernelFunctionMetadata(&F);
     for(uint j = 0; j < node->getNumOperands() - 1; j++) {
       MDNode *attrNode = dyn_cast_or_null<MDNode>(node->getOperand(1 + j));
@@ -1158,6 +1168,8 @@ namespace gbe
       if (!attrName) continue;
       if (attrName->getString() == "kernel_arg_type") {
         typeNameNode = attrNode;
+      } else if (attrName->getString() == "kernel_arg_type_qual") {
+        typeQualNode = attrNode;
       }
     }
 
@@ -1165,9 +1177,11 @@ namespace gbe
     ir::FunctionArgument::InfoFromLLVM llvmInfo;
     for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, argID++) {
       llvmInfo.typeName= (cast<MDString>(typeNameNode->getOperand(1 + argID)))->getString();
+      llvmInfo.typeQual = (cast<MDString>(typeQualNode->getOperand(1 + argID)))->getString();
       bool isImage = llvmInfo.isImageType();
-      if (I->getType()->isPointerTy() || isImage) {
-        BtiMap.insert(std::make_pair(&*I, getNewBti(&*I, isImage)));
+      bool isPipe = llvmInfo.isPipeType();
+      if (I->getType()->isPointerTy() || isImage || isPipe) {
+        BtiMap.insert(std::make_pair(&*I, getNewBti(&*I, isImage || isPipe)));
       }
     }
 
@@ -1262,6 +1276,7 @@ namespace gbe
   }
 
   void GenWriter::analyzePointerOrigin(Function &F) {
+
     // used to record where the pointers get mixed (i.e. select or phi instruction)
     std::set<Value *> mixedPtr;
     // This is a two-pass algorithm, the 1st pass will try to update the pointer sources for
@@ -2024,6 +2039,10 @@ namespace gbe
           (void)ctx.getFunction().getSamplerSet()->append(reg, &ctx);
           continue;
         }
+        if(llvmInfo.isPipeType()) {
+          ctx.input(argName, ir::FunctionArgument::PIPE, reg, llvmInfo, 4, 4, BtiMap.find(&*I)->second);
+          continue;
+        }
 
         if (type->isPointerTy() == false)
           ctx.input(argName, ir::FunctionArgument::VALUE, reg, llvmInfo, getTypeByteSize(unit, type), getAlignmentByte(unit, type), 0);
@@ -3602,6 +3621,24 @@ namespace gbe
       case GEN_OCL_WORK_GROUP_SCAN_INCLUSIVE_MIN:
         this->newRegister(&I);
         break;
+      case GEN_OCL_GET_PIPE:
+      {
+        Value *srcValue = I.getOperand(0);
+        if( BtiMap.find(dst) == BtiMap.end())
+        {
+          unsigned tranBti = BtiMap.find(srcValue)->second;
+          BtiMap.insert(std::make_pair(dst, tranBti));
+        }
+        regTranslator.newValueProxy(srcValue, dst);
+        break;
+      }
+      case GEN_OCL_MAKE_RID:
+      case GEN_OCL_GET_RID:
+      {
+        Value *srcValue = I.getOperand(0);
+        regTranslator.newValueProxy(srcValue, dst);
+        break;
+      }
       case GEN_OCL_PRINTF:
         break;
       case GEN_OCL_NOT_FOUND:
@@ -4412,6 +4449,12 @@ namespace gbe
             this->emitWorkGroupInst(I, CS, ir::WORKGROUP_OP_INCLUSIVE_MAX); break;
           case GEN_OCL_WORK_GROUP_SCAN_INCLUSIVE_MIN:
             this->emitWorkGroupInst(I, CS, ir::WORKGROUP_OP_INCLUSIVE_MIN); break;
+          case GEN_OCL_GET_PIPE:
+          case GEN_OCL_MAKE_RID:
+          case GEN_OCL_GET_RID:
+          {
+            break;
+          }
           default: break;
         }
       }
diff --git a/backend/src/llvm/llvm_gen_ocl_function.hxx b/backend/src/llvm/llvm_gen_ocl_function.hxx
index 0849f1e..a360d81 100644
--- a/backend/src/llvm/llvm_gen_ocl_function.hxx
+++ b/backend/src/llvm/llvm_gen_ocl_function.hxx
@@ -188,3 +188,8 @@ DECL_LLVM_GEN_FUNCTION(WORK_GROUP_SCAN_INCLUSIVE_MIN, __gen_ocl_work_group_scan_
 
 DECL_LLVM_GEN_FUNCTION(WORK_GROUP_ALL, __gen_ocl_work_group_all)
 DECL_LLVM_GEN_FUNCTION(WORK_GROUP_ANY, __gen_ocl_work_group_any)
+
+// pipe function
+DECL_LLVM_GEN_FUNCTION(GET_PIPE, __gen_ocl_get_pipe)
+DECL_LLVM_GEN_FUNCTION(GET_RID, __gen_ocl_get_rid)
+DECL_LLVM_GEN_FUNCTION(MAKE_RID, __gen_ocl_make_rid)
diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 9dc3fe6..b59d459 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -161,7 +161,7 @@ cl_command_queue_bind_surface(cl_command_queue queue, cl_kernel k)
   for (i = 0; i < k->arg_n; ++i) {
     int32_t offset; // location of the address in the curbe
     arg_type = interp_kernel_get_arg_type(k->opaque, i);
-    if (arg_type != GBE_ARG_GLOBAL_PTR || !k->args[i].mem)
+    if ((arg_type != GBE_ARG_GLOBAL_PTR && arg_type != GBE_ARG_PIPE)|| !k->args[i].mem)
       continue;
     offset = interp_kernel_get_curbe_offset(k->opaque, GBE_CURBE_KERNEL_ARGUMENT, i);
     if (offset < 0)
diff --git a/src/cl_kernel.c b/src/cl_kernel.c
index 723eac3..abbabbd 100644
--- a/src/cl_kernel.c
+++ b/src/cl_kernel.c
@@ -136,7 +136,8 @@ cl_kernel_set_arg(cl_kernel k, cl_uint index, size_t sz, const void *value)
       return CL_INVALID_SAMPLER;
   } else {
     // should be image, GLOBAL_PTR, CONSTANT_PTR
-    if (UNLIKELY(value == NULL && arg_type == GBE_ARG_IMAGE))
+    if (UNLIKELY(value == NULL && (arg_type == GBE_ARG_IMAGE ||
+            arg_type == GBE_ARG_PIPE)))
       return CL_INVALID_ARG_VALUE;
     if(value != NULL)
       mem = *(cl_mem*)value;
@@ -331,6 +332,8 @@ cl_get_kernel_arg_info(cl_kernel k, cl_uint arg_index, cl_kernel_arg_info param_
       type_qual = type_qual | CL_KERNEL_ARG_TYPE_VOLATILE;
     if (strstr((char*)ret_info, "restrict"))
       type_qual = type_qual | CL_KERNEL_ARG_TYPE_RESTRICT;
+    if (strstr((char*)ret_info, "pipe"))
+      type_qual = CL_KERNEL_ARG_TYPE_PIPE;
     *(cl_kernel_arg_type_qualifier *)param_value = type_qual;
     return CL_SUCCESS;
 
-- 
2.5.0



More information about the Beignet mailing list