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
This commit is contained in:
Bin Cheng 2019-07-18 08:38:09 +00:00 committed by Bin Cheng
parent f1f1054190
commit 3796e3b399
4 changed files with 104 additions and 44 deletions

View file

@ -1,3 +1,12 @@
2019-07-18 Bin Cheng <bin.linux@linux.alibaba.com>
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 <richard.sandiford@arm.com>
* basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro.

View file

@ -1,3 +1,8 @@
2019-07-18 Bin Cheng <bin.linux@linux.alibaba.com>
PR tree-optimization/91137
* gcc.c-torture/execute/pr91137.c: New test.
2019-07-18 Richard Sandiford <richard.sandiford@arm.com>
* c-c++-common/pr53633-2.c: New test.

View file

@ -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;
}

View file

@ -591,6 +591,9 @@ struct ivopts_data
/* The common candidates. */
vec<iv_common_cand *> iv_common_cands;
/* Hash map recording base object information of tree exp. */
hash_map<tree, tree> *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<iv_inv_expr_hasher> (10);
data->name_expansion_cache = NULL;
data->base_object_map = NULL;
data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (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));
return fold_convert (ptr_type_node,
build_fold_addr_expr (base));
case POINTER_PLUS_EXPR:
return determine_base_object (TREE_OPERAND (expr, 0));
case PLUS_EXPR:
case MINUS_EXPR:
/* Pointer addition is done solely using POINTER_PLUS_EXPR. */
gcc_unreachable ();
default:
if (POLY_INT_CST_P (expr))
return NULL_TREE;
return fold_convert (ptr_type_node, expr);
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);
if (!obj)
{
if (!EXPR_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
/* Record special node for multiple base objects and stop. */
if (*static_cast<tree *> (wdata))
{
*static_cast<tree *> (wdata) = integer_zero_node;
return integer_zero_node;
}
/* Record the base object and continue looking. */
*static_cast<tree *> (wdata) = obj;
return NULL_TREE;
}
/* 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. */
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<tree, tree>;
(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 ();