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
commit acd8bc5cb8efa16b913b9a41c25fc8810a4a7461
Author: Jason Merrill <ja...@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