ソースを参照

gcc: Convert pointers to handles when submitting pointer tasks.

* gcc-plugin/src/starpu.c (data_lookup_fn): New variable.
  (handle_task_attribute)[LOOKUP_STARPU_FUNCTION]: New macro.  Use it.
  Initialize `data_lookup_fn'.
  (build_pointer_lookup): New function.
  (build_task_submission): Use it.

* gcc-plugin/tests/lib.h (starpu_insert_task): For STARPU_[RW]*, make
  sure we have a handle, not a raw data pointer.
  (pointer_as_int, int_as_pointer, dummy_pointer_to_handle,
  dummy_handle_to_pointer): New macros.
  (starpu_data_lookup): Alias for `dummy_pointer_to_handle'.
  (starpu_handle_get_local_ptr): Alias for `dummy_handle_to_pointer'.
Ludovic Courtès 14 年 前
コミット
371b6a739e
共有2 個のファイルを変更した96 個の追加16 個の削除を含む
  1. 67 12
      gcc-plugin/src/starpu.c
  2. 29 4
      gcc-plugin/tests/lib.h

+ 67 - 12
gcc-plugin/src/starpu.c

@@ -63,8 +63,8 @@ static const char task_implementation_wrapper_attribute_name[] =
 static const char codelet_struct_name[] = "starpu_codelet";
 static const char task_struct_name[] = "starpu_task";
 
-/* The `starpu_insert_task' FUNCTION_DECL.  */
-static tree insert_task_fn = NULL_TREE;
+/* The `starpu_insert_task' and `starpu_data_lookup' FUNCTION_DECLs.  */
+static tree insert_task_fn, data_lookup_fn;
 
 
 /* Forward declarations.  */
@@ -282,17 +282,22 @@ handle_task_attribute (tree *node, tree name, tree args,
 
   TREE_USED (fn) = true;
 
-  if (insert_task_fn == NULL_TREE)
-    {
-      /* Lookup the TASK_CREATE_NAME in the global scope (this can't be done
-	 from `lower_starpu'.)
-	 XXX: Move it in a pass of its own.  */
+  /* Lookup the useful StarPU functions in the global scope (this can't be
+     done from `lower_starpu'.)
+     XXX: Move it in a pass of its own.  */
 
-      insert_task_fn = lookup_name (get_identifier ("starpu_insert_task"));
-      gcc_assert (insert_task_fn != NULL_TREE &&
-		  TREE_CODE (insert_task_fn) == FUNCTION_DECL);
+#define LOOKUP_STARPU_FUNCTION(var, name)				\
+  if ((var) == NULL_TREE)						\
+    {									\
+      (var) = lookup_name (get_identifier (name));			\
+      gcc_assert ((var) != NULL_TREE && TREE_CODE (var) == FUNCTION_DECL); \
     }
 
+  LOOKUP_STARPU_FUNCTION (insert_task_fn, "starpu_insert_task");
+  LOOKUP_STARPU_FUNCTION (data_lookup_fn, "starpu_data_lookup");
+
+#undef LOOKUP_STARPU_FUNCTION
+
   return NULL_TREE;
 }
 
@@ -933,6 +938,57 @@ handle_pre_genericize (void *gcc_data, void *user_data)
     maybe_define_codelet (fndecl);
 }
 
+/* Build a "conversion" from a raw C pointer to its data handle.  The
+   assumption is that the programmer should have already registered the
+   pointer by themselves.  */
+
+static tree
+build_pointer_lookup (tree pointer, gimple_seq *body)
+{
+  gimple emit_error_message (void)
+  {
+    static const char msg[] =
+      "starpu: task called with unregistered pointer, aborting\n";
+
+    return gimple_build_call (built_in_decls[BUILT_IN_PUTS], 1,
+			      build_string_literal (strlen (msg) + 1, msg));
+  }
+
+  tree var;
+
+  var = create_tmp_var (ptr_type_node, ".handle-arg");
+  mark_addressable (var);
+
+  /* Initialize VAR with `starpu_data_lookup (POINTER)'.  */
+  gimple_seq init = NULL;
+  tree modify = build2 (MODIFY_EXPR, ptr_type_node, var,
+			build_call_expr (data_lookup_fn, 1, pointer));
+  force_gimple_operand (modify, &init, true, var);
+
+  gimple_seq_add_seq (body, init);
+
+  /* FIXME: Add `if (VAR == NULL) abort ();'.  */
+#if 0
+  tree abort_label = create_artificial_label (UNKNOWN_LOCATION);
+  tree success_label = create_artificial_label (UNKNOWN_LOCATION);
+
+  gimple cond = gimple_build_cond (EQ_EXPR,
+				   var, build_zero_cst (ptr_type_node),
+				   abort_label, success_label);
+  gimple_seq_add_stmt (body, cond);
+
+  gimplify_seq_add_stmt (body, gimple_build_label (abort_label));
+  gimple_seq_add_stmt (body, emit_error_message ());
+  gimple_seq_add_stmt (body,
+		       gimple_build_call (built_in_decls[BUILT_IN_ABORT], 0));
+  gimplify_seq_add_stmt (body, gimple_build_label (success_label));
+
+  rebuild_cgraph_edges ();
+#endif
+
+  return var;
+}
+
 /* Build a call to `starpu_insert_task' for TASK_DECL, which will replace
    CALL.  */
 
@@ -1028,8 +1084,7 @@ build_task_submission (tree task_decl, gimple call)
 
 	  VEC_safe_push (tree, heap, args,
 			 build_int_cst (integer_type_node, STARPU_RW));
-	  VEC_safe_push (tree, heap, args, arg);
-	  /* FIXME: Should pass the result of `starpu_data_lookup (ARG)'.  */
+	  VEC_safe_push (tree, heap, args, build_pointer_lookup (arg, &body));
 	}
       else
 	{

+ 29 - 4
gcc-plugin/tests/lib.h

@@ -93,8 +93,12 @@ starpu_insert_task (starpu_codelet *cl, ...)
 	case STARPU_RW:
 	case STARPU_R:
 	case STARPU_W:
-	  assert (va_arg (args, void *) == expected->pointer);
-	  break;
+	  {
+	    starpu_data_handle handle;
+	    handle = starpu_data_lookup (expected->pointer);
+	    assert (va_arg (args, void *) == handle);
+	    break;
+	  }
 
 	default:
 	  abort ();
@@ -142,14 +146,35 @@ starpu_unpack_cl_args (void *cl_raw_arg, ...)
   va_end (args);
 }
 
+
+/* Data handles.  For testing purposes, there's a dummy implementation of
+   data handles below, which disguises the original pointer to form a pseudo
+   handle.  This allows us to test whether the task implementation is
+   actually passed a pointer, not a handle.  */
+
+#define pointer_as_int(p) ((uintptr_t) (p))
+#define int_as_pointer(i) ((void *) (i))
+
+#define dummy_pointer_to_handle(p)		\
+  ({						\
+     assert ((pointer_as_int (p) & 1) == 0);	\
+     int_as_pointer (~pointer_as_int (p));	\
+   })
+
+#define dummy_handle_to_pointer(h)		\
+  ({						\
+     assert ((pointer_as_int (h) & 1) == 1);	\
+     int_as_pointer (~pointer_as_int (h));	\
+   })
+
 starpu_data_handle
 starpu_data_lookup (const void *ptr)
 {
-  return (starpu_data_handle) ptr;
+  return dummy_pointer_to_handle (ptr);
 }
 
 void *
 starpu_handle_get_local_ptr (starpu_data_handle handle)
 {
-  return handle;
+  return dummy_handle_to_pointer (handle);
 }