https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96680

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Sandra Loosemore <san...@gcc.gnu.org>:

https://gcc.gnu.org/g:1294b819e1207c0ae76db29a75256f3fafd5f262

commit r15-6895-g1294b819e1207c0ae76db29a75256f3fafd5f262
Author: Sandra Loosemore <sloosem...@baylibre.com>
Date:   Mon Jan 13 20:18:12 2025 +0000

    OpenMP: Re-work and extend context selector resolution

    This patch reimplements the middle-end support for "declare variant"
    and extends the resolution mechanism to also handle metadirectives
    (PR112779).  It also adds partial support for dynamic selectors
    (PR113904) and fixes a selector scoring bug reported as PR114596.  I hope
    this rewrite also improves the engineering aspect of the code, e.g. more
    comments to explain what it is doing.

    In most cases, variant constructs can be resolved either in the front
    end or during gimplification; if the variant with the highest score
    has a static selector, then only that one is emitted.  In the case
    where it has a dynamic selector, it is resolved into a (possibly nested)
    if/then/else construct, testing the run-time predicate for each selector
    sorted by decreasing order of score until a static selector is found.

    In some cases, notably a variant construct in a "declare simd"
    function which may or may not expand into a simd clone, it may not be
    possible to score or sort the variants until later in compilation (the
    ompdevlow pass).  In this case the gimplifier emits a loop containing
    a switch statement with the variants in arbitrary order and uses the
    OMP_NEXT_VARIANT tree node as a placeholder to control which variant
    is tested on each iteration of the loop.  It looks something like:

         switch_var = OMP_NEXT_VARIANT (0, state);
         loop_label:
         switch (switch_var)
           {
           case 1:
            if (dynamic_selector_predicate_1)
              {
                alternative_1;
                goto end_label;
              }
            else
              {
                switch_var = OMP_NEXT_VARIANT (1, state);
                goto loop_label;
              }
           case 2:
             ...
           }
          end_label:

    Note that when there are no dynamic selectors, the loop is unnecessary
    and only the switch is emitted.

    Finally, in the ompdevlow pass, the OMP_NEXT_VARIANT magic cookies are
    resolved and replaced with constants.  When compiling with -O we can
    expect that the loop and switch will be discarded by subsequent
    optimizations and replaced with direct jumps between the cases,
    eventually arriving at code with similar control flow to the
    early-resolution cases.

    This approach is somewhat simpler than the one currently used for
    handling declare variant in that all possible code paths are already
    included in the output of the gimplifier, so it is not necessary to
    maintain hidden references or data structures pointing to expansions of
    not-yet-resolved variant constructs and special logic for passing them
    through LTO (see PR lto/96680).

    A possible disadvantage of this expansion strategy is that dead code
    for unused variants in the switch can remain when compiling without
    -O.  If this turns out to be a critical problem (e.g., an unused case
    includes calls to functions not available to the linker) perhaps some
    further processing could be performed by default after ompdevlow to
    simplify such constructs.

    In order to make this patch more readable for review purposes, it
    leaves the existing code for "declare variant" resolution (including
    the above-mentioned LTO hack) in place, in some cases just ifdef-ing
    out functions that won't compile due to changed interfaces for
    dependencies.  The next patch in the series will delete all the
    now-unused code.

    gcc/ChangeLog
            PR middle-end/114596
            PR middle-end/112779
            PR middle-end/113904

            * Makefile.in (GTFILES): Move omp-general.h earlier; required
            because of moving score_wide_int declaration to that file.
            * cgraph.h (struct cgraph_node): Add has_omp_variant_constructs
flag.
            * cgraphclones.cc (cgraph_node::create_clone): Propagate
            has_omp_variant_constructs flag.
            * gimplify.cc (omp_resolved_variant_calls): New.
            (expand_late_variant_directive): New.
            (find_supercontext): New.
            (gimplify_variant_call_expr): New.
            (gimplify_call_expr): Adjust parameters to make fallback available.
            Update processing for "declare variant" substitution.
            (is_gimple_stmt): Add OMP_METADIRECTIVE.
            (omp_construct_selector_matches): Ifdef out unused function.
            (omp_get_construct_context): New.
            (gimplify_omp_dispatch): Replace call to deleted function
            omp_resolve_declare_variant with equivalent logic.
            (expand_omp_metadirective): New.
            (expand_late_variant_directive): New.
            (gimplify_omp_metadirective): New.
            (gimplify_expr): Adjust arguments to gimplify_call_expr.  Add
            cases for OMP_METADIRECTIVE, OMP_NEXT_VARIANT, and
            OMP_TARGET_DEVICE_MATCHES.
            (gimplify_function_tree): Initialize/clean up
            omp_resolved_variant_calls.
            * gimplify.h (omp_construct_selector_matches): Delete declaration.
            (omp_get_construct_context): Declare.
            * lto-cgraph.cc (lto_output_node): Write
has_omp_variant_constructs.
            (input_overwrite_node): Read has_omp_variant_constructs.
            * omp-builtins.def (BUILT_IN_OMP_GET_NUM_DEVICES): New.
            * omp-expand.cc (expand_omp_taskreg): Propagate
            has_omp_variant_constructs.
            (expand_omp_target): Likewise.
            * omp-general.cc (omp_maybe_offloaded): Add construct_context
            parameter; use it instead of querying gimplifier state.  Add
            comments.
            (omp_context_name_list_prop): Do not test lang_GNU_Fortran in
            offload compiler, just use the string as-is.
            (expr_uses_parm_decl): New.
            (omp_check_context_selector): Add metadirective_p parameter.
            Remove sorry for target_device selector.  Add additional checks
            specific to metadirective or declare variant.
            (make_omp_metadirective_variant): New.
            (omp_construct_traits_match): New.
            (omp_context_selector_matches): Temporarily ifdef out the previous
            code, and add a new implementation based on the old one with
            different parameters, some unnecessary loops removed, and code
            re-indented.
            (omp_target_device_matches_on_host): New.
            (resolve_omp_target_device_matches): New.
            (omp_construct_simd_compare): Support matching of "simdlen" and
            "aligned" clauses.
            (omp_context_selector_set_compare): Make static.  Adjust call to
            omp_construct_simd_compare.
            (score_wide_int): Move declaration to omp-general.h.
            (omp_selector_is_dynamic): New.
            (omp_device_num_check): New.
            (omp_dynamic_cond): New.
            (omp_context_compute_score): Ifdef out the old version and
            re-implement with different parameters.
            (omp_complete_construct_context): New.
            (omp_resolve_late_declare_variant): Ifdef out.
            (omp_declare_variant_remove_hook): Likewise.
            (omp_resolve_declare_variant): Likewise.
            (sort_variant): New.
            (omp_get_dynamic_candidates): New.
            (omp_declare_variant_candidates): New.
            (omp_metadirective_candidates): New.
            (omp_early_resolve_metadirective): New.
            (omp_resolve_variant_construct): New.
            * omp-general.h (score_wide_int): Moved here from omp-general.cc.
            (struct omp_variant): New.
            (make_omp_metadirective_variant): Declare.
            (omp_construct_traits_to_codes): Delete declaration.
            (omp_check_context_selector): Adjust parameters.
            (omp_context_selector_matches): Likewise.
            (omp_context_selector_set_compare): Delete declaration.
            (omp_resolve_declare_variant): Likewise.
            (omp_declare_variant_candidates): Declare.
            (omp_metadirective_candidates): Declare.
            (omp_get_dynamic_candidates): Declare.
            (omp_early_resolve_metadirective): Declare.
            (omp_resolve_variant_construct): Declare.
            (omp_dynamic_cond): Declare.
            * omp-offload.cc (resolve_omp_variant_cookies): New.
            (execute_omp_device_lower): Call the above function to resolve
            variant directives.  Remove call to omp_resolve_declare_variant.
            (pass_omp_device_lower::gate): Check has_omp_variant_construct bit.
            * omp-simd-clone.cc (simd_clone_create): Propagate
            has_omp_variant_constructs bit.
            * tree-inline.cc (expand_call_inline): Likewise.
            (tree_function_versioning): Likewise.

    gcc/c/ChangeLog
            PR middle-end/114596
            PR middle-end/112779
            PR middle-end/113904
            * c-parser.cc (c_finish_omp_declare_variant): Update for changes
            to omp-general.h interfaces.

    gcc/cp/ChangeLog
            PR middle-end/114596
            PR middle-end/112779
            PR middle-end/113904
            * decl.cc (omp_declare_variant_finalize_one): Update for changes
            to omp-general.h interfaces.
            * parser.cc (cp_finish_omp_declare_variant): Likewise.

    gcc/fortran/ChangeLog
            PR middle-end/114596
            PR middle-end/112779
            PR middle-end/113904
            * trans-openmp.cc (gfc_trans_omp_declare_variant): Update for
changes
            to omp-general.h interfaces.

    gcc/testsuite/
            PR middle-end/114596
            PR middle-end/112779
            PR middle-end/113904
            * c-c++-common/gomp/declare-variant-12.c: Adjust expected behavior
            per PR114596.
            * c-c++-common/gomp/declare-variant-13.c: Test that this is
resolvable
            after gimplification, not just final resolution.
            * c-c++-common/gomp/declare-variant-14.c: Tweak testcase to ensure
            that -O causes dead code to be optimized away.
            * gfortran.dg/gomp/declare-variant-12.f90: Adjust expected behavior
            per PR114596.
            * gfortran.dg/gomp/declare-variant-13.f90: Test that this is
resolvable
            after gimplification, not just final resolution.
            * gfortran.dg/gomp/declare-variant-14.f90: Tweak testcase to ensure
            that -O causes dead code to be optimized away.

    Co-Authored-By: Kwok Cheung Yeung <k...@codesourcery.com>
    Co-Authored-By: Sandra Loosemore <san...@codesourcery.com>
    Co-Authored-By: Marcel Vollweiler <mar...@codesourcery.com>

Reply via email to