re PR tree-optimization/46076 (constant propagation and compile-time math no longer...
authorRichard Guenther <rguenther@suse.de>
Tue, 12 Apr 2011 10:44:15 +0000 (10:44 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 12 Apr 2011 10:44:15 +0000 (10:44 +0000)
2011-04-12  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/46076
* gimple.h (struct gimple_statement_call): Add fntype field.
(gimple_call_fntype): Adjust.
(gimple_call_set_fntype): New function.
* gimple.c (gimple_build_call_1): Set the call function type.
* gimplify.c (gimplify_call_expr): Preserve the function
type the frontend used for the call.
(gimplify_modify_expr): Likewise.
* lto-streamer-in.c (input_gimple_stmt): Input the call stmts
function type.
* lto-streamer-out.c (output_gimple_stmt): Output the call stmts
function type.
* tree-ssa.c (useless_type_conversion_p): Function pointer
conversions are useless.

* gcc.dg/tree-ssa/pr46076.c: Un-XFAIL.

From-SVN: r172310

gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h
gcc/gimplify.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr46076.c
gcc/tree-ssa.c

index c438014b8904a2848a5c3275ca95ec6f958cf226..00108150bf402cb07f4b0f24faa51d28df2bd372 100644 (file)
@@ -1,3 +1,20 @@
+2011-04-12  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/46076
+       * gimple.h (struct gimple_statement_call): Add fntype field.
+       (gimple_call_fntype): Adjust.
+       (gimple_call_set_fntype): New function.
+       * gimple.c (gimple_build_call_1): Set the call function type.
+       * gimplify.c (gimplify_call_expr): Preserve the function
+       type the frontend used for the call.
+       (gimplify_modify_expr): Likewise.
+       * lto-streamer-in.c (input_gimple_stmt): Input the call stmts
+       function type.
+       * lto-streamer-out.c (output_gimple_stmt): Output the call stmts
+       function type.
+       * tree-ssa.c (useless_type_conversion_p): Function pointer
+       conversions are useless.
+
 2011-04-12  Martin Jambor  <mjambor@suse.cz>
 
        * cgraph.h (cgraph_node): Remove function declaration.
index 1cc16d4bc51811a31bfc4a6107716e1259c6fde9..090fc94dd2f6df9edbefa8c80710ac89a7923de6 100644 (file)
@@ -231,6 +231,7 @@ gimple_build_call_1 (tree fn, unsigned nargs)
   if (TREE_CODE (fn) == FUNCTION_DECL)
     fn = build_fold_addr_expr (fn);
   gimple_set_op (s, 1, fn);
+  gimple_call_set_fntype (s, TREE_TYPE (TREE_TYPE (fn)));
   gimple_call_reset_alias_info (s);
   return s;
 }
index be45e4b921de4c0d3ad8feaff08e26105905c570..572cabcc57fb77263f755ecc2db30b534aac431b 100644 (file)
@@ -405,7 +405,10 @@ struct GTY(()) gimple_statement_call
   struct pt_solution call_used;
   struct pt_solution call_clobbered;
 
-  /* [ WORD 13 ]
+  /* [ WORD 13 ]  */
+  tree fntype;
+
+  /* [ WORD 14 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -2001,22 +2004,33 @@ gimple_call_set_lhs (gimple gs, tree lhs)
 }
 
 
-/* Return the tree node representing the function called by call
-   statement GS.  */
+/* Return the function type of the function called by GS.  */
 
 static inline tree
-gimple_call_fn (const_gimple gs)
+gimple_call_fntype (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
-  return gimple_op (gs, 1);
+  return gs->gimple_call.fntype;
 }
 
-/* Return the function type of the function called by GS.  */
+/* Set the type of the function called by GS to FNTYPE.  */
+
+static inline void
+gimple_call_set_fntype (gimple gs, tree fntype)
+{
+  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  gs->gimple_call.fntype = fntype;
+}
+
+
+/* Return the tree node representing the function called by call
+   statement GS.  */
 
 static inline tree
-gimple_call_fntype (const_gimple gs)
+gimple_call_fn (const_gimple gs)
 {
-  return TREE_TYPE (TREE_TYPE (gimple_call_fn (gs)));
+  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  return gimple_op (gs, 1);
 }
 
 /* Return a pointer to the tree node representing the function called by call
index 9afd4ff27fe2b0b297a895448b812e681424aa96..47bcb821f71538371f06dc582d813af0581632c8 100644 (file)
@@ -2290,7 +2290,7 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
 static enum gimplify_status
 gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 {
-  tree fndecl, parms, p;
+  tree fndecl, parms, p, fnptrtype;
   enum gimplify_status ret;
   int i, nargs;
   gimple call;
@@ -2349,6 +2349,9 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
        }
     }
 
+  /* Remember the original function pointer type.  */
+  fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
+
   /* There is a sequence point before the call, so any side effects in
      the calling expression must occur before the actual call.  Force
      gimplify_expr to use an internal post queue.  */
@@ -2436,7 +2439,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 
   /* Verify the function result.  */
   if (want_value && fndecl
-      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
+      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
     {
       error_at (loc, "using result of function returning %<void%>");
       ret = GS_ERROR;
@@ -2488,11 +2491,16 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
         have to do is replicate it as a GIMPLE_CALL tuple.  */
       gimple_stmt_iterator gsi;
       call = gimple_build_call_from_tree (*expr_p);
+      gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
       gimplify_seq_add_stmt (pre_p, call);
       gsi = gsi_last (*pre_p);
       fold_stmt (&gsi);
       *expr_p = NULL_TREE;
     }
+  else
+    /* Remember the original function type.  */
+    CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
+                                    CALL_EXPR_FN (*expr_p));
 
   return ret;
 }
@@ -4607,7 +4615,11 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
     {
       /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
         instead of a GIMPLE_ASSIGN.  */
+      tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
+      CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
+      STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
       assign = gimple_build_call_from_tree (*from_p);
+      gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
       if (!gimple_call_noreturn_p (assign))
        gimple_call_set_lhs (assign, *to_p);
     }
index ddc0cae5328cac5eac1ef1f109ef061f1ccf2ea9..b250023143e9f22d9bf33e5a0397f70629151633 100644 (file)
@@ -1062,6 +1062,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
              op = TREE_OPERAND (op, 0);
            }
        }
+      if (is_gimple_call (stmt))
+       gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
       break;
 
     case GIMPLE_NOP:
index 787f4f2494d3e98cedecb11a295f22ed451a35af..a29cdd5fccf01bb7697156ebc933a1d442a2152b 100644 (file)
@@ -1759,6 +1759,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
            }
          lto_output_tree_ref (ob, op);
        }
+      if (is_gimple_call (stmt))
+       lto_output_tree_ref (ob, gimple_call_fntype (stmt));
       break;
 
     case GIMPLE_NOP:
index 91c792fef95c8952966fb972f0b196826ad6e6d2..105a162f541749995d847662b9c56280a47ea87a 100644 (file)
@@ -1,3 +1,8 @@
+2011-04-12  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/46076
+       * gcc.dg/tree-ssa/pr46076.c: Un-XFAIL.
+
 2011-04-12  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        PR testsuite/21164
index e9dc434ece028dc869e646167be59b17338982b0..a2777a604b9b8627f274d8124660f7c68ec78d32 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do link } */
 /* { dg-options "-O2" } */
 
-extern void link_error (void) { /* XFAIL */ }
+extern void link_error (void);
 
 typedef unsigned char(*Calculable)(void);
 
index 5a41818c575cfee8b4d8f762571348bdaacefa9c..4cd86c6781f6cb2a639ad96af440710924f32945 100644 (file)
@@ -1239,17 +1239,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
          && TYPE_RESTRICT (outer_type))
        return false;
 
-      /* If the outer type is (void *) or a pointer to an incomplete
-        record type or a pointer to an unprototyped function,
-        then the conversion is not necessary.  */
-      if (VOID_TYPE_P (TREE_TYPE (outer_type))
-         || ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
-              || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
-             && (TREE_CODE (TREE_TYPE (outer_type))
-                 == TREE_CODE (TREE_TYPE (inner_type)))
-             && !prototype_p (TREE_TYPE (outer_type))
-             && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (outer_type)),
-                                           TREE_TYPE (TREE_TYPE (inner_type)))))
+      /* If the outer type is (void *), the conversion is not necessary.  */
+      if (VOID_TYPE_P (TREE_TYPE (outer_type)))
        return true;
     }
 
@@ -1305,8 +1296,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
       /* Do not lose casts to function pointer types.  */
       if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
           || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
-         && !useless_type_conversion_p (TREE_TYPE (outer_type),
-                                        TREE_TYPE (inner_type)))
+         && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
+              || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
        return false;
 
       /* We do not care for const qualification of the pointed-to types