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> 2009-04-18 Kazu Hirata <kazu@codesourcery.com>
* tree-vrp.c (ssa_name_nonzero_p): Remove. * 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> 2009-04-18 Eric Botcazou <ebotcazou@adacore.com>
* gcc.target/i386/pr39496.c: Compile with -mtune=i686. * 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) ...@@ -1574,7 +1574,8 @@ remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
gimple stmt = gsi_stmt (*gsi); gimple stmt = gsi_stmt (*gsi);
/* The folded result must still be a conditional statement. */ /* 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; data->may_branch = true;
......
...@@ -2836,43 +2836,81 @@ fold_gimple_call (gimple_stmt_iterator *gsi) ...@@ -2836,43 +2836,81 @@ fold_gimple_call (gimple_stmt_iterator *gsi)
return false; return false;
} }
/* Fold the statement pointed to by GSI. In some cases, this function may /* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument
replace the whole statement with a new one. Returns true iff folding distinguishes both cases. */
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 static bool
fold_stmt (gimple_stmt_iterator *gsi) fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
{ {
bool changed = false; bool changed = false;
gimple stmt = gsi_stmt (*gsi); gimple stmt = gsi_stmt (*gsi);
unsigned i;
/* Fold the main computation performed by the statement. */ /* Fold the main computation performed by the statement. */
switch (gimple_code (stmt)) switch (gimple_code (stmt))
{ {
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
{ {
unsigned old_num_ops = gimple_num_ops (stmt);
tree new_rhs = fold_gimple_assign (gsi); 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); gimple_assign_set_rhs_from_tree (gsi, new_rhs);
changed = true; changed = true;
} }
break; break;
} }
case GIMPLE_COND: case GIMPLE_COND:
changed |= fold_gimple_cond (stmt); changed |= fold_gimple_cond (stmt);
break; break;
case GIMPLE_CALL: 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. */ /* The entire statement may be replaced in this case. */
changed |= fold_gimple_call (gsi); if (!inplace)
changed |= fold_gimple_call (gsi);
break; break;
default: case GIMPLE_ASM:
return changed; /* 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; break;
default:;
} }
stmt = gsi_stmt (*gsi); stmt = gsi_stmt (*gsi);
...@@ -2895,6 +2933,19 @@ fold_stmt (gimple_stmt_iterator *gsi) ...@@ -2895,6 +2933,19 @@ fold_stmt (gimple_stmt_iterator *gsi)
return changed; 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 /* Perform the minimal folding on statement STMT. Only operations like
*&x created by constant propagation are handled. The statement cannot *&x created by constant propagation are handled. The statement cannot
be replaced with a new one. Return true if the statement was be replaced with a new one. Return true if the statement was
...@@ -2906,51 +2957,9 @@ fold_stmt (gimple_stmt_iterator *gsi) ...@@ -2906,51 +2957,9 @@ fold_stmt (gimple_stmt_iterator *gsi)
bool bool
fold_stmt_inplace (gimple stmt) fold_stmt_inplace (gimple stmt)
{ {
gimple_stmt_iterator si; gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
bool changed = false; bool changed = fold_stmt_1 (&gsi, true);
gcc_assert (gsi_stmt (gsi) == stmt);
/* 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;
}
}
}
return changed; 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