Commit 2586ba4b by Richard Guenther Committed by Richard Biener

re PR tree-optimization/39804 (internal compiler error: in propagate_necessity,…

re PR tree-optimization/39804 (internal compiler error: in propagate_necessity, at tree-ssa-dce.c:754)

2009-04-18  Richard Guenther  <rguenther@suse.de>

	PR middle-end/39804
	* tree-ssa-ccp.c (fold_stmt_1): New function factored from ...
	(fold_stmt): ... this and ...
	(fold_stmt_inplace): ... this.
	(fold_stmt_1): Fold references in calls and asms.
	* tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt.

	* gcc.target/i386/pr39804.c: New testcase.

From-SVN: r146314
parent 1eefab17
2009-04-18 Richard Guenther <rguenther@suse.de>
PR middle-end/39804
* tree-ssa-ccp.c (fold_stmt_1): New function factored from ...
(fold_stmt): ... this and ...
(fold_stmt_inplace): ... this.
(fold_stmt_1): Fold references in calls and asms.
* tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt.
2009-04-18 Kazu Hirata <kazu@codesourcery.com>
* tree-vrp.c (ssa_name_nonzero_p): Remove.
......
2009-04-18 Richard Guenther <rguenther@suse.de>
PR middle-end/39804
* gcc.target/i386/pr39804.c: New testcase.
2009-04-18 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/i386/pr39496.c: Compile with -mtune=i686.
......
/* { dg-do compile } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O" } */
typedef unsigned char u8;
struct __large_struct { unsigned long buf[100]; };
static inline __attribute__((always_inline)) unsigned long
__copy_from_user_inatomic(void *to, const void *from, unsigned long n)
{
unsigned long ret = 0;
asm volatile("1: mov""b"" %2,%""b""1\n" "2:\n"
".section .fixup,\"ax\"\n"
"3: mov %3,%0\n"
" xor""b"" %""b""1,%""b""1\n"
" jmp 2b\n"
".previous\n"
" .section __ex_table,\"a\"\n"
" " ".balign 4" " " "\n"
" " ".long" " " "1b" "," "3b" "\n"
" .previous\n"
: "=r" (ret), "=q"(*(u8 *)to)
: "m" ((*(struct __large_struct *)(from))), "i" (1), "0" (ret));
return ret;
}
void romchecksum(const unsigned char *rom, unsigned char c)
{
unsigned char sum;
for (sum = 0;
!__copy_from_user_inatomic(&(c), ( typeof(c) *)(rom++), sizeof(c));)
sum += c;
}
......@@ -1574,7 +1574,8 @@ remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
gimple stmt = gsi_stmt (*gsi);
/* The folded result must still be a conditional statement. */
fold_stmt_inplace (stmt);
fold_stmt (gsi);
gcc_assert (gsi_stmt (*gsi) == stmt);
data->may_branch = true;
......
......@@ -2836,43 +2836,81 @@ fold_gimple_call (gimple_stmt_iterator *gsi)
return false;
}
/* Fold the statement pointed to by GSI. In some cases, this function may
replace the whole statement with a new one. Returns true iff folding
makes any changes.
The statement pointed to by GSI should be in valid gimple form but may
be in unfolded state as resulting from for example constant propagation
which can produce *&x = 0. */
/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument
distinguishes both cases. */
bool
fold_stmt (gimple_stmt_iterator *gsi)
static bool
fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
{
bool changed = false;
gimple stmt = gsi_stmt (*gsi);
unsigned i;
/* Fold the main computation performed by the statement. */
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
{
unsigned old_num_ops = gimple_num_ops (stmt);
tree new_rhs = fold_gimple_assign (gsi);
if (new_rhs != NULL_TREE)
if (new_rhs != NULL_TREE
&& (!inplace
|| get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
{
gimple_assign_set_rhs_from_tree (gsi, new_rhs);
changed = true;
}
break;
}
case GIMPLE_COND:
changed |= fold_gimple_cond (stmt);
break;
case GIMPLE_CALL:
/* Fold *& in call arguments. */
for (i = 0; i < gimple_call_num_args (stmt); ++i)
if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
{
tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
if (tmp)
{
gimple_call_set_arg (stmt, i, tmp);
changed = true;
}
}
/* The entire statement may be replaced in this case. */
changed |= fold_gimple_call (gsi);
if (!inplace)
changed |= fold_gimple_call (gsi);
break;
default:
return changed;
case GIMPLE_ASM:
/* Fold *& in asm operands. */
for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
{
tree link = gimple_asm_output_op (stmt, i);
tree op = TREE_VALUE (link);
if (REFERENCE_CLASS_P (op)
&& (op = maybe_fold_reference (op, true)) != NULL_TREE)
{
TREE_VALUE (link) = op;
changed = true;
}
}
for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
{
tree link = gimple_asm_input_op (stmt, i);
tree op = TREE_VALUE (link);
if (REFERENCE_CLASS_P (op)
&& (op = maybe_fold_reference (op, false)) != NULL_TREE)
{
TREE_VALUE (link) = op;
changed = true;
}
}
break;
default:;
}
stmt = gsi_stmt (*gsi);
......@@ -2895,6 +2933,19 @@ fold_stmt (gimple_stmt_iterator *gsi)
return changed;
}
/* Fold the statement pointed to by GSI. In some cases, this function may
replace the whole statement with a new one. Returns true iff folding
makes any changes.
The statement pointed to by GSI should be in valid gimple form but may
be in unfolded state as resulting from for example constant propagation
which can produce *&x = 0. */
bool
fold_stmt (gimple_stmt_iterator *gsi)
{
return fold_stmt_1 (gsi, false);
}
/* Perform the minimal folding on statement STMT. Only operations like
*&x created by constant propagation are handled. The statement cannot
be replaced with a new one. Return true if the statement was
......@@ -2906,51 +2957,9 @@ fold_stmt (gimple_stmt_iterator *gsi)
bool
fold_stmt_inplace (gimple stmt)
{
gimple_stmt_iterator si;
bool changed = false;
/* Fold the main computation performed by the statement. */
switch (gimple_code (stmt))
{
case GIMPLE_ASSIGN:
{
unsigned old_num_ops;
tree new_rhs;
old_num_ops = gimple_num_ops (stmt);
si = gsi_for_stmt (stmt);
new_rhs = fold_gimple_assign (&si);
if (new_rhs != NULL_TREE
&& get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops)
{
gimple_assign_set_rhs_from_tree (&si, new_rhs);
changed = true;
}
gcc_assert (gsi_stmt (si) == stmt);
break;
}
case GIMPLE_COND:
changed |= fold_gimple_cond (stmt);
break;
default:
break;
}
/* Fold *& on the lhs. */
if (gimple_has_lhs (stmt))
{
tree lhs = gimple_get_lhs (stmt);
if (lhs && REFERENCE_CLASS_P (lhs))
{
tree new_lhs = maybe_fold_reference (lhs, true);
if (new_lhs)
{
gimple_set_lhs (stmt, new_lhs);
changed = true;
}
}
}
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
bool changed = fold_stmt_1 (&gsi, true);
gcc_assert (gsi_stmt (gsi) == stmt);
return changed;
}
......
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