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

--- Comment #8 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>:

https://gcc.gnu.org/g:5869a881442aa4214d5deed7cfe0d352bcca1fd4

commit r15-9414-g5869a881442aa4214d5deed7cfe0d352bcca1fd4
Author: Patrick Palka <ppa...@redhat.com>
Date:   Sun Apr 13 11:04:46 2025 -0400

    c++: improve constexpr call caching [PR115639]

    For the testcase from this PR, checking

      static_assert(0 == big_calc());

    takes twice as much time as

      constexpr int ret = big_calc();
      static_assert(0 == ret);

    ultimately because in the former, we first constant evaluate big_calc()
    with mce_unknown (as part of warning-dependent folding from
    cp_build_binary_op).  We then constant evaluate it a second time, with
    mce_true, during finish_static_assert.  The result of the first
    evaluation isn't reused because of the different mce_value, which in
    general can give a different result.

    But big_calc() here doesn't depend on mce_value at all (i.e. there's no if
    consteval or __builtin_is_constant_evaluated calls, nested or otherwise)
    so we should be able to reuse the result in such cases.  Specifically if a
    constexpr call with mce_unknown succeeds, we can safely reuse the result
    during a subsequent mce_true or mce_false evaluation.

    This patch implements this by also caching a successful mce_unknown call
    result into the corresponding mce_true and mce_false slots, so that such
    a subsequent evaluation effectively reuses the mce_unknown result.  To
    make it more convenient to access the cache slot for the same call with
    different mce_value, this patch gives each constexpr_call entry three
    result slots, one per mce_value, instead of having a distinct
    constexpr_call entry for each mce_value.  And we can no longer use
    NULL_TREE to denote the call is in progress; instead use unknown_type_node.

    After this patch compile time for the above two fragments is the same.

            PR c++/115639

    gcc/cp/ChangeLog:

            * constexpr.cc (struct constexpr_call): Add NSDMIs to each
            field.  Replace 'result' data member with 3-element 'results'
            array and a 'result' accessor function.  Remove
            'manifestly_const_eval' data member.
            (constexpr_call_hasher::equal): Adjust after constexpr_call
            layout change.
            (cxx_eval_call_expression): Likewise.  Define some local
            variables closer to their first use.  Use unknown_type_node
            instead of NULL_TREE as the "in progress" result.  After
            successully evaluating a call with mce_unknown, also cache the
            result in the corresponding mce_true and mce_false slots.

    Reviewed-by: Jason Merrill <ja...@redhat.com>

Reply via email to