This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFA (gimplify): PATCH to implement C++ order of evaluation paper


On Thu, Jul 07, 2016 at 03:18:13PM -0400, Jason Merrill wrote:
> How about this?  I also have a patch to handle assignment order
> entirely in the front end, but my impression has been that you wanted
> to make this change for other reasons as well.

So what exactly is supposed to be the evaluation order for function calls
with lhs in C++17?
Reading
http://en.cppreference.com/w/cpp/language/eval_order
I'm confused.
struct S { S (); ~S (); ... };
S s[1024];
typedef S (*fn) (int, int);
fn a[1024];
void foo (int *i, int *j, int *k, int *l)
{
  s[i[0]++] = (a[j[0]++]) (k[0]++, l[0]++);
}
So, j[0]++ needs to happen first, then k[0]++ and l[0]++ (indeterminately
sequenced), but what about the function call vs. i[0]++?

There is the rule that for E1 = E2 all side-effects of E2 happen before all
side-effects of E1.

I mean, if the function return type is a gimple reg type, then I see no
problem in honoring that, the function call returns a temporary, then the
side-effects of the lhs are evaluated and then it is stored to that lvalue.

But, if the return type is non-POD, then we need to pass the address of the
lhs as invisible reference to the function call, how can we do it if we
can't yet evaluate the side-effects of the lhs?

Perhaps better testcase is:

int bar (int);
void baz ()
{
  s[bar (0)] = (a[bar (1)]) (bar (2), 0);
}

In which order all the 4 calls are made?

What the patch you've posted does is that it gimplifies from_p first,
and gimplify_call_expr will first evaluate bar (1), then bar (2),
but then it is a CALL_EXPR; then it gimplifies the lhs, i.e. bar (0)
call, and finally the indirect call.

> 
> In other news, I convinced the committee to drop function arguments
> from the order of evaluation paper, so we don't have to worry about
> that hit on PUSH_ARGS_REVERSED targets.
> 
> Jason

> commit 8dac319f5647d31568ad9278edeff3607aa1b3cc
> Author: Jason Merrill <jason@redhat.com>
> Date:   Sat Jun 25 19:12:42 2016 +0300
> 
>     	P0145: Refining Expression Order for C++ (assignment)
>     
>     	* gimplify.c (initial_rhs_predicate_for): New.
>     	(gimplfy_modify_expr): Gimplify RHS before LHS.
> 
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 47c4d25..0276588 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -3813,6 +3813,18 @@ rhs_predicate_for (tree lhs)
>      return is_gimple_mem_rhs_or_call;
>  }
>  
> +/* Return the initial guess for an appropriate RHS predicate for this LHS,
> +   before the LHS has been gimplified.  */
> +
> +static gimple_predicate
> +initial_rhs_predicate_for (tree lhs)
> +{
> +  if (is_gimple_reg_type (TREE_TYPE (lhs)))
> +    return is_gimple_reg_rhs_or_call;
> +  else
> +    return is_gimple_mem_rhs_or_call;
> +}
> +
>  /* Gimplify a C99 compound literal expression.  This just means adding
>     the DECL_EXPR before the current statement and using its anonymous
>     decl instead.  */
> @@ -4778,10 +4790,6 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
>       that is what we must do here.  */
>    maybe_with_size_expr (from_p);
>  
> -  ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
> -  if (ret == GS_ERROR)
> -    return ret;
> -
>    /* As a special case, we have to temporarily allow for assignments
>       with a CALL_EXPR on the RHS.  Since in GIMPLE a function call is
>       a toplevel statement, when gimplifying the GENERIC expression
> @@ -4794,6 +4802,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
>       reaches the CALL_EXPR.  On return from gimplify_expr, the newly
>       created GIMPLE_CALL <foo> will be the last statement in *PRE_P
>       and all we need to do here is set 'a' to be its LHS.  */
> +  ret = gimplify_expr (from_p, pre_p, post_p,
> +		       initial_rhs_predicate_for (*to_p), fb_rvalue);
> +  if (ret == GS_ERROR)
> +    return ret;
> +
> +  ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
> +  if (ret == GS_ERROR)
> +    return ret;
> +
> +  /* Now that the LHS is gimplified, we know what to use for the RHS.  */
>    ret = gimplify_expr (from_p, pre_p, post_p, rhs_predicate_for (*to_p),
>  		       fb_rvalue);
>    if (ret == GS_ERROR)


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]