aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c15
-rw-r--r--gcc/tree-ssa-ccp.c66
4 files changed, 75 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f3ba567..5c6811c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2008-08-08 Richard Guenther <rguenther@suse.de>
+ * tree-ssa-ccp.c (likely_value): Calls are not all varying.
+ (surely_varying_stmt_p): Calls are varying only if they are
+ non-builtin and not indirect or have no result.
+ (ccp_fold): Re-instantiate code before the tuples merge.
+
+2008-08-08 Richard Guenther <rguenther@suse.de>
+
PR tree-optimization/37056
* gimple.h (gimple_assign_rhs_class): New helper function.
* tree-ssa-loop-niter.c (get_val_for): Fix tuplification, handle
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d930e38..ba897b0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2008-08-08 Richard Guenther <rguenther@suse.de>
+ * gcc.dg/tree-ssa/ssa-ccp-20.c: New testcase.
+
+2008-08-08 Richard Guenther <rguenther@suse.de>
+
PR tree-optimization/37056
* gcc.c-torture/compile/pr37056.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c
new file mode 100644
index 0000000..63febd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp1" } */
+
+/* Make sure CCP propagates through indirect calls. */
+
+int foo (void)
+{
+ int i = -5;
+ int (*fn)(int) = __builtin_abs;
+ int j = fn(i);
+ return j + 5;
+}
+
+/* { dg-final { scan-tree-dump "return 10;" "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index b867bba..af102cd 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -528,17 +528,10 @@ likely_value (gimple stmt)
&& !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return VARYING;
- /* A GIMPLE_CALL is assumed to be varying. NOTE: This may be overly
- conservative, in the presence of const and pure calls. */
- if (code == GIMPLE_CALL)
- return VARYING;
-
/* Note that only a GIMPLE_SINGLE_RHS assignment can satisfy
is_gimple_min_invariant, so we do not consider calls or
other forms of assignment. */
- if (code == GIMPLE_ASSIGN
- && (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
- == GIMPLE_SINGLE_RHS)
+ if (gimple_assign_single_p (stmt)
&& is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
return CONSTANT;
@@ -630,15 +623,23 @@ surely_varying_stmt_p (gimple stmt)
return true;
}
- /* If it contains a call, it is varying. */
+ /* If it is a call and does not return a value or is not a
+ builtin and not an indirect call, it is varying. */
if (is_gimple_call (stmt))
- return true;
+ {
+ tree fndecl;
+ if (!gimple_call_lhs (stmt)
+ || ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+ && DECL_BUILT_IN (fndecl)))
+ return true;
+ }
/* Anything other than assignments and conditional jumps are not
interesting for CCP. */
if (gimple_code (stmt) != GIMPLE_ASSIGN
- && (gimple_code (stmt) != GIMPLE_COND)
- && (gimple_code (stmt) != GIMPLE_SWITCH))
+ && gimple_code (stmt) != GIMPLE_COND
+ && gimple_code (stmt) != GIMPLE_SWITCH
+ && gimple_code (stmt) != GIMPLE_CALL)
return true;
return false;
@@ -1034,11 +1035,42 @@ ccp_fold (gimple stmt)
break;
case GIMPLE_CALL:
- /* It may be possible to fold away calls to builtin functions if
- their arguments are constants. At present, such folding will not
- be attempted, as likely_value classifies all calls as VARYING. */
- gcc_unreachable ();
- break;
+ {
+ tree fn = gimple_call_fn (stmt);
+ prop_value_t *val;
+
+ if (TREE_CODE (fn) == SSA_NAME)
+ {
+ val = get_value (fn);
+ if (val->lattice_val == CONSTANT)
+ fn = val->value;
+ }
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
+ {
+ tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
+ tree call, retval;
+ unsigned i;
+ for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ {
+ args[i] = gimple_call_arg (stmt, i);
+ if (TREE_CODE (args[i]) == SSA_NAME)
+ {
+ val = get_value (args[i]);
+ if (val->lattice_val == CONSTANT)
+ args[i] = val->value;
+ }
+ }
+ call = build_call_array (gimple_call_return_type (stmt),
+ fn, gimple_call_num_args (stmt), args);
+ retval = fold_call_expr (call, false);
+ if (retval)
+ /* fold_call_expr wraps the result inside a NOP_EXPR. */
+ STRIP_NOPS (retval);
+ return retval;
+ }
+ return NULL_TREE;
+ }
case GIMPLE_COND:
{