From 2044a4c3cc2db3697e62eea701c489378ad54947 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 22 Apr 2014 12:21:32 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 ++ gcc/omp-low.c | 120 ++++++++++++++------ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/c-c++-common/gomp/pr60823-1.c | 19 ++++ gcc/testsuite/c-c++-common/gomp/pr60823-2.c | 43 +++++++ gcc/testsuite/c-c++-common/gomp/pr60823-3.c | 32 ++++++ gcc/tree-dfa.c | 2 +- 7 files changed, 197 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/pr60823-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr60823-2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/pr60823-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80ffa581870..e882ff81db8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-04-22 Jakub Jelinek + + 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 * config/arm/arm.c (arm_hard_regno_mode_ok): Loosen diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 0a46fb7fcfa..d0489e136e2 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 20978b1d8f3..bee26e35d21 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-04-22 Jakub Jelinek + + 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 * gcc.target/arm/anddi_notdi-1.c: New test. diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-1.c b/gcc/testsuite/c-c++-common/gomp/pr60823-1.c new file mode 100644 index 00000000000..5f985724dae --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr60823-1.c @@ -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; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-2.c b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c new file mode 100644 index 00000000000..e0bf570ddca --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c @@ -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; +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-3.c b/gcc/testsuite/c-c++-common/gomp/pr60823-3.c new file mode 100644 index 00000000000..93e9fbe3a16 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr60823-3.c @@ -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 diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index fcf8d80fda4..a1f27587487 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -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);