diff mbox

RFC (gimplify, openmp): PATCH to is_gimple_reg to check DECL_HAS_VALUE_EXPR_P

Message ID 2b6c588f-2996-07ab-eef3-b8548d65c88e@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 10, 2016, 7:48 p.m. UTC
While working on another issue I noticed that is_gimple_reg was happily 
accepting VAR_DECLs with DECL_VALUE_EXPR even when later gimplification 
would replace them with something that is_gimple_reg doesn't like, 
leading to trouble.  So I've modified is_gimple_reg to check the VALUE_EXPR.

But this breaks a couple of libgomp testcases, namely 
libgomp.c++/member-[45].C.  This seems to be a latent bug in 
gimplify_omp_for:

>       /* If DECL is not a gimple register, create a temporary variable to act
>          as an iteration counter.  This is valid, since DECL cannot be
>          modified in the body of the loop.  Similarly for any iteration vars
>          in simd with collapse > 1 where the iterator vars must be
>          lastprivate.  */
>       if (orig_for_stmt != for_stmt)
>         var = decl;
>       else if (!is_gimple_reg (decl)
>                || (ort == ORT_SIMD
>                    && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1))
>         {
>           struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
>           /* Make sure omp_add_variable is not called on it prematurely.
>              We call it ourselves a few lines later.  */
>           gimplify_omp_ctxp = NULL;
>           var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
>           gimplify_omp_ctxp = ctx;
>           TREE_OPERAND (t, 0) = var;
>
>           gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));

So we update DECL from VAR in the loop body, but we don't update it 
after the last iteration, when we do the increment but then don't enter 
the body.  As a result, this test fails:

>   #pragma omp parallel for lastprivate (T<Q>::t)
>   for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t += 3)
>     f[T<Q>::t + 2] |= 2;
>   if (T<Q>::t != 33)
>     __builtin_abort ();

Here T<Q>::t ends up with the value 30 because it doesn't get the last 
update.

Thoughts?

Jason

Comments

Richard Biener June 11, 2016, 6:43 p.m. UTC | #1
On June 10, 2016 9:48:45 PM GMT+02:00, Jason Merrill <jason@redhat.com> wrote:
>While working on another issue I noticed that is_gimple_reg was happily
>
>accepting VAR_DECLs with DECL_VALUE_EXPR even when later gimplification
>
>would replace them with something that is_gimple_reg doesn't like, 
>leading to trouble.  So I've modified is_gimple_reg to check the
>VALUE_EXPR.

Can you instead try rejecting them?  I've run into similar issues lately with is_gimple_val.

Richard.

>But this breaks a couple of libgomp testcases, namely 
>libgomp.c++/member-[45].C.  This seems to be a latent bug in 
>gimplify_omp_for:
>
>>       /* If DECL is not a gimple register, create a temporary
>variable to act
>>          as an iteration counter.  This is valid, since DECL cannot
>be
>>          modified in the body of the loop.  Similarly for any
>iteration vars
>>          in simd with collapse > 1 where the iterator vars must be
>>          lastprivate.  */
>>       if (orig_for_stmt != for_stmt)
>>         var = decl;
>>       else if (!is_gimple_reg (decl)
>>                || (ort == ORT_SIMD
>>                    && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1))
>>         {
>>           struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
>>           /* Make sure omp_add_variable is not called on it
>prematurely.
>>              We call it ourselves a few lines later.  */
>>           gimplify_omp_ctxp = NULL;
>>           var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
>>           gimplify_omp_ctxp = ctx;
>>           TREE_OPERAND (t, 0) = var;
>>
>>           gimplify_seq_add_stmt (&for_body, gimple_build_assign
>(decl, var));
>
>So we update DECL from VAR in the loop body, but we don't update it 
>after the last iteration, when we do the increment but then don't enter
>
>the body.  As a result, this test fails:
>
>>   #pragma omp parallel for lastprivate (T<Q>::t)
>>   for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t += 3)
>>     f[T<Q>::t + 2] |= 2;
>>   if (T<Q>::t != 33)
>>     __builtin_abort ();
>
>Here T<Q>::t ends up with the value 30 because it doesn't get the last 
>update.
>
>Thoughts?
>
>Jason
Jakub Jelinek June 11, 2016, 7:30 p.m. UTC | #2
On Sat, Jun 11, 2016 at 08:43:06PM +0200, Richard Biener wrote:
> On June 10, 2016 9:48:45 PM GMT+02:00, Jason Merrill <jason@redhat.com> wrote:
> >While working on another issue I noticed that is_gimple_reg was happily
> >
> >accepting VAR_DECLs with DECL_VALUE_EXPR even when later gimplification
> >
> >would replace them with something that is_gimple_reg doesn't like, 
> >leading to trouble.  So I've modified is_gimple_reg to check the
> >VALUE_EXPR.
> 
> Can you instead try rejecting them?  I've run into similar issues lately with is_gimple_val.

I'm afraid that would break OpenMP badly.
During gimplification, outside of OpenMP contexts we always replace decls
for their DECL_VALUE_EXPR, but inside of OpenMP contexts we do it only for
some decls.  In particular, omp_notice_variable returns whether the
DECL_VALUE_EXPR should be temporarily ignored (if it returns true) or not.
If DECL_VALUE_EXPR is temporarily ignored, it is only for a short time,
in particular until the omplower pass, which makes sure that the right thing
is done with it and everything is regimplified.

Anyway, looking at Jason's patch, I'm really surprised it didn't break far
more, it is fine if such an ignored DECL_VALUE_EXPR is considered
is_gimple_reg.  And I have no idea how else to express this in the IL,
the DECL_VALUE_EXPR is often something already the FEs set, and we really
want to replace it with the values in most uses, just can't allow it if we
want to replace it by something different instead (e.g. privatize in some
OpenMP/OpenACC region).

	Jakub
Richard Biener June 13, 2016, 9:03 a.m. UTC | #3
On Sat, Jun 11, 2016 at 9:30 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Sat, Jun 11, 2016 at 08:43:06PM +0200, Richard Biener wrote:
>> On June 10, 2016 9:48:45 PM GMT+02:00, Jason Merrill <jason@redhat.com> wrote:
>> >While working on another issue I noticed that is_gimple_reg was happily
>> >
>> >accepting VAR_DECLs with DECL_VALUE_EXPR even when later gimplification
>> >
>> >would replace them with something that is_gimple_reg doesn't like,
>> >leading to trouble.  So I've modified is_gimple_reg to check the
>> >VALUE_EXPR.
>>
>> Can you instead try rejecting them?  I've run into similar issues lately with is_gimple_val.
>
> I'm afraid that would break OpenMP badly.
> During gimplification, outside of OpenMP contexts we always replace decls
> for their DECL_VALUE_EXPR, but inside of OpenMP contexts we do it only for
> some decls.  In particular, omp_notice_variable returns whether the
> DECL_VALUE_EXPR should be temporarily ignored (if it returns true) or not.
> If DECL_VALUE_EXPR is temporarily ignored, it is only for a short time,
> in particular until the omplower pass, which makes sure that the right thing
> is done with it and everything is regimplified.

Ugh :/  Feels like OMP lowering should happen during gimplification then.
The PR71104 fix (yes, still pending...) runs into this generally with the
change to first gimplify the RHS and then the LHS for assignments
as it affects how rhs_predicate_for works - I've adjusted rhs_predicate_for like

@@ -3771,7 +3771,9 @@ gimplify_init_ctor_eval (tree object, ve
 gimple_predicate
 rhs_predicate_for (tree lhs)
 {
-  if (is_gimple_reg (lhs))
+  if (is_gimple_reg (lhs)
+      && (! DECL_P (lhs)
+         || ! DECL_HAS_VALUE_EXPR_P (lhs)))
     return is_gimple_reg_rhs_or_call;
   else
     return is_gimple_mem_rhs_or_call;

but I don't like this very much either (it's Jasons change but rejecting
decls with value expr instead).

Richard.

> Anyway, looking at Jason's patch, I'm really surprised it didn't break far
> more, it is fine if such an ignored DECL_VALUE_EXPR is considered
> is_gimple_reg.  And I have no idea how else to express this in the IL,
> the DECL_VALUE_EXPR is often something already the FEs set, and we really
> want to replace it with the values in most uses, just can't allow it if we
> want to replace it by something different instead (e.g. privatize in some
> OpenMP/OpenACC region).
>
>         Jakub
Jakub Jelinek June 13, 2016, 9:11 a.m. UTC | #4
On Mon, Jun 13, 2016 at 11:03:54AM +0200, Richard Biener wrote:
> > I'm afraid that would break OpenMP badly.
> > During gimplification, outside of OpenMP contexts we always replace decls
> > for their DECL_VALUE_EXPR, but inside of OpenMP contexts we do it only for
> > some decls.  In particular, omp_notice_variable returns whether the
> > DECL_VALUE_EXPR should be temporarily ignored (if it returns true) or not.
> > If DECL_VALUE_EXPR is temporarily ignored, it is only for a short time,
> > in particular until the omplower pass, which makes sure that the right thing
> > is done with it and everything is regimplified.
> 
> Ugh :/  Feels like OMP lowering should happen during gimplification then.

That is not really possible.  OMP lowering relies on all the OpenMP clauses
(including implicitly added) to be finalized before it can figure out what
to do.  And to have the OpenMP clauses finalized, you need to gimplify
everything.  So, it is impossible to do it at the same time as
gimplification, it needs to be another pass (whether a separate full pass,
or a "subpass" of the gimplification matters less; though for debugging,
dumps, etc. having it a separate full pass is better; in any case, it needs
another processing of the whole IL, and for the is_gimple_reg case doesn't
change anything, we still need to postpone the DECL_VALUE_EXPR processing
of some decls in certain uses till the second pass or subpass).

	Jakub
Jason Merrill June 13, 2016, 2:05 p.m. UTC | #5
On Mon, Jun 13, 2016 at 5:03 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Sat, Jun 11, 2016 at 9:30 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> On Sat, Jun 11, 2016 at 08:43:06PM +0200, Richard Biener wrote:
>>> On June 10, 2016 9:48:45 PM GMT+02:00, Jason Merrill <jason@redhat.com> wrote:
>>> >While working on another issue I noticed that is_gimple_reg was happily
>>> >
>>> >accepting VAR_DECLs with DECL_VALUE_EXPR even when later gimplification
>>> >
>>> >would replace them with something that is_gimple_reg doesn't like,
>>> >leading to trouble.  So I've modified is_gimple_reg to check the
>>> >VALUE_EXPR.
>>>
>>> Can you instead try rejecting them?  I've run into similar issues lately with is_gimple_val.
>>
>> I'm afraid that would break OpenMP badly.
>> During gimplification, outside of OpenMP contexts we always replace decls
>> for their DECL_VALUE_EXPR, but inside of OpenMP contexts we do it only for
>> some decls.  In particular, omp_notice_variable returns whether the
>> DECL_VALUE_EXPR should be temporarily ignored (if it returns true) or not.
>> If DECL_VALUE_EXPR is temporarily ignored, it is only for a short time,
>> in particular until the omplower pass, which makes sure that the right thing
>> is done with it and everything is regimplified.
>
> Ugh :/  Feels like OMP lowering should happen during gimplification then.
> The PR71104 fix (yes, still pending...) runs into this generally with the
> change to first gimplify the RHS and then the LHS for assignments

Yep, that's what led me here, too.

Jason

> as it affects how rhs_predicate_for works - I've adjusted rhs_predicate_for like

> @@ -3771,7 +3771,9 @@ gimplify_init_ctor_eval (tree object, ve
>  gimple_predicate
>  rhs_predicate_for (tree lhs)
>  {
> -  if (is_gimple_reg (lhs))
> +  if (is_gimple_reg (lhs)
> +      && (! DECL_P (lhs)
> +         || ! DECL_HAS_VALUE_EXPR_P (lhs)))
>      return is_gimple_reg_rhs_or_call;
>    else
>      return is_gimple_mem_rhs_or_call;
>
> but I don't like this very much either (it's Jasons change but rejecting
> decls with value expr instead).
>
> Richard.
>
>> Anyway, looking at Jason's patch, I'm really surprised it didn't break far
>> more, it is fine if such an ignored DECL_VALUE_EXPR is considered
>> is_gimple_reg.  And I have no idea how else to express this in the IL,
>> the DECL_VALUE_EXPR is often something already the FEs set, and we really
>> want to replace it with the values in most uses, just can't allow it if we
>> want to replace it by something different instead (e.g. privatize in some
>> OpenMP/OpenACC region).
>>
>>         Jakub
diff mbox

Patch

commit acd8bc5cb8efa16b913b9a41c25fc8810a4a7461
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jun 10 14:55:54 2016 -0400

    	* gimple-expr.c (is_gimple_reg): Check DECL_HAS_VALUE_EXPR_P.

diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index ed012cc..9016e8c 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -761,6 +761,14 @@  is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
+  /* A variable with DECL_VALUE_EXPR will be replaced by a more complex
+     expression.  */
+  if ((TREE_CODE (t) == VAR_DECL
+       || TREE_CODE (t) == PARM_DECL
+       || TREE_CODE (t) == RESULT_DECL)
+      && DECL_HAS_VALUE_EXPR_P (t))
+    return is_gimple_reg (DECL_VALUE_EXPR (t));
+
   /* Complex and vector values must have been put into SSA-like form.
      That is, no assignments to the individual components.  */
   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE