From 3796e3b399875dac8e6d100c7fe662a91a39ba42 Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Thu, 18 Jul 2019 08:38:09 +0000 Subject: [PATCH] re PR tree-optimization/91137 (Wrong code with -O3) PR tree-optimization/91137 * tree-ssa-loop-ivopts.c (struct ivopts_data): New field. (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize): Init, use and fini the above new field. (determine_base_object_1): New function. (determine_base_object): Reimplement using walk_tree. gcc/testsuite PR tree-optimization/91137 * gcc.c-torture/execute/pr91137.c: New test. From-SVN: r273570 --- gcc/ChangeLog | 9 ++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.c-torture/execute/pr91137.c | 34 +++++++ gcc/tree-ssa-loop-ivopts.c | 92 +++++++++++-------- 4 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr91137.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b545a034e57..e7ba87ac2e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-18 Bin Cheng + + PR tree-optimization/91137 + * tree-ssa-loop-ivopts.c (struct ivopts_data): New field. + (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize): + Init, use and fini the above new field. + (determine_base_object_1): New function. + (determine_base_object): Reimplement using walk_tree. + 2019-07-18 Richard Sandiford * basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f9f17893295..0bbbd8ad1b7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-18 Bin Cheng + + PR tree-optimization/91137 + * gcc.c-torture/execute/pr91137.c: New test. + 2019-07-18 Richard Sandiford * c-c++-common/pr53633-2.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr91137.c b/gcc/testsuite/gcc.c-torture/execute/pr91137.c new file mode 100644 index 00000000000..aa6bb6ca021 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr91137.c @@ -0,0 +1,34 @@ +long long a; +unsigned b; +int c[70]; +int d[70][70]; +int e; + +__attribute__ ((noinline)) void f(long long *g, int p2) { + *g = p2; +} + +__attribute__ ((noinline)) void fn2() { + for (int j = 0; j < 70; j++) { + for (int i = 0; i < 70; i++) { + if (b) + c[i] = 0; + for (int l = 0; l < 70; l++) + d[i][1] = d[l][i]; + } + for (int k = 0; k < 70; k++) + e = c[0]; + } +} + +int main() { + b = 5; + for (int j = 0; j < 70; ++j) + c[j] = 2075593088; + fn2(); + f(&a, e); + if (a) + __builtin_abort(); + return 0; +} + diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index fd5e99b3886..43ba4295d57 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -591,6 +591,9 @@ struct ivopts_data /* The common candidates. */ vec iv_common_cands; + /* Hash map recording base object information of tree exp. */ + hash_map *base_object_map; + /* The maximum invariant variable id. */ unsigned max_inv_var_id; @@ -1043,61 +1046,68 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data) data->vcands.create (20); data->inv_expr_tab = new hash_table (10); data->name_expansion_cache = NULL; + data->base_object_map = NULL; data->iv_common_cand_tab = new hash_table (10); data->iv_common_cands.create (20); decl_rtl_to_reset.create (20); gcc_obstack_init (&data->iv_obstack); } -/* Returns a memory object to that EXPR points. In case we are able to - determine that it does not point to any such object, NULL is returned. */ +/* walk_tree callback for determine_base_object. */ static tree -determine_base_object (tree expr) +determine_base_object_1 (tree *tp, int *walk_subtrees, void *wdata) { - enum tree_code code = TREE_CODE (expr); - tree base, obj; - - /* If this is a pointer casted to any type, we need to determine - the base object for the pointer; so handle conversions before - throwing away non-pointer expressions. */ - if (CONVERT_EXPR_P (expr)) - return determine_base_object (TREE_OPERAND (expr, 0)); - - if (!POINTER_TYPE_P (TREE_TYPE (expr))) - return NULL_TREE; - - switch (code) + tree_code code = TREE_CODE (*tp); + tree obj = NULL_TREE; + if (code == ADDR_EXPR) { - case INTEGER_CST: - return NULL_TREE; - - case ADDR_EXPR: - obj = TREE_OPERAND (expr, 0); - base = get_base_address (obj); - + tree base = get_base_address (TREE_OPERAND (*tp, 0)); if (!base) - return expr; - - if (TREE_CODE (base) == MEM_REF) - return determine_base_object (TREE_OPERAND (base, 0)); + obj = *tp; + else if (TREE_CODE (base) != MEM_REF) + obj = fold_convert (ptr_type_node, build_fold_addr_expr (base)); + } + else if (code == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*tp))) + obj = fold_convert (ptr_type_node, *tp); - return fold_convert (ptr_type_node, - build_fold_addr_expr (base)); + if (!obj) + { + if (!EXPR_P (*tp)) + *walk_subtrees = 0; - case POINTER_PLUS_EXPR: - return determine_base_object (TREE_OPERAND (expr, 0)); + return NULL_TREE; + } + /* Record special node for multiple base objects and stop. */ + if (*static_cast (wdata)) + { + *static_cast (wdata) = integer_zero_node; + return integer_zero_node; + } + /* Record the base object and continue looking. */ + *static_cast (wdata) = obj; + return NULL_TREE; +} - case PLUS_EXPR: - case MINUS_EXPR: - /* Pointer addition is done solely using POINTER_PLUS_EXPR. */ - gcc_unreachable (); +/* Returns a memory object to that EXPR points with caching. Return NULL if we + are able to determine that it does not point to any such object; specially + return integer_zero_node if EXPR contains multiple base objects. */ - default: - if (POLY_INT_CST_P (expr)) - return NULL_TREE; - return fold_convert (ptr_type_node, expr); +static tree +determine_base_object (struct ivopts_data *data, tree expr) +{ + tree *slot, obj = NULL_TREE; + if (data->base_object_map) + { + if ((slot = data->base_object_map->get(expr)) != NULL) + return *slot; } + else + data->base_object_map = new hash_map; + + (void) walk_tree_without_duplicates (&expr, determine_base_object_1, &obj); + data->base_object_map->put (expr, obj); + return obj; } /* Return true if address expression with non-DECL_P operand appears @@ -1155,7 +1165,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step, } iv->base = base; - iv->base_object = determine_base_object (base); + iv->base_object = determine_base_object (data, base); iv->step = step; iv->biv_p = false; iv->nonlin_use = NULL; @@ -7527,6 +7537,8 @@ tree_ssa_iv_optimize_finalize (struct ivopts_data *data) delete data->inv_expr_tab; data->inv_expr_tab = NULL; free_affine_expand_cache (&data->name_expansion_cache); + if (data->base_object_map) + delete data->base_object_map; delete data->iv_common_cand_tab; data->iv_common_cand_tab = NULL; data->iv_common_cands.release (); -- 2.30.2