[PATCH] c++: quadratic constexpr behavior for left-assoc logical exprs [PR102780]
Jason Merrill
jason@redhat.com
Wed Oct 27 20:37:04 GMT 2021
On 10/27/21 14:54, Patrick Palka wrote:
> On Tue, 26 Oct 2021, Jakub Jelinek wrote:
>
>> On Tue, Oct 26, 2021 at 05:07:43PM -0400, Patrick Palka wrote:
>>> The performance impact of the other calls to cxx_eval_outermost_const_expr
>>> from p_c_e_1 is probably already mostly mitigated by the constexpr call
>>> cache and the fact that we try to evaluate all calls to constexpr
>>> functions during cp_fold_function anyway (at least with -O). So trial
>>
>> constexpr function bodies don't go through cp_fold_function (intentionally,
>> so that we don't optimize away UB), the bodies are copied before the trees of the
>> normal copy are folded.
>
> Ah right, I had forgotten about that..
>
> Here's another approach that doesn't need to remove trial evaluation for
> &&/||. The idea is to first quietly check if the second operand is
> potentially constant _before_ performing trial evaluation of the first
> operand. This speeds up the case we care about (both operands are
> potentially constant) without regressing any diagnostics. We have to be
> careful about emitting bogus diagnostics when tf_error is set, hence the
> first hunk below which makes p_c_e_1 always proceed quietly first, and
> replay noisily in case of error (similar to how satisfaction works).
>
> Would something like this be preferable?
Seems plausible, though doubling the number of stack frames is a downside.
What did you think of Jakub's suggestion of linearizing the terms?
> -- >8 --
>
> gcc/cp/ChangeLog:
>
> * constexpr.c (potential_constant_expression_1): When tf_error is
> set, proceed quietly first and return true if successful.
> <case TRUTH_*_EXPR>: When tf_error is not set, check potentiality
> of the second operand before performing trial evaluation of the
> first operand rather than after.
>
>
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index 6f83d303cdd..821bd41d994 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -8056,6 +8056,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
> #define RECUR(T,RV) \
> potential_constant_expression_1 ((T), (RV), strict, now, flags, jump_target)
>
> + if (flags & tf_error)
> + {
> + flags &= ~tf_error;
> + if (RECUR (t, want_rval))
> + return true;
> + flags |= tf_error;
> + }
> +
> enum { any = false, rval = true };
> int i;
> tree tmp;
> @@ -8892,13 +8900,16 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
> tmp = boolean_false_node;
> truth:
> {
> - tree op = TREE_OPERAND (t, 0);
> - if (!RECUR (op, rval))
> + tree op0 = TREE_OPERAND (t, 0);
> + tree op1 = TREE_OPERAND (t, 1);
> + if (!RECUR (op0, rval))
> return false;
> + if (!(flags & tf_error) && RECUR (op1, rval))
> + return true;
> if (!processing_template_decl)
> - op = cxx_eval_outermost_constant_expr (op, true);
> - if (tree_int_cst_equal (op, tmp))
> - return RECUR (TREE_OPERAND (t, 1), rval);
> + op0 = cxx_eval_outermost_constant_expr (op0, true);
> + if (tree_int_cst_equal (op0, tmp))
> + return (flags & tf_error) ? RECUR (op1, rval) : false;
> else
> return true;
> }
>
More information about the Gcc-patches
mailing list