Commit 0fbdb0c0 by Richard Biener Committed by Richard Biener

re PR tree-optimization/91178 (Infinite recursion in split_constant_offset in slp after r260289)

2019-07-31  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/91178
	* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
	Use tail-recursion.

	* gcc.dg/torture/pr91178-2.c: New testcase.

From-SVN: r273928
parent 1104467f
2019-07-31 Richard Biener <rguenther@suse.de>
PR tree-optimization/91178
* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
Use tail-recursion.
2019-07-31 Jakub Jelinek <jakub@redhat.com> 2019-07-31 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/91201 PR tree-optimization/91201
......
2019-07-31 Richard Biener <rguenther@suse.de>
PR tree-optimization/91178
* gcc.dg/torture/pr91178-2.c: New testcase.
2019-07-31 Jakub Jelinek <jakub@redhat.com> 2019-07-31 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/91201 PR tree-optimization/91201
......
/* { dg-do compile } */
int a[100][70304];
int b[100];
void c()
{
for (int d = 2; d < 4; d++)
for (int e = 2; e <= 50; e++)
for (int f = 32; f <= 38; f++)
b[d + f] -= a[e][5];
}
...@@ -1249,113 +1249,123 @@ static bool ...@@ -1249,113 +1249,123 @@ static bool
vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops, vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
unsigned int *i_p) unsigned int *i_p)
{ {
unsigned int i = *i_p; bool changed = false;
vn_reference_op_t op = &(*ops)[i]; vn_reference_op_t op;
vn_reference_op_t mem_op = &(*ops)[i - 1];
gimple *def_stmt;
enum tree_code code;
poly_offset_int off;
def_stmt = SSA_NAME_DEF_STMT (op->op0);
if (!is_gimple_assign (def_stmt))
return false;
code = gimple_assign_rhs_code (def_stmt);
if (code != ADDR_EXPR
&& code != POINTER_PLUS_EXPR)
return false;
off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
/* The only thing we have to do is from &OBJ.foo.bar add the offset do
from .foo.bar to the preceding MEM_REF offset and replace the
address with &OBJ. */
if (code == ADDR_EXPR)
{ {
tree addr, addr_base; unsigned int i = *i_p;
poly_int64 addr_offset; op = &(*ops)[i];
vn_reference_op_t mem_op = &(*ops)[i - 1];
addr = gimple_assign_rhs1 (def_stmt); gimple *def_stmt;
addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0), enum tree_code code;
&addr_offset); poly_offset_int off;
/* If that didn't work because the address isn't invariant propagate
the reference tree from the address operation in case the current def_stmt = SSA_NAME_DEF_STMT (op->op0);
dereference isn't offsetted. */ if (!is_gimple_assign (def_stmt))
if (!addr_base return changed;
&& *i_p == ops->length () - 1
&& known_eq (off, 0) code = gimple_assign_rhs_code (def_stmt);
/* This makes us disable this transform for PRE where the if (code != ADDR_EXPR
reference ops might be also used for code insertion which && code != POINTER_PLUS_EXPR)
is invalid. */ return changed;
&& default_vn_walk_kind == VN_WALKREWRITE)
off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
/* The only thing we have to do is from &OBJ.foo.bar add the offset
from .foo.bar to the preceding MEM_REF offset and replace the
address with &OBJ. */
if (code == ADDR_EXPR)
{ {
auto_vec<vn_reference_op_s, 32> tem; tree addr, addr_base;
copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem); poly_int64 addr_offset;
/* Make sure to preserve TBAA info. The only objects not
wrapped in MEM_REFs that can have their address taken are addr = gimple_assign_rhs1 (def_stmt);
STRING_CSTs. */ addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
if (tem.length () >= 2 &addr_offset);
&& tem[tem.length () - 2].opcode == MEM_REF) /* If that didn't work because the address isn't invariant propagate
the reference tree from the address operation in case the current
dereference isn't offsetted. */
if (!addr_base
&& *i_p == ops->length () - 1
&& known_eq (off, 0)
/* This makes us disable this transform for PRE where the
reference ops might be also used for code insertion which
is invalid. */
&& default_vn_walk_kind == VN_WALKREWRITE)
{ {
vn_reference_op_t new_mem_op = &tem[tem.length () - 2]; auto_vec<vn_reference_op_s, 32> tem;
new_mem_op->op0 copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
= wide_int_to_tree (TREE_TYPE (mem_op->op0), /* Make sure to preserve TBAA info. The only objects not
wi::to_poly_wide (new_mem_op->op0)); wrapped in MEM_REFs that can have their address taken are
STRING_CSTs. */
if (tem.length () >= 2
&& tem[tem.length () - 2].opcode == MEM_REF)
{
vn_reference_op_t new_mem_op = &tem[tem.length () - 2];
new_mem_op->op0
= wide_int_to_tree (TREE_TYPE (mem_op->op0),
wi::to_poly_wide (new_mem_op->op0));
}
else
gcc_assert (tem.last ().opcode == STRING_CST);
ops->pop ();
ops->pop ();
ops->safe_splice (tem);
--*i_p;
return true;
} }
else if (!addr_base
gcc_assert (tem.last ().opcode == STRING_CST); || TREE_CODE (addr_base) != MEM_REF
ops->pop (); || (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
ops->pop (); && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base,
ops->safe_splice (tem); 0))))
--*i_p; return changed;
return true;
off += addr_offset;
off += mem_ref_offset (addr_base);
op->op0 = TREE_OPERAND (addr_base, 0);
}
else
{
tree ptr, ptroff;
ptr = gimple_assign_rhs1 (def_stmt);
ptroff = gimple_assign_rhs2 (def_stmt);
if (TREE_CODE (ptr) != SSA_NAME
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
/* Make sure to not endlessly recurse.
See gcc.dg/tree-ssa/20040408-1.c for an example. Can easily
happen when we value-number a PHI to its backedge value. */
|| SSA_VAL (ptr) == op->op0
|| !poly_int_tree_p (ptroff))
return changed;
off += wi::to_poly_offset (ptroff);
op->op0 = ptr;
} }
if (!addr_base
|| TREE_CODE (addr_base) != MEM_REF
|| (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base, 0))))
return false;
off += addr_offset;
off += mem_ref_offset (addr_base);
op->op0 = TREE_OPERAND (addr_base, 0);
}
else
{
tree ptr, ptroff;
ptr = gimple_assign_rhs1 (def_stmt);
ptroff = gimple_assign_rhs2 (def_stmt);
if (TREE_CODE (ptr) != SSA_NAME
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
/* Make sure to not endlessly recurse.
See gcc.dg/tree-ssa/20040408-1.c for an example. Can easily
happen when we value-number a PHI to its backedge value. */
|| SSA_VAL (ptr) == op->op0
|| !poly_int_tree_p (ptroff))
return false;
off += wi::to_poly_offset (ptroff); mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
op->op0 = ptr; if (tree_fits_shwi_p (mem_op->op0))
mem_op->off = tree_to_shwi (mem_op->op0);
else
mem_op->off = -1;
/* ??? Can end up with endless recursion here!?
gcc.c-torture/execute/strcmp-1.c */
if (TREE_CODE (op->op0) == SSA_NAME)
op->op0 = SSA_VAL (op->op0);
if (TREE_CODE (op->op0) != SSA_NAME)
op->opcode = TREE_CODE (op->op0);
changed = true;
} }
/* Tail-recurse. */
while (TREE_CODE (op->op0) == SSA_NAME);
mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off); /* Fold a remaining *&. */
if (tree_fits_shwi_p (mem_op->op0)) if (TREE_CODE (op->op0) == ADDR_EXPR)
mem_op->off = tree_to_shwi (mem_op->op0);
else
mem_op->off = -1;
/* ??? Can end up with endless recursion here!?
gcc.c-torture/execute/strcmp-1.c */
if (TREE_CODE (op->op0) == SSA_NAME)
op->op0 = SSA_VAL (op->op0);
if (TREE_CODE (op->op0) != SSA_NAME)
op->opcode = TREE_CODE (op->op0);
/* And recurse. */
if (TREE_CODE (op->op0) == SSA_NAME)
vn_reference_maybe_forwprop_address (ops, i_p);
else if (TREE_CODE (op->op0) == ADDR_EXPR)
vn_reference_fold_indirect (ops, i_p); vn_reference_fold_indirect (ops, i_p);
return true;
return changed;
} }
/* Optimize the reference REF to a constant if possible or return /* Optimize the reference REF to a constant if possible or return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment