aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-04-12 10:44:15 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-04-12 10:44:15 +0000
commitf20ca7258739d74b12cf381293b10f72125732c5 (patch)
treee792618dd649e3a0226cbeeef5d614d64ccfe552
parent78a869ec7471a7c86d992a4cd3a506f5538995fc (diff)
downloadgcc-f20ca7258739d74b12cf381293b10f72125732c5.zip
gcc-f20ca7258739d74b12cf381293b10f72125732c5.tar.gz
gcc-f20ca7258739d74b12cf381293b10f72125732c5.tar.bz2
re PR tree-optimization/46076 (constant propagation and compile-time math no longer happening versus 4.4 and 4.5)
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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/gimple.c1
-rw-r--r--gcc/gimple.h30
-rw-r--r--gcc/gimplify.c16
-rw-r--r--gcc/lto-streamer-in.c2
-rw-r--r--gcc/lto-streamer-out.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr46076.c2
-rw-r--r--gcc/tree-ssa.c17
9 files changed, 68 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c438014..0010815 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 1cc16d4..090fc94 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -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;
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index be45e4b..572cabc 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -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
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9afd4ff..47bcb82 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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);
}
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index ddc0cae..b250023 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -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:
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 787f4f2..a29cdd5 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 91c792f..105a162 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c b/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c
index e9dc434..a2777a6 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c
@@ -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);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 5a41818..4cd86c6 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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