]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-ssa-ccp.c (likely_value): Calls are not all varying.
authorRichard Guenther <rguenther@suse.de>
Fri, 8 Aug 2008 15:01:05 +0000 (15:01 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 8 Aug 2008 15:01:05 +0000 (15:01 +0000)
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.

* gcc.dg/tree-ssa/ssa-ccp-20.c: New testcase.

From-SVN: r138882

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index f3ba5675bcf0355a31ba10fcbf024fa5560e1949..5c6811c214654b76524886e7275eb376d840b261 100644 (file)
@@ -1,3 +1,10 @@
+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
index d930e38ce957812a2e32b0f0bcb4bae021664499..ba897b0311da65de465d8f4b7755616954f69db0 100644 (file)
@@ -1,3 +1,7 @@
+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
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 (file)
index 0000000..63febd0
--- /dev/null
@@ -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" } } */
index b867bba08d5e02033f4ff911b4866afec823f94e..af102cd25e1338e83744b4e89b808bc361cac8e2 100644 (file)
@@ -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:
       {