Commit f20ca725 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/46076 (constant propagation and compile-time math no…

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
parent 78a869ec
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> 2011-04-12 Martin Jambor <mjambor@suse.cz>
* cgraph.h (cgraph_node): Remove function declaration. * cgraph.h (cgraph_node): Remove function declaration.
......
...@@ -231,6 +231,7 @@ gimple_build_call_1 (tree fn, unsigned nargs) ...@@ -231,6 +231,7 @@ gimple_build_call_1 (tree fn, unsigned nargs)
if (TREE_CODE (fn) == FUNCTION_DECL) if (TREE_CODE (fn) == FUNCTION_DECL)
fn = build_fold_addr_expr (fn); fn = build_fold_addr_expr (fn);
gimple_set_op (s, 1, fn); gimple_set_op (s, 1, fn);
gimple_call_set_fntype (s, TREE_TYPE (TREE_TYPE (fn)));
gimple_call_reset_alias_info (s); gimple_call_reset_alias_info (s);
return s; return s;
} }
......
...@@ -405,7 +405,10 @@ struct GTY(()) gimple_statement_call ...@@ -405,7 +405,10 @@ struct GTY(()) gimple_statement_call
struct pt_solution call_used; struct pt_solution call_used;
struct pt_solution call_clobbered; struct pt_solution call_clobbered;
/* [ WORD 13 ] /* [ WORD 13 ] */
tree fntype;
/* [ WORD 14 ]
Operand vector. NOTE! This must always be the last field Operand vector. NOTE! This must always be the last field
of this structure. In particular, this means that this of this structure. In particular, this means that this
structure cannot be embedded inside another one. */ structure cannot be embedded inside another one. */
...@@ -2001,22 +2004,33 @@ gimple_call_set_lhs (gimple gs, tree lhs) ...@@ -2001,22 +2004,33 @@ gimple_call_set_lhs (gimple gs, tree lhs)
} }
/* Return the tree node representing the function called by call /* Return the function type of the function called by GS. */
statement GS. */
static inline tree static inline tree
gimple_call_fn (const_gimple gs) gimple_call_fntype (const_gimple gs)
{ {
GIMPLE_CHECK (gs, GIMPLE_CALL); 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 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 /* Return a pointer to the tree node representing the function called by call
......
...@@ -2290,7 +2290,7 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location) ...@@ -2290,7 +2290,7 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
static enum gimplify_status static enum gimplify_status
gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) 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; enum gimplify_status ret;
int i, nargs; int i, nargs;
gimple call; gimple call;
...@@ -2349,6 +2349,9 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) ...@@ -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 /* There is a sequence point before the call, so any side effects in
the calling expression must occur before the actual call. Force the calling expression must occur before the actual call. Force
gimplify_expr to use an internal post queue. */ 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) ...@@ -2436,7 +2439,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
/* Verify the function result. */ /* Verify the function result. */
if (want_value && fndecl 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%>"); error_at (loc, "using result of function returning %<void%>");
ret = GS_ERROR; ret = GS_ERROR;
...@@ -2488,11 +2491,16 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) ...@@ -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. */ have to do is replicate it as a GIMPLE_CALL tuple. */
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p); call = gimple_build_call_from_tree (*expr_p);
gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
gimplify_seq_add_stmt (pre_p, call); gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p); gsi = gsi_last (*pre_p);
fold_stmt (&gsi); fold_stmt (&gsi);
*expr_p = NULL_TREE; *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; return ret;
} }
...@@ -4607,7 +4615,11 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -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 /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
instead of a GIMPLE_ASSIGN. */ 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); assign = gimple_build_call_from_tree (*from_p);
gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
if (!gimple_call_noreturn_p (assign)) if (!gimple_call_noreturn_p (assign))
gimple_call_set_lhs (assign, *to_p); gimple_call_set_lhs (assign, *to_p);
} }
......
...@@ -1062,6 +1062,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, ...@@ -1062,6 +1062,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
op = TREE_OPERAND (op, 0); op = TREE_OPERAND (op, 0);
} }
} }
if (is_gimple_call (stmt))
gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
break; break;
case GIMPLE_NOP: case GIMPLE_NOP:
......
...@@ -1759,6 +1759,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt) ...@@ -1759,6 +1759,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
} }
lto_output_tree_ref (ob, op); lto_output_tree_ref (ob, op);
} }
if (is_gimple_call (stmt))
lto_output_tree_ref (ob, gimple_call_fntype (stmt));
break; break;
case GIMPLE_NOP: case GIMPLE_NOP:
......
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> 2011-04-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR testsuite/21164 PR testsuite/21164
......
/* { dg-do link } */ /* { dg-do link } */
/* { dg-options "-O2" } */ /* { dg-options "-O2" } */
extern void link_error (void) { /* XFAIL */ } extern void link_error (void);
typedef unsigned char(*Calculable)(void); typedef unsigned char(*Calculable)(void);
......
...@@ -1239,17 +1239,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type) ...@@ -1239,17 +1239,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
&& TYPE_RESTRICT (outer_type)) && TYPE_RESTRICT (outer_type))
return false; return false;
/* If the outer type is (void *) or a pointer to an incomplete /* If the outer type is (void *), the conversion is not necessary. */
record type or a pointer to an unprototyped function, if (VOID_TYPE_P (TREE_TYPE (outer_type)))
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)))))
return true; return true;
} }
...@@ -1305,8 +1296,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type) ...@@ -1305,8 +1296,8 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
/* Do not lose casts to function pointer types. */ /* Do not lose casts to function pointer types. */
if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
&& !useless_type_conversion_p (TREE_TYPE (outer_type), && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
TREE_TYPE (inner_type))) || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
return false; return false;
/* We do not care for const qualification of the pointed-to types /* We do not care for const qualification of the pointed-to types
......
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