https://gcc.gnu.org/g:a0c4cba52a5dc7db28810b44b209982df8144c37

commit a0c4cba52a5dc7db28810b44b209982df8144c37
Author: Josef Melcr <melcr...@fit.cvut.cz>
Date:   Wed Dec 4 19:27:44 2024 +0100

    omp-cp: Move callback attr from callee to caller, add it to builtins
    
    gcc/ChangeLog:
    
            * builtin-attrs.def (ATTR_CALLBACK): Add attribute definition
            (DEF_CALLBACK_ATTRIBUTE_NOTHROW): New macro for creating
            callback attribute
            (ATTR_NOTHROW_CALLBACK_GOMP_LIST): New attr list
            * gimple.h (gimple_omp_parallel_set_child_fn): Remove callback
            attribute addition
            * ipa-prop.cc (ipa_duplicate_jump_function): Declare
            (calc_callback_args_idx): Refactor
            (ipa_compute_jump_functions_for_edge): Change
            calc_callback_args_idx call
            (ipa_copy_ith_jump_func): Remove function
            * omp-builtins.def (BUILT_IN_GOMP_PARALLEL): Change attr list to
            callback list
    
    gcc/c-family/ChangeLog:
    
            * c-attribs.cc (handle_callback_attribute): Add attribute
            handler
    
    Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz>

Diff:
---
 gcc/builtin-attrs.def     |  10 +++
 gcc/c-family/c-attribs.cc |  36 +++++++++-
 gcc/gimple.h              |  10 +--
 gcc/ipa-prop.cc           | 171 +++++++++++++---------------------------------
 gcc/omp-builtins.def      |   2 +-
 5 files changed, 95 insertions(+), 134 deletions(-)

diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 1b8885c933cf..8a0b3463adcb 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -121,6 +121,7 @@ DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure")
 DEF_ATTR_IDENT (ATTR_RETURNS_TWICE, "returns_twice")
 DEF_ATTR_IDENT (ATTR_RETURNS_NONNULL, "returns_nonnull")
 DEF_ATTR_IDENT (ATTR_WARN_UNUSED_RESULT, "warn_unused_result")
+DEF_ATTR_IDENT (ATTR_CALLBACK, "callback")
 
 DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
 
@@ -387,6 +388,15 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4)
 #undef DEF_FORMAT_ATTRIBUTE_NOTHROW
 #undef DEF_FORMAT_ATTRIBUTE_BOTH
 
+/* Callback attr */
+#define DEF_CALLBACK_ATTRIBUTE_NOTHROW(TYPE, CA, VALUES)                       
 \
+  DEF_ATTR_TREE_LIST (ATTR_CALLBACK_##TYPE##_NOTHROW_##VALUES, ATTR_CALLBACK,\
+                     ATTR_NOTHROW_NONNULL_##CA, ATTR_LIST_##VALUES)
+
+DEF_CALLBACK_ATTRIBUTE_NOTHROW(GOMP, 1, 2)
+DEF_ATTR_TREE_LIST(ATTR_NOTHROW_CALLBACK_GOMP_LIST, ATTR_CALLBACK, 
ATTR_CALLBACK_GOMP_NOTHROW_2, ATTR_NOTHROW_LIST)
+#undef DEF_CALLBACK_ATTRIBUTE_NOTHROW
+
 /* Transactional memory variants of the above.  */
 
 DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST,
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index c342e7a1e55f..6fb1f8d034d1 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -188,6 +188,7 @@ static tree handle_retain_attribute (tree *, tree, tree, 
int, bool *);
 static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
 static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *);
 static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, 
int, bool *);
+static tree handle_callback_attribute (tree *, tree, tree, int, bool *);
 
 /* Helper to define attribute exclusions.  */
 #define ATTR_EXCL(name, function, type, variable)      \
@@ -465,6 +466,7 @@ const struct attribute_spec c_common_gnu_attributes[] =
                              handle_tm_attribute, NULL },
   { "transaction_may_cancel_outer", 0, 0, false, true, false, false,
                              handle_tm_attribute, NULL },
+  { "callback", 1, -1, true, false, false, false, handle_callback_attribute, 
NULL},
   /* ??? These two attributes didn't make the transition from the
      Intel language document to the multi-vendor language document.  */
   { "transaction_pure",       0, 0, false, true,  false, false,
@@ -643,7 +645,6 @@ const struct attribute_spec c_common_gnu_attributes[] =
                              handle_flag_enum_attribute, NULL },
   { "null_terminated_string_arg", 1, 1, false, true, true, false,
                              handle_null_terminated_string_arg_attribute, 
NULL},
-  { "callback", 0, 0, true, false, false, false, NULL, NULL}
 };
 
 const struct scoped_attribute_specs c_common_gnu_attribute_table =
@@ -5192,6 +5193,39 @@ get_argument (tree fndecl, unsigned argno)
   return NULL_TREE;
 }
 
+static tree
+handle_callback_attribute (tree *node, tree name, tree args,
+                          int ARG_UNUSED (flags),
+                          bool ARG_UNUSED (*no_add_attrs))
+{
+  tree decl = *node;
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    {
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "%qE attribute can only be used on functions", name);
+    }
+  tree callback_fn_idx_node = args;
+  for (int i = 0; i < 3;
+       i++, callback_fn_idx_node = TREE_VALUE (callback_fn_idx_node))
+    ;
+  int callback_fn_idx = TREE_INT_CST_LOW (callback_fn_idx_node) - 1;
+  if (callback_fn_idx < 0)
+    error_at (DECL_SOURCE_LOCATION (decl),
+             "callback function position out of range");
+  //
+  //  tree cfn = get_argument (decl, callback_fn_idx);
+  //  if (cfn == NULL_TREE)
+  //    error_at(DECL_SOURCE_LOCATION(decl), "couldnt retrieve callback 
function
+  //    from arguments");
+  //
+  //  if (TREE_CODE(cfn) != ADDR_EXPR || TREE_CODE(TREE_OPERAND(cfn, 0)) !=
+  //  FUNCTION_DECL)
+  //    error_at(DECL_SOURCE_LOCATION(decl), "argument no. %d is not a fndecl",
+  //    callback_fn_idx);
+  //
+  return NULL_TREE;
+}
+
 /* Attempt to append attribute access specification ATTRSPEC, optionally
    described by the human-readable string ATTRSTR, for type T, to one in
    ATTRS. VBLIST is an optional list of bounds of variable length array
diff --git a/gcc/gimple.h b/gcc/gimple.h
index faae38491fea..b40f3e8009a1 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -5817,15 +5817,7 @@ inline void
 gimple_omp_parallel_set_child_fn (gomp_parallel *omp_parallel_stmt,
                                  tree child_fn)
 {
-  if (child_fn != NULL_TREE
-      && !lookup_attribute ("callback", DECL_ATTRIBUTES (child_fn)))
-    {
-      tree attrs = tree_cons (get_identifier ("callback"), NULL,
-                             DECL_ATTRIBUTES (child_fn));
-      decl_attributes (&child_fn, attrs, 0);
-    }
-
-  omp_parallel_stmt->child_fn = child_fn;
+    omp_parallel_stmt->child_fn = child_fn;
 }
 
 /* Return the artificial argument used to send variables and values
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 11404bdd3aff..ae0e32b1fe65 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -325,6 +325,10 @@ ipa_get_param_decl_index (class ipa_node_params *info, 
tree ptree)
   return ipa_get_param_decl_index_1 (info->descriptors, ptree);
 }
 
+static void
+ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst,
+                            ipa_jump_func *src_jf, ipa_jump_func *dst_jf);
+
 /* Populate the param_decl field in parameter DESCRIPTORS that correspond to
    NODE.  */
 
@@ -2314,21 +2318,46 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, const ipa_vr &vr)
   ipa_set_jfunc_vr (jf, tmp);
 }
 
+static void
+calc_callback_args_idx (cgraph_edge *og, cgraph_edge *cbe)
+{
+  gcc_checking_assert (cbe->callback);
+  ipa_edge_args *args = ipa_edge_args_sum->get_create (cbe);
+  int argn = 0;
+  tree arg;
+  tree cb_args
+    = lookup_attribute ("callback", DECL_ATTRIBUTES (og->callee->decl));
+  for (arg = TREE_CHAIN (TREE_VALUE (cb_args)); arg;
+       arg = TREE_CHAIN (arg), argn++)
+    ;
+  vec_safe_grow_cleared (args->jump_functions, argn, true);
+  vec_safe_grow_cleared (args->callback_args, argn, true);
+  gcc_checking_assert (cb_args);
+  int idx = 0;
+  for (arg = TREE_CHAIN (cb_args); arg; arg = TREE_CHAIN (arg), idx++)
+    {
+      tree val = TREE_VALUE (arg);
+      if (TREE_CODE (val) == INTEGER_CST)
+       {
+         int arg_idx = TREE_INT_CST_LOW (val);
+         bool is_data = arg_idx != -1;
+         if (arg_idx == -1)
+           {
+             arg_idx = idx;
+           }
+         (*args->callback_args)[idx] = {arg_idx, is_data};
+       }
+      else
+       {
+         gcc_checking_assert (0);
+       }
+    }
+}
+
 /* Compute jump function for all arguments of callsite CS and insert the
    information in the jump_functions array in the ipa_edge_args corresponding
    to this callsite.  */
 
-static void calc_callback_args_idx(cgraph_edge * e) {
-  gcc_checking_assert(e->callback);
-  ipa_edge_args *args = ipa_edge_args_sum->get_create (e);
-  int argn = 1;
-  vec_safe_grow_cleared (args->callback_args, argn, true);
-  (*args->callback_args)[0] = {1, true};
-  for (int i = 1; i < argn; i++) {
-    (*args->callback_args)[i] = {i, false};
-  }
-}
-
 static void
 ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
                                     struct cgraph_edge *cs)
@@ -2438,13 +2467,13 @@ ipa_compute_jump_functions_for_edge (struct 
ipa_func_body_info *fbi,
            {
              tree pointee = TREE_OPERAND (arg, 0);
              if (TREE_CODE (pointee) == FUNCTION_DECL
-                 && lookup_attribute ("callback", DECL_ATTRIBUTES (pointee))
+                 && lookup_attribute ("callback", DECL_ATTRIBUTES 
(cs->callee->decl))
                  && !cs->callback)
                {
                  cgraph_node *kernel_node = cgraph_node::get_create (pointee);
                  gcc_checking_assert (!callback_edge);
                  callback_edge = cs->make_callback (kernel_node);
-                 calc_callback_args_idx (callback_edge);
+                 calc_callback_args_idx (cs, callback_edge);
                }
            }
        }
@@ -2513,16 +2542,17 @@ ipa_compute_jump_functions_for_edge (struct 
ipa_func_body_info *fbi,
       for (i = 0; i < cb_summary->callback_args->length (); i++)
        {
          cb_arg_info cb = (*cb_summary->callback_args)[i];
-         ipa_copy_ith_jump_func (cs, cb.idx, callback_edge, i);
+         class ipa_jump_func * src = ipa_get_ith_jump_func(args, cb.idx);
+    class ipa_jump_func * dst = ipa_get_ith_jump_func(cb_summary, i);
+    ipa_duplicate_jump_function(cs, callback_edge, src, dst);
          if (cb.is_data_arg)
            {
-             class ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, cb.idx);
              unsigned j;
-             for (j = 0; jfunc->agg.items && (j < jfunc->agg.items->length ());
+             for (j = 0; src->agg.items && (j < src->agg.items->length ());
                   j++)
                {
-                 if ((*jfunc->agg.items)[j].jftype == IPA_JF_PASS_THROUGH)
-                   (*jfunc->agg.items)[j].value.pass_through.agg_preserved
+                 if ((*src->agg.items)[j].jftype == IPA_JF_PASS_THROUGH)
+                   (*src->agg.items)[j].value.pass_through.agg_preserved
                      = true;
                }
            }
@@ -4554,111 +4584,6 @@ ipa_edge_args_sum_t::remove (cgraph_edge *cs, 
ipa_edge_args *args)
     }
 }
 
-void
-ipa_copy_ith_jump_func (class cgraph_edge *src, unsigned src_idx,
-                       class cgraph_edge *dst, unsigned dst_idx)
-{
-  class ipa_edge_args *src_args = ipa_edge_args_sum->get (src);
-  class ipa_edge_args *dst_args = ipa_edge_args_sum->get (dst);
-  
-  
-  if (dst_idx >= vec_safe_length (dst_args->jump_functions))
-    {
-      vec_safe_grow_cleared (dst_args->jump_functions, dst_idx + 1, true);
-    }
-
-  struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (src_args, src_idx);
-  struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (dst_args, dst_idx);
-
-  ::new (dst_jf) ipa_jump_func (*src_jf);
-
-  dst_jf->agg.items = vec_safe_copy (src_jf->agg.items);
-  dst_jf->m_vr = src_jf->m_vr;
-
-  if (src_jf->type == IPA_JF_CONST)
-    {
-      struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf);
-
-      if (!src_rdesc)
-       dst_jf->value.constant.rdesc = NULL;
-      else if (src->caller == dst->caller)
-       {
-         /* Creation of a speculative edge.  If the source edge is the one
-            grabbing a reference, we must create a new (duplicate)
-            reference description.  Otherwise they refer to the same
-            description corresponding to a reference taken in a function
-            src->caller is inlined to.  In that case we just must
-            increment the refcount.  */
-         if (src_rdesc->cs == src)
-           {
-             symtab_node *n = symtab_node_for_jfunc (src_jf);
-             gcc_checking_assert (n);
-             ipa_ref *ref
-               = src->caller->find_reference (n, src->call_stmt,
-                                              src->lto_stmt_uid, IPA_REF_ADDR);
-             gcc_checking_assert (ref);
-             dst->caller->clone_reference (ref, ref->stmt);
-
-             ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
-             dst_rdesc->cs = dst;
-             dst_rdesc->refcount = src_rdesc->refcount;
-             dst_rdesc->next_duplicate = NULL;
-             dst_jf->value.constant.rdesc = dst_rdesc;
-           }
-         else
-           {
-             src_rdesc->refcount++;
-             dst_jf->value.constant.rdesc = src_rdesc;
-           }
-       }
-      else if (src_rdesc->cs == src)
-       {
-         struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
-         dst_rdesc->cs = dst;
-         dst_rdesc->refcount = src_rdesc->refcount;
-         dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
-         src_rdesc->next_duplicate = dst_rdesc;
-         dst_jf->value.constant.rdesc = dst_rdesc;
-       }
-      else
-       {
-         struct ipa_cst_ref_desc *dst_rdesc;
-         /* This can happen during inlining, when a JFUNC can refer to a
-            reference taken in a function up in the tree of inline clones.
-            We need to find the duplicate that refers to our tree of
-            inline clones.  */
-
-         gcc_assert (dst->caller->inlined_to);
-         for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc;
-              dst_rdesc = dst_rdesc->next_duplicate)
-           {
-             struct cgraph_node *top;
-             top = dst_rdesc->cs->caller->inlined_to
-                     ? dst_rdesc->cs->caller->inlined_to
-                     : dst_rdesc->cs->caller;
-             if (dst->caller->inlined_to == top)
-               break;
-           }
-         gcc_assert (dst_rdesc);
-         dst_jf->value.constant.rdesc = dst_rdesc;
-       }
-    }
-  else if (dst_jf->type == IPA_JF_PASS_THROUGH && src->caller == dst->caller)
-    {
-      struct cgraph_node *inline_root
-       = dst->caller->inlined_to ? dst->caller->inlined_to : dst->caller;
-      ipa_node_params *root_info = ipa_node_params_sum->get (inline_root);
-      int idx = ipa_get_jf_pass_through_formal_id (dst_jf);
-
-      int c = ipa_get_controlled_uses (root_info, idx);
-      if (c != IPA_UNDESCRIBED_USE)
-       {
-         c++;
-         ipa_set_controlled_uses (root_info, idx, c);
-       }
-    }
-}
-
 /* Method invoked when an edge is duplicated.  Copy ipa_edge_args and adjust
    reference count data strucutres accordingly.  */
 static void
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index c70e077063b7..46a68668d894 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -399,7 +399,7 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_POST, 
"GOMP_doacross_ull_post",
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_WAIT, "GOMP_doacross_ull_wait",
                  BT_FN_VOID_ULL_VAR, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL, "GOMP_parallel",
-                 BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)
+                 BT_FN_VOID_OMPFN_PTR_UINT_UINT, 
ATTR_NOTHROW_CALLBACK_GOMP_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_REDUCTIONS,
                  "GOMP_parallel_reductions",
                  BT_FN_UINT_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)

Reply via email to