On Mon, Oct 20, 2025 at 7:10 AM Andrew Pinski
<[email protected]> wrote:
>
> On Sun, Oct 19, 2025 at 2:27 PM H.J. Lu <[email protected]> wrote:
> >
> > On Fri, Oct 17, 2025 at 5:40 PM Josef Melcr <[email protected]> wrote:
> > >
> > > Hi,
> > > I pushed the patched below to master. It is largely the same as the v5
> > > (link:
> > > https://gcc.gnu.org/pipermail/gcc-patches/2025-October/697470.html),
> > > but I took out all the oacc bits, as they did not apply (discussed in
> > > https://gcc.gnu.org/pipermail/gcc-patches/2025-October/697527.html).
> > >
> > > ==========
> > >
> > > This patch enables constant propagation to outlined OpenMP kernels.
> > > It does so using a new function attribute called ' callback' (note the
> > > space).
> > >
> > > The attribute ' callback' captures the notion of a function calling one
> > > of its arguments with some of its parameters as arguments. An OpenMP
> > > example of such function is GOMP_parallel.
> > > We implement the attribute with new callgraph edges called callback
> > > edges. They are imaginary edges pointing from the caller of the function
> > > with the attribute (e.g. caller of GOMP_parallel) to the body function
> > > itself (e.g. the outlined OpenMP body). They share their call statement
> > > with the edge from which they are derived (direct edge caller ->
> > > GOMP_parallel
> > > in this case). These edges allow passes such as ipa-cp to see the hidden
> > > call site to the body function and optimize the function accordingly.
> > >
> > > To illustrate on an example, the body GOMP_parallel looks something
> > > like this:
> > >
> > > void GOMP_parallel (void (*fn) (void *), void *data, /* ... */)
> > > {
> > > /* ... */
> > > fn (data);
> > > /* ... */
> > > }
> > >
> > >
> > > If we extend it with the attribute ' callback(1, 2)', we express that the
> > > function calls its first argument and passes it its second argument.
> > > This is represented in the call graph in this manner:
> > >
> > > direct indirect
> > > caller -----------------> GOMP_parallel ---------------> fn
> > > |
> > > ----------------------> fn
> > > callback
> > >
> > > The direct edge is then the callback-carrying edge, all new edges
> > > are the derived callback edges.
> > > While constant propagation is the main focus of this patch, callback
> > > edges can be useful for different passes (for example, they improve icf
> > > for OpenMP kernels), as they allow for address redirection.
> > > If the outlined body function gets optimized and cloned, from body_fn to
> > > body_fn.optimized, the callback edge allows us to replace the
> > > address in the arguments list:
> > >
> > > GOMP_parallel (body_fn, &data_struct, /* ... */);
> > >
> > > becomes
> > >
> > > GOMP_parallel (body_fn.optimized, &data_struct, /* ... */);
> > >
> > > This redirection is possible for any function with the attribute.
> > >
> > > This callback attribute implementation is partially compatible with
> > > clang's implementation. Its semantics, arguments and argument indexing
> > > style are
> > > the same, but we represent an unknown argument position with 0
> > > (precedent set by attributes such as 'format'), while clang uses -1 or
> > > '?'.
> > > We use the index 1 for the 'this' pointer in member functions, clang
> > > uses 0. We also allow for multiple callback attributes on the same
> > > function,
> > > while clang only allows one.
> > >
> > > The attribute is currently for GCC internal use only, thanks to the
> > > space in its name. Originally, it was supposed to be called
> > > 'callback' like its clang counterpart, but we cannot use this name, as
> > > clang uses non-standard indexing style, leading to inconsistencies. The
> > > attribute will be introduced into the public API as 'gnu::callback_only'
> > > in a future patch.
> > >
> > > The attribute allows us to propagate constants into body functions of
> > > OpenMP constructs. Currently, GCC won't propagate the value 'c' into the
> > > OpenMP body in the following example:
> > >
> > > int a[100];
> > > void test(int c) {
> > > #pragma omp parallel for
> > > for (int i = 0; i < c; i++) {
> > > if (!__builtin_constant_p(c)) {
> > > __builtin_abort();
> > > }
> > > a[i] = i;
> > > }
> > > }
> > > int main() {
> > > test(100);
> > > return a[5] - 5;
> > > }
> > >
> > > With this patch, the body function will get cloned and the constant 'c'
> > > will get propagated.
> > >
> > > Some functions may utilize the attribute's infrastructure without being
> > > declared with it, for example GOMP_task. These functions are special
> > > cases and use the special case functions found in attr-callback.h.
> > > Special
> > > cases use the attribute under certain circumstances, for example
> > > GOMP_task uses it when the copy function is not being used required.
> > >
> > > gcc/ChangeLog:
> > >
> > > * Makefile.in: Add attr-callback.o to OBJS.
> > > * builtin-attrs.def (ATTR_CALLBACK): Callback attr identifier.
> > > (DEF_CALLBACK_ATTRIBUTE): Macro for callback attr creation.
> > > (GOMP): Attr for libgomp functions.
> > > (ATTR_CALLBACK_GOMP_LIST): ATTR_NOTHROW_LIST with GOMP callback
> > > attr added.
> > > * cgraph.cc (cgraph_add_edge_to_call_site_hash): Always hash the
> > > callback-carrying edge.
> > > (cgraph_node::get_edge): Always return the callback-carrying
> > > edge.
> > > (cgraph_edge::set_call_stmt): Add cascade for callback edges.
> > > (symbol_table::create_edge): Allow callback edges to share call
> > > stmts, initialize new flags.
> > > (cgraph_edge::make_callback): New method, derives a new callback
> > > edge.
> > > (cgraph_edge::get_callback_carrying_edge): New method.
> > > (cgraph_edge::first_callback_edge): Likewise.
> > > (cgraph_edge::next_callback_edge): Likewise.
> > > (cgraph_edge::purge_callback_edges): Likewise.
> > > (cgraph_edge::redirect_callee): When redirecting a callback
> > > edge, redirect its ref as well.
> > > (cgraph_edge::redirect_call_stmt_to_callee): Add callback edge
> > > redirection logic, set update_derived_edges to true hwne
> > > redirecting the carrying edge.
> > > (cgraph_node::remove_callers): Add cascade for callback edges.
> > > (cgraph_edge::dump_edge_flags): Print callback flags.
> > > (cgraph_node::verify_node): Add sanity checks for callback
> > > edges.
> > > * cgraph.h: Add new 1 bit flags and 16 bit callback_id to
> > > cgraph_edge class.
> > > * cgraphclones.cc (cgraph_edge::clone): Copy over callback data.
> > > * cif-code.def (CALLBACK_EDGE): Add CIF_CALLBACK_EDGE code.
> > > * ipa-cp.cc (purge_useless_callback_edges): New function,
> > > deletes callback edges when necessary.
> > > (ipcp_decision_stage): Call purge_useless_callback_edges.
> > > * ipa-fnsummary.cc (ipa_call_summary_t::duplicate): Add
> > > an exception for callback edges.
> > > (analyze_function_body): Copy over summary from carrying to
> > > callback edge.
> > > * ipa-inline-analysis.cc (do_estimate_growth_1): Skip callback
> > > edges when estimating growth.
> > > * ipa-inline-transform.cc (inline_transform): Add redirection
> > > cascade for callback edges.
> > > * ipa-param-manipulation.cc
> > > (drop_decl_attribute_if_params_changed_p): New function.
> > > (ipa_param_adjustments::build_new_function_type): Add
> > > args_modified out param.
> > > (ipa_param_adjustments::adjust_decl): Drop callback attrs when
> > > modifying args.
> > > * ipa-param-manipulation.h: Adjust decl of
> > > build_new_function_type.
> > > * ipa-prop.cc (ipa_duplicate_jump_function): Add decl.
> > > (init_callback_edge_summary): New function.
> > > (ipa_compute_jump_functions_for_edge): Add callback edge
> > > creation logic.
> > > * lto-cgraph.cc (lto_output_edge): Stream out callback data.
> > > (input_edge): Input callback data.
> > > * omp-builtins.def (BUILT_IN_GOMP_PARALLEL_LOOP_STATIC): Use new
> > > attr list.
> > > (BUILT_IN_GOMP_PARALLEL_LOOP_GUIDED): Likewise.
> > > (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC): Likewise.
> > > (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_RUNTIME): Likewise.
> > > (BUILT_IN_GOMP_PARALLEL): Likewise.
> > > (BUILT_IN_GOMP_PARALLEL_SECTIONS): Likewise.
> > > (BUILT_IN_GOMP_TEAMS_REG): Likewise.
> > > * tree-core.h (ECF_CB_1_2): New constant for callback(1,2).
> > > * tree-inline.cc (copy_bb): Copy callback edges when copying the
> > > carrying edge.
> > > (redirect_all_calls): Redirect callback edges.
> > > * tree.cc (set_call_expr_flags): Create callback attr according
> > > to the ECF_CB flag.
> > > * attr-callback.cc: New file.
> > > * attr-callback.h: New file.
> > >
> > > gcc/c-family/ChangeLog:
> > >
> > > * c-attribs.cc: Define callback attr.
> > >
> > > gcc/fortran/ChangeLog:
> > >
> > > * f95-lang.cc (ATTR_CALLBACK_GOMP_LIST): New attr list
> > > corresponding to the list in builtin-attrs.def.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * gcc.dg/ipa/ipcp-cb-spec1.c: New test.
> > > * gcc.dg/ipa/ipcp-cb-spec2.c: New test.
> > > * gcc.dg/ipa/ipcp-cb1.c: New test.
> >
> > These run-time tests should be moved to libgomp to avoid
> >
> > xgcc: fatal error: cannot read spec file 'libgomp.spec': No such file
> > or directory
> > compilation terminated.
> > compiler exited with status 1
> > FAIL: gcc.dg/ipa/ipcp-cb1.c (test for excess errors)
>
> No what Josef is doing is correct.
> The testcases have already:
> /* { dg-require-effective-target fopenmp } */
>
> That is how gcc.dg/gomp/gomp.exp and others handles this already.
> e.g. c-c++-common/gomp/assume-3.c c-c++-common/gomp/pr60823-2.c
> gcc.dg/gomp/pr114075.c etc.
But these aren't libgomp run-time tests. -fopenmp-simd doesn't need
libgomp.
> target-supports.exp has:
> ```
> proc check_effective_target_fopenmp {} {
> # nvptx/amdgcn can be built with the device-side bits of libgomp, but it
> # does not make sense to test it as an openmp host.
> if [istarget nvptx-*-*] { return 0 }
> if [istarget amdgcn-*-*] { return 0 }
>
> return [check_no_compiler_messages fopenmp object {
> void foo (void) { }
> } "-fopenmp"]
> }
> ```
>
> I am not sure why this is not working for you. Unless the other
> testcases are failing in a similar way.
Please see commits like
commit 2d5c1e5149809f978ea2c07517de13fdbb925de6
Author: Tobias Burnus <[email protected]>
Date: Mon Mar 17 10:12:44 2025 +0100
Move gfortran.dg/gomp/declare-variant-mod-1*.f90 to
libgomp.fortran/ [PR115271]
The test is a supposed to be a compile-only test but as
dg-additional-sources
does not work with dg-compile (due to compiling with '-o'), dg-link had to
be used; as the code actually compiles (no diagnostic error), the linker
is actually invoked, which fails unless the system compiler by chance
provides the required files. Solution: move the test to libgomp.
>
> >
> > --
> > H.J.
--
H.J.