re PR tree-optimization/58653 (wrong code (segfaults) at -O3 on x86_64-linux-gnu in 64-bit mode (affecting gcc 4.6 to trunk))

2013-11-06  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/58653
	* tree-predcom.c (ref_at_iteration): Rewrite to generate
	a MEM_REF.
	(prepare_initializers_chain): Adjust.

	* gcc.dg/tree-ssa/predcom-6.c: New testcase.
	* gcc.dg/tree-ssa/predcom-7.c: Likewise.

From-SVN: r204458
This commit is contained in:
Richard Biener 2013-11-06 15:00:16 +00:00 committed by Richard Biener
parent 28d31e4074
commit 9f2b860bed
5 changed files with 65 additions and 86 deletions

View File

@ -1,3 +1,10 @@
2013-11-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/58653
* tree-predcom.c (ref_at_iteration): Rewrite to generate
a MEM_REF.
(prepare_initializers_chain): Adjust.
2013-11-06 Andrew MacLeod <amacleod@redhat.com>
* gimple.h (block_in_transaction): Move to basic-block.h and rename.

View File

@ -1,3 +1,9 @@
2013-11-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/58653
* gcc.dg/tree-ssa/predcom-6.c: New testcase.
* gcc.dg/tree-ssa/predcom-7.c: Likewise.
2013-11-05 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-c++-common/cilk-plus/CK/fib.c: Reduced the iteration from

View File

@ -0,0 +1,13 @@
/* { dg-do run } */
int a, c, e[5][2];
unsigned int d;
int
main ()
{
for (d = 0; d < 2; d++)
if (a ? 0 : e[c + 3][d] & e[c + 4][d])
break;
return 0;
}

View File

@ -0,0 +1,18 @@
/* { dg-do run } */
/* { dg-options "-O3 -fdump-tree-pcom-details" } */
int b, f, d[5][2];
unsigned int c;
int
main ()
{
for (c = 0; c < 2; c++)
if (d[b + 3][c] & d[b + 4][c])
if (f)
break;
return 0;
}
/* { dg-final { scan-tree-dump "Executing predictive commoning" "pcom" } } */
/* { dg-final { cleanup-tree-dump "pcom" } } */

View File

@ -1334,90 +1334,29 @@ replace_ref_with (gimple stmt, tree new_tree, bool set, bool in_lhs)
gsi_insert_after (&bsi, new_stmt, GSI_NEW_STMT);
}
/* Returns the reference to the address of REF in the ITER-th iteration of
LOOP, or NULL if we fail to determine it (ITER may be negative). We
try to preserve the original shape of the reference (not rewrite it
as an indirect ref to the address), to make tree_could_trap_p in
prepare_initializers_chain return false more often. */
/* Returns a memory reference to DR in the ITER-th iteration of
the loop it was analyzed in. Append init stmts to STMTS. */
static tree
ref_at_iteration (struct loop *loop, tree ref, int iter)
static tree
ref_at_iteration (data_reference_p dr, int iter, gimple_seq *stmts)
{
tree idx, *idx_p, type, val, op0 = NULL_TREE, ret;
affine_iv iv;
bool ok;
if (handled_component_p (ref))
{
op0 = ref_at_iteration (loop, TREE_OPERAND (ref, 0), iter);
if (!op0)
return NULL_TREE;
}
else if (!INDIRECT_REF_P (ref)
&& TREE_CODE (ref) != MEM_REF)
return unshare_expr (ref);
if (TREE_CODE (ref) == MEM_REF)
{
ret = unshare_expr (ref);
idx = TREE_OPERAND (ref, 0);
idx_p = &TREE_OPERAND (ret, 0);
}
else if (TREE_CODE (ref) == COMPONENT_REF)
{
/* Check that the offset is loop invariant. */
if (TREE_OPERAND (ref, 2)
&& !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
return NULL_TREE;
return build3 (COMPONENT_REF, TREE_TYPE (ref), op0,
unshare_expr (TREE_OPERAND (ref, 1)),
unshare_expr (TREE_OPERAND (ref, 2)));
}
else if (TREE_CODE (ref) == ARRAY_REF)
{
/* Check that the lower bound and the step are loop invariant. */
if (TREE_OPERAND (ref, 2)
&& !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
return NULL_TREE;
if (TREE_OPERAND (ref, 3)
&& !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 3)))
return NULL_TREE;
ret = build4 (ARRAY_REF, TREE_TYPE (ref), op0, NULL_TREE,
unshare_expr (TREE_OPERAND (ref, 2)),
unshare_expr (TREE_OPERAND (ref, 3)));
idx = TREE_OPERAND (ref, 1);
idx_p = &TREE_OPERAND (ret, 1);
}
tree off = DR_OFFSET (dr);
tree coff = DR_INIT (dr);
if (iter == 0)
;
else if (TREE_CODE (DR_STEP (dr)) == INTEGER_CST)
coff = size_binop (PLUS_EXPR, coff,
size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
else
return NULL_TREE;
ok = simple_iv (loop, loop, idx, &iv, true);
if (!ok)
return NULL_TREE;
iv.base = expand_simple_operations (iv.base);
if (integer_zerop (iv.step))
*idx_p = unshare_expr (iv.base);
else
{
type = TREE_TYPE (iv.base);
if (POINTER_TYPE_P (type))
{
val = fold_build2 (MULT_EXPR, sizetype, iv.step,
size_int (iter));
val = fold_build_pointer_plus (iv.base, val);
}
else
{
val = fold_build2 (MULT_EXPR, type, iv.step,
build_int_cst_type (type, iter));
val = fold_build2 (PLUS_EXPR, type, iv.base, val);
}
*idx_p = unshare_expr (val);
}
return ret;
off = size_binop (PLUS_EXPR, off,
size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
tree addr = fold_build_pointer_plus (DR_BASE_ADDRESS (dr), off);
addr = force_gimple_operand_1 (addr, stmts, is_gimple_mem_ref_addr,
NULL_TREE);
return fold_build2 (MEM_REF, TREE_TYPE (DR_REF (dr)),
addr,
fold_convert (reference_alias_ptr_type (DR_REF (dr)),
coff));
}
/* Get the initialization expression for the INDEX-th temporary variable
@ -2376,14 +2315,10 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
if (chain->inits[i] != NULL_TREE)
continue;
init = ref_at_iteration (loop, DR_REF (dr), (int) i - n);
if (!init)
return false;
init = ref_at_iteration (dr, (int) i - n, &stmts);
if (!chain->all_always_accessed && tree_could_trap_p (init))
return false;
init = force_gimple_operand (init, &stmts, false, NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (entry, stmts);