Quellcode durchsuchen

gcc: opencl: Generate the `clSetKernelArg' calls.

* gcc-plugin/src/starpu.c (build_opencl_set_kernel_arg_call,
  build_opencl_set_kernel_arg_calls): New functions.
  (define_opencl_task_implementation): Move initialization of
  `DECL_ARGUMENTS (task_impl)' above.  Append the result of
  `build_opencl_set_kernel_arg_calls'.

* gcc-plugin/tests/mocks.h (clSetKernelArg)[!STARPU_USE_OPENCL]: New
  declaration.
  (opencl_set_kernel_arg_calls): New variable.
  (clSetKernelArg, starpu_opencl_error_string): New functions.

* gcc-plugin/tests/opencl.c (main): Check OPENCL_SET_KERNEL_ARG_CALLS.
Ludovic Courtès vor 13 Jahren
Ursprung
Commit
35c287decd
3 geänderte Dateien mit 130 neuen und 4 gelöschten Zeilen
  1. 81 2
      gcc-plugin/src/starpu.c
  2. 48 2
      gcc-plugin/tests/mocks.h
  3. 1 0
      gcc-plugin/tests/opencl.c

+ 81 - 2
gcc-plugin/src/starpu.c

@@ -1185,6 +1185,80 @@ opencl_event_type (void)
   return t;
 }
 
+/* Return an error-checking `clSetKernelArg' call for argument ARG, at
+   index IDX, of KERNEL.  */
+
+static tree
+build_opencl_set_kernel_arg_call (location_t loc, tree fn,
+				  tree kernel, unsigned int idx,
+				  tree arg)
+{
+  gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
+	      && TREE_TYPE (kernel) == opencl_kernel_type ());
+
+  static tree setkernarg_fn, clstrerror_fn;
+  LOOKUP_STARPU_FUNCTION (setkernarg_fn, "clSetKernelArg");
+  LOOKUP_STARPU_FUNCTION (clstrerror_fn, "starpu_opencl_error_string");
+
+  local_define (tree, build_errorstr, (tree error_var))
+  {
+    return build_call_expr (clstrerror_fn, 1, error_var);
+  };
+
+  tree call = build_call_expr (setkernarg_fn, 4, kernel,
+			       build_int_cst (integer_type_node, idx),
+			       size_in_bytes (TREE_TYPE (arg)),
+			       build_addr (arg, fn));
+  tree error_var = build_decl (loc, VAR_DECL,
+			       create_tmp_var_name ("setkernelarg_error"),
+			       integer_type_node);
+  DECL_ARTIFICIAL (error_var) = true;
+  DECL_CONTEXT (error_var) = fn;
+
+  tree assignment = build2 (INIT_EXPR, TREE_TYPE (error_var),
+			    error_var, call);
+
+  /* Build `if (ERROR_VAR != 0) error ();'.  */
+  tree cond;
+  cond = build3 (COND_EXPR, void_type_node,
+		 build2 (NE_EXPR, boolean_type_node,
+			 error_var, integer_zero_node),
+		 build_error_statements (loc, error_var, build_errorstr,
+					 "failed to set OpenCL kernel "
+					 "argument %d", idx),
+		 NULL_TREE);
+
+  tree stmts = NULL_TREE;
+  append_to_statement_list (assignment, &stmts);
+  append_to_statement_list (cond, &stmts);
+
+  return build4 (TARGET_EXPR, void_type_node, error_var,
+		 stmts, NULL_TREE, NULL_TREE);
+}
+
+/* Return the sequence of `clSetKernelArg' calls for KERNEL.  */
+
+static tree
+build_opencl_set_kernel_arg_calls (location_t loc, tree task_impl,
+				   tree kernel)
+{
+  gcc_assert (task_implementation_p (task_impl));
+
+  size_t n;
+  tree arg, stmts = NULL_TREE;
+
+  for (arg = DECL_ARGUMENTS (task_impl), n = 0;
+       arg != NULL_TREE;
+       arg = TREE_CHAIN (arg), n++)
+    {
+      tree call = build_opencl_set_kernel_arg_call (loc, task_impl,
+						    kernel, n, arg);
+      append_to_statement_list (call, &stmts);
+    }
+
+  return stmts;
+}
+
 /* Define a body for TASK_IMPL that loads OpenCL source from FILE and calls
    KERNEL.  */
 
@@ -1237,6 +1311,9 @@ define_opencl_task_implementation (location_t loc, tree task_impl,
 						  file, opencl_include_dirs);
   if (source_var != NULL_TREE)
     {
+      /* Give TASK_IMPL an actual argument list.  */
+      DECL_ARGUMENTS (task_impl) = build_function_arguments (task_impl);
+
       tree prog_var, prog_loaded_var;
 
       /* Global variable to hold the `starpu_opencl_program' object.  */
@@ -1312,6 +1389,10 @@ define_opencl_task_implementation (location_t loc, tree task_impl,
       tree stmts = NULL_TREE;
       append_to_statement_list (load_cond, &stmts);
       append_to_statement_list (load_kern, &stmts);
+      append_to_statement_list (build_opencl_set_kernel_arg_calls (loc,
+								   task_impl,
+								   kernel_var),
+				&stmts);
 
       /* Bind the local vars.  */
       tree vars = chain_trees (kernel_var, queue_var, event_var,
@@ -1327,8 +1408,6 @@ define_opencl_task_implementation (location_t loc, tree task_impl,
       DECL_INITIAL (task_impl) = BIND_EXPR_BLOCK (bind);
       DECL_RESULT (task_impl) =
 	build_decl (loc, RESULT_DECL, NULL_TREE, void_type_node);
-      DECL_ARGUMENTS (task_impl) =
-	build_function_arguments (task_impl);
 
       /* Compile TASK_IMPL.  */
       rest_of_decl_compilation (task_impl, true, 0);

+ 48 - 2
gcc-plugin/tests/mocks.h

@@ -438,11 +438,15 @@ typedef int cl_event;
 typedef int cl_kernel;
 typedef int cl_command_queue;
 
+extern cl_int clSetKernelArg (cl_kernel, cl_uint, size_t, const void *);
+
 #endif
 
 
-/* Number of `load_opencl_from_string' and `load_kernel' calls.  */
-static unsigned int load_opencl_calls, load_opencl_kernel_calls;
+/* Number of `load_opencl_from_string', `load_kernel', and `clSetKernelArg'
+   calls.  */
+static unsigned int load_opencl_calls, load_opencl_kernel_calls,
+  opencl_set_kernel_arg_calls;
 
 struct load_opencl_arguments
 {
@@ -488,6 +492,48 @@ starpu_worker_get_devid (int id)
   return -id;
 }
 
+/* Set the INDEXth argument to KERNEL to the SIZE bytes pointed to by
+   VALUE.  */
+cl_int
+clSetKernelArg (cl_kernel kernel, cl_uint index, size_t size,
+		const void *value)
+{
+  size_t n;
+  const struct insert_task_argument *arg;
+
+  for (n = 0, arg = expected_insert_task_arguments;
+       n < index;
+       n++, arg++)
+    assert (arg->pointer != NULL);
+
+  switch (arg->type)
+    {
+    case STARPU_VALUE:
+      assert (size == arg->size);
+      assert (memcmp (arg->pointer, value, size) == 0);
+      break;
+
+    case STARPU_RW:
+    case STARPU_R:
+    case STARPU_W:
+      assert (size == sizeof (void *));
+      assert (* (void **) value == arg->pointer);
+      break;
+
+    default:
+      abort ();
+    }
+
+  opencl_set_kernel_arg_calls++;
+  return 0;
+}
+
+const char *
+starpu_opencl_error_string (cl_int s)
+{
+  return "mock";
+}
+
 
 /* Initialization.  */
 

+ 1 - 0
gcc-plugin/tests/opencl.c

@@ -63,6 +63,7 @@ main ()
   assert (tasks_submitted == 3);
   assert (load_opencl_calls == 1);
   assert (load_opencl_kernel_calls == 3);
+  assert (opencl_set_kernel_arg_calls == 3 * 2);
 
   return EXIT_SUCCESS;
 }