re PR tree-optimization/60823 (ICE in gimple_expand_cfg, at cfgexpand.c:5644)

PR tree-optimization/60823
	* omp-low.c (ipa_simd_modify_function_body): Go through
	all SSA_NAMEs and for those refering to vector arguments
	which are going to be replaced adjust SSA_NAME_VAR and,
	if it is a default definition, change it into a non-default
	definition assigned at the beginning of function from new_decl.
	(ipa_simd_modify_stmt_ops): Rewritten.
	* tree-dfa.c (set_ssa_default_def): When removing default def,
	check for NULL loc instead of NULL *loc.

	* c-c++-common/gomp/pr60823-1.c: New test.
	* c-c++-common/gomp/pr60823-2.c: New test.
	* c-c++-common/gomp/pr60823-3.c: New test.

From-SVN: r209616
This commit is contained in:
Jakub Jelinek 2014-04-22 12:21:32 +02:00 committed by Jakub Jelinek
parent 9d8b4d1ce9
commit 2044a4c3cc
7 changed files with 197 additions and 38 deletions

View File

@ -1,3 +1,15 @@
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/60823
* omp-low.c (ipa_simd_modify_function_body): Go through
all SSA_NAMEs and for those refering to vector arguments
which are going to be replaced adjust SSA_NAME_VAR and,
if it is a default definition, change it into a non-default
definition assigned at the beginning of function from new_decl.
(ipa_simd_modify_stmt_ops): Rewritten.
* tree-dfa.c (set_ssa_default_def): When removing default def,
check for NULL loc instead of NULL *loc.
2014-04-22 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* config/arm/arm.c (arm_hard_regno_mode_ok): Loosen

View File

@ -11281,45 +11281,53 @@ static tree
ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
if (!SSA_VAR_P (*tp))
{
/* Make sure we treat subtrees as a RHS. This makes sure that
when examining the `*foo' in *foo=x, the `foo' get treated as
a use properly. */
wi->is_lhs = false;
wi->val_only = true;
if (TYPE_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
struct ipa_parm_adjustment *cand
= ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
if (!cand)
return NULL_TREE;
tree t = *tp;
tree repl = make_ssa_name (TREE_TYPE (t), NULL);
gimple stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
if (wi->is_lhs)
{
stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl);
gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
SSA_NAME_DEF_STMT (repl) = info->stmt;
}
tree *orig_tp = tp;
if (TREE_CODE (*tp) == ADDR_EXPR)
tp = &TREE_OPERAND (*tp, 0);
struct ipa_parm_adjustment *cand = NULL;
if (TREE_CODE (*tp) == PARM_DECL)
cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
else
{
/* You'd think we could skip the extra SSA variable when
wi->val_only=true, but we may have `*var' which will get
replaced into `*var_array[iter]' and will likely be something
not gimple. */
stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl));
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
if (TYPE_P (*tp))
*walk_subtrees = 0;
}
if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
tree repl = NULL_TREE;
if (cand)
repl = unshare_expr (cand->new_decl);
else
{
if (tp != orig_tp)
{
*walk_subtrees = 0;
bool modified = info->modified;
info->modified = false;
walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
if (!info->modified)
{
info->modified = modified;
return NULL_TREE;
}
info->modified = modified;
repl = *tp;
}
else
return NULL_TREE;
}
if (tp != orig_tp)
{
repl = build_fold_addr_expr (repl);
gimple stmt
= gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl);
repl = gimple_assign_lhs (stmt);
gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
*orig_tp = repl;
}
else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
{
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
*tp = vce;
@ -11328,8 +11336,6 @@ ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
*tp = repl;
info->modified = true;
wi->is_lhs = false;
wi->val_only = true;
return NULL_TREE;
}
@ -11348,7 +11354,7 @@ ipa_simd_modify_function_body (struct cgraph_node *node,
tree retval_array, tree iter)
{
basic_block bb;
unsigned int i, j;
unsigned int i, j, l;
/* Re-use the adjustments array, but this time use it to replace
every function argument use to an offset into the corresponding
@ -11371,6 +11377,46 @@ ipa_simd_modify_function_body (struct cgraph_node *node,
j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
}
l = adjustments.length ();
for (i = 1; i < num_ssa_names; i++)
{
tree name = ssa_name (i);
if (name
&& SSA_NAME_VAR (name)
&& TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
{
for (j = 0; j < l; j++)
if (SSA_NAME_VAR (name) == adjustments[j].base
&& adjustments[j].new_decl)
{
tree base_var;
if (adjustments[j].new_ssa_base == NULL_TREE)
{
base_var
= copy_var_decl (adjustments[j].base,
DECL_NAME (adjustments[j].base),
TREE_TYPE (adjustments[j].base));
adjustments[j].new_ssa_base = base_var;
}
else
base_var = adjustments[j].new_ssa_base;
if (SSA_NAME_IS_DEFAULT_DEF (name))
{
bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
gimple_stmt_iterator gsi = gsi_after_labels (bb);
tree new_decl = unshare_expr (adjustments[j].new_decl);
set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
SSA_NAME_IS_DEFAULT_DEF (name) = 0;
gimple stmt = gimple_build_assign (name, new_decl);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
}
else
SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
}
}
}
struct modify_stmt_info info;
info.adjustments = adjustments;

View File

@ -1,3 +1,10 @@
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/60823
* c-c++-common/gomp/pr60823-1.c: New test.
* c-c++-common/gomp/pr60823-2.c: New test.
* c-c++-common/gomp/pr60823-3.c: New test.
2014-04-22 Ian Bolton <ian.bolton@arm.com>
* gcc.target/arm/anddi_notdi-1.c: New test.

View File

@ -0,0 +1,19 @@
/* PR tree-optimization/60823 */
/* { dg-do compile } */
/* { dg-options "-O2 -fopenmp-simd" } */
#pragma omp declare simd simdlen(4) notinbranch
int
foo (const double c1, const double c2)
{
double z1 = c1, z2 = c2;
int res = 100, i;
for (i = 0; i < 100; i++)
{
res = (z1 * z1 + z2 * z2 > 4.0) ? (i < res ? i : res) : res;
z1 = c1 + z1 * z1 - z2 * z2;
z2 = c2 + 2.0 * z1 * z2;
}
return res;
}

View File

@ -0,0 +1,43 @@
/* PR tree-optimization/60823 */
/* { dg-do run } */
/* { dg-options "-O2 -fopenmp-simd" } */
#pragma omp declare simd simdlen(4) notinbranch
__attribute__((noinline)) int
foo (double c1, double c2)
{
double z1 = c1, z2 = c2;
int res = 100, i;
for (i = 0; i < 5; i++)
{
res = (z1 * z1 + z2 * z2 > 4.0) ? (i < res ? i : res) : res;
z1 = c1 + z1 * z1 - z2 * z2;
z2 = c2 + 2.0 * z1 * z2;
c1 += 0.5;
c2 += 0.5;
}
return res;
}
__attribute__((noinline, noclone)) void
bar (double *x, double *y)
{
asm volatile ("" : : "rm" (x), "rm" (y) : "memory");
}
int
main ()
{
int i;
double c[4] = { 0.0, 1.0, 0.0, 1.0 };
double d[4] = { 0.0, 1.0, 2.0, 0.0 };
int e[4];
bar (c, d);
#pragma omp simd safelen(4)
for (i = 0; i < 4; i++)
e[i] = foo (c[i], d[i]);
if (e[0] != 3 || e[1] != 1 || e[2] != 1 || e[3] != 2)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,32 @@
/* PR tree-optimization/60823 */
/* { dg-do compile } */
/* { dg-options "-O2 -fopenmp-simd -fno-strict-aliasing" } */
void bar (char *, double *);
#if __SIZEOF_DOUBLE__ >= 4
struct S { char c[sizeof (double)]; };
void baz (struct S, struct S);
union U { struct S s; double d; };
#pragma omp declare simd simdlen(4) notinbranch
__attribute__((noinline)) int
foo (double c1, double c2)
{
double *a = &c1;
char *b = (char *) &c1 + 2;
b[-2]++;
b[1]--;
*a++;
c2++;
bar ((char *) &c2 + 1, &c2);
c2 *= 3.0;
bar (b, a);
baz (((union U) { .d = c1 }).s, ((union U) { .d = c2 }).s);
baz (*(struct S *)&c1, *(struct S *)&c2);
return c1 + c2 + ((struct S *)&c1)->c[1];
}
#endif

View File

@ -343,7 +343,7 @@ set_ssa_default_def (struct function *fn, tree var, tree def)
{
loc = htab_find_slot_with_hash (DEFAULT_DEFS (fn), &in,
DECL_UID (var), NO_INSERT);
if (*loc)
if (loc)
{
SSA_NAME_IS_DEFAULT_DEF (*(tree *)loc) = false;
htab_clear_slot (DEFAULT_DEFS (fn), loc);