On Thu, Jun 16, 2016 at 11:28:48AM -0400, Jason Merrill wrote:
> gimple_predicate
> rhs_predicate_for (tree lhs)
> {
> - if (is_gimple_reg (lhs))
> + if (will_be_gimple_reg (lhs))
> return is_gimple_reg_rhs_or_call;
> else
> return is_gimple_mem_rhs_or_call;
> @@ -4778,10 +4811,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
> @@ -4799,6 +4828,10 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p,
> gimple_seq *post_p,
> 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;
> +
> /* In case of va_arg internal fn wrappped in a WITH_SIZE_EXPR, add the type
> size as argument to the call. */
> if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
I wonder if instead of trying to guess early what we'll gimplify into it
wouldn't be better to gimplify *from_p twice, first time with a predicate
that would assume *to_p could be gimplified into is_gimple_ref, but
guarantee there are no side-effects (so that those aren't evaluated
after lhs side-effects), and second time if needed (if *to_p didn't end up
being is_gimple_reg). So something like a new predicate like:
static bool
is_whatever (tree t)
{
/* For calls, as there are side-effects, assume lhs might not be
is_gimple_reg. */
if (TREE_CODE (t) == CALL_EXPR && is_gimple_reg_type (TREE_TYPE (t)))
return is_gimple_val (t);
/* For other side effects, also make sure those are evaluated before
side-effects in lhs. */
if (TREE_THIS_VOLATILE (t))
return is_gimple_mem_rhs_or_call (t);
/* Otherwise, optimistically assume lhs will be is_gimple_reg. */
return is_gimple_reg_rhs_or_call (t);
}
and then do in gimplify_modify_expr:
ret = gimplify_expr (from_p, pre_p, post_p,
is_gimple_reg (*to_p)
? is_gimple_reg_rhs_or_call : is_whatever,
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;
if (!is_gimple_reg (*to_p) && !is_gimple_mem_rhs_or_call (*from_p))
{
ret = gimplify_expr (from_p, pre_p, post_p, is_gimple_mem_rhs_or_call,
fb_rvalue);
if (ret == GS_ERROR)
return ret;
}
Or if you want to guess if *to_p will be is_gimple_reg or not after
gimplification, do it just very conservatively and let the more difficult
to predict cases handled worst case by forcing something into a temporary
with the above code.
Jakub