re PR tree-optimization/42438 (Fix for PR38819 is too conservative)

2010-01-03  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/42438
	* tree-ssa-pre.c (struct bb_bitmap_sets): Add
	contains_may_not_return_call flag.
	(BB_MAY_NOTRETURN): New.
	(valid_in_sets): Trapping nary operations are not valid
	in blocks that may not return.
	(insert_into_preds_of_block): Remove check for trapping
	expressions.
	(compute_avail): Compute also BB_MAY_NOTRETURN.

	* gcc.dg/tree-ssa/ssa-pre-27.c: New testcase.

From-SVN: r155584
This commit is contained in:
Richard Guenther 2010-01-03 12:06:02 +00:00 committed by Richard Biener
parent c41b7b1364
commit a19eb9d236
4 changed files with 78 additions and 11 deletions

View File

@ -1,3 +1,15 @@
2010-01-03 Richard Guenther <rguenther@suse.de>
PR tree-optimization/42438
* tree-ssa-pre.c (struct bb_bitmap_sets): Add
contains_may_not_return_call flag.
(BB_MAY_NOTRETURN): New.
(valid_in_sets): Trapping nary operations are not valid
in blocks that may not return.
(insert_into_preds_of_block): Remove check for trapping
expressions.
(compute_avail): Compute also BB_MAY_NOTRETURN.
2010-01-03 Gerald Pfeifer <gerald@pfeifer.com>
* doc/invoke.texi: Add 2010 to copyright years.

View File

@ -1,3 +1,8 @@
2010-01-03 Richard Guenther <rguenther@suse.de>
PR tree-optimization/42438
* gcc.dg/tree-ssa/ssa-pre-27.c: New testcase.
2010-01-02 Richard Guenther <rguenther@suse.de>
PR testsuite/41651

View File

@ -0,0 +1,29 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-pre" } */
int foo (int i, int j, int b)
{
int res = 0;
if (b)
res = i/j;
/* We should insert the possibly trapping i/j. */
res += i/j;
return res;
}
extern void bar (void);
int foo2 (int i, int j, int b)
{
int res = 0;
if (b)
res = i/j;
/* But we fail so here because of the possibly not returning
call in the same basic-block. */
res += i/j;
bar ();
return res;
}
/* { dg-final { scan-tree-dump-times "# prephitmp" 1 "pre" } } */
/* { dg-final { scan-tree-dump-times "# prephitmp" 2 "pre" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -382,11 +382,14 @@ typedef struct bb_bitmap_sets
bitmap expr_dies;
/* True if we have visited this block during ANTIC calculation. */
unsigned int visited:1;
unsigned int visited : 1;
/* True we have deferred processing this block during ANTIC
calculation until its successor is processed. */
unsigned int deferred : 1;
/* True when the block contains a call that might not return. */
unsigned int contains_may_not_return_call : 1;
} *bb_value_sets_t;
#define EXP_GEN(BB) ((bb_value_sets_t) ((BB)->aux))->exp_gen
@ -399,6 +402,7 @@ typedef struct bb_bitmap_sets
#define EXPR_DIES(BB) ((bb_value_sets_t) ((BB)->aux))->expr_dies
#define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
#define BB_DEFERRED(BB) ((bb_value_sets_t) ((BB)->aux))->deferred
#define BB_MAY_NOTRETURN(BB) ((bb_value_sets_t) ((BB)->aux))->contains_may_not_return_call
/* Basic block list in postorder. */
@ -2032,6 +2036,13 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, pre_expr expr,
return false;
}
}
/* If the NARY may trap make sure the block does not contain
a possible exit point.
??? This is overly conservative if we translate AVAIL_OUT
as the available expression might be after the exit point. */
if (BB_MAY_NOTRETURN (block)
&& vn_nary_may_trap (nary))
return false;
return true;
}
break;
@ -2469,6 +2480,7 @@ compute_antic (void)
BB_VISITED (block) = 0;
BB_DEFERRED (block) = 0;
/* While we are here, give empty ANTIC_IN sets to each block. */
ANTIC_IN (block) = bitmap_set_new ();
PA_IN (block) = bitmap_set_new ();
@ -3187,16 +3199,6 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
}
}
/* Make sure we are not inserting trapping expressions. */
FOR_EACH_EDGE (pred, ei, block->preds)
{
bprime = pred->src;
eprime = avail[bprime->index];
if (eprime->kind == NARY
&& vn_nary_may_trap (PRE_EXPR_NARY (eprime)))
return false;
}
/* Make the necessary insertions. */
FOR_EACH_EDGE (pred, ei, block->preds)
{
@ -3804,6 +3806,8 @@ compute_avail (void)
for (gsi = gsi_start_phis (block); !gsi_end_p (gsi); gsi_next (&gsi))
make_values_for_phi (gsi_stmt (gsi), block);
BB_MAY_NOTRETURN (block) = 0;
/* Now compute value numbers and populate value sets with all
the expressions computed in BLOCK. */
for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
@ -3814,6 +3818,23 @@ compute_avail (void)
stmt = gsi_stmt (gsi);
gimple_set_uid (stmt, stmt_uid++);
/* Cache whether the basic-block has any non-visible side-effect
or control flow.
If this isn't a call or it is the last stmt in the
basic-block then the CFG represents things correctly. */
if (is_gimple_call (stmt)
&& !stmt_ends_bb_p (stmt))
{
/* Non-looping const functions always return normally.
Otherwise the call might not return or have side-effects
that forbids hoisting possibly trapping expressions
before it. */
int flags = gimple_call_flags (stmt);
if (!(flags & ECF_CONST)
|| (flags & ECF_LOOPING_CONST_OR_PURE))
BB_MAY_NOTRETURN (block) = 1;
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
{
pre_expr e = get_or_alloc_expr_for_name (op);