Commit e36711f3 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/16876 (ICE on testcase with -O3 in fold-const)

2007-06-23  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/16876
	PR middle-end/29478
	* tree.h (CALL_CANNOT_INLINE_P): New macro to access static_flag
	for CALL_EXPRs.
	* tree-inline.c (initialize_inlined_parameters): Do not call
	lang_hooks.tree_inlining.convert_parm_for_inlining.
	* cgraphbuild.c (initialize_inline_failed): Set inline failed
	reason for mismatched types.
	* gimplify.c (gimplify_call_expr): Verify the call expression
	arguments match the called function type signature.  Otherwise
	mark the call expression to be not considered for inlining
	using CALL_CANNOT_INLINE_P flag.
	* ipa-inline.c (cgraph_mark_inline): Honor CALL_CANNOT_INLINE_P on the
	edges call expression.
	(cgraph_decide_inlining_of_small_function): Likewise.
	(cgraph_decide_inlining): Likewise.
	* c-objc-common.h (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
	Remove define.
	* c-tree.h (c_convert_parm_for_inlining): Remove declaration.
	* c-typeck.c (c_convert_parm_for_inlining): Remove.
	* langhooks-def.h (lhd_tree_inlining_convert_parm_for_inlining):
	Remove declaration.
	(LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING): Remove define.
	* langhooks.c (lhd_tree_inlining_convert_parm_for_inlining):
	Remove.
	* langhooks.h (struct lang_hooks_for_tree_inlining): Remove
	convert_parm_for_inlining member.

	* gcc.dg/pr29254.c: The warning is bogus.
	* gcc.dg/warn-1.c: Likewise.
	* gcc.dg/assign-warn-3.c: Likewise.
	* gcc.dg/noncompile/pr16876.c: The testcase is bogus, remove.

From-SVN: r125974
parent 630ef467
2007-06-23 Richard Guenther <rguenther@suse.de>
PR tree-optimization/16876
PR middle-end/29478
* tree.h (CALL_CANNOT_INLINE_P): New macro to access static_flag
for CALL_EXPRs.
* tree-inline.c (initialize_inlined_parameters): Do not call
lang_hooks.tree_inlining.convert_parm_for_inlining.
* cgraphbuild.c (initialize_inline_failed): Set inline failed
reason for mismatched types.
* gimplify.c (gimplify_call_expr): Verify the call expression
arguments match the called function type signature. Otherwise
mark the call expression to be not considered for inlining
using CALL_CANNOT_INLINE_P flag.
* ipa-inline.c (cgraph_mark_inline): Honor CALL_CANNOT_INLINE_P on the
edges call expression.
(cgraph_decide_inlining_of_small_function): Likewise.
(cgraph_decide_inlining): Likewise.
* c-objc-common.h (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
Remove define.
* c-tree.h (c_convert_parm_for_inlining): Remove declaration.
* c-typeck.c (c_convert_parm_for_inlining): Remove.
* langhooks-def.h (lhd_tree_inlining_convert_parm_for_inlining):
Remove declaration.
(LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING): Remove define.
* langhooks.c (lhd_tree_inlining_convert_parm_for_inlining):
Remove.
* langhooks.h (struct lang_hooks_for_tree_inlining): Remove
convert_parm_for_inlining member.
2007-06-23 Richard Earnshaw <rearnsha@arm.com> 2007-06-23 Richard Earnshaw <rearnsha@arm.com>
PR target/31152 PR target/31152
......
...@@ -89,9 +89,6 @@ extern void c_initialize_diagnostics (diagnostic_context *); ...@@ -89,9 +89,6 @@ extern void c_initialize_diagnostics (diagnostic_context *);
#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS #undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \ #define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
c_disregard_inline_limits c_disregard_inline_limits
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
c_convert_parm_for_inlining
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
......
...@@ -577,7 +577,6 @@ extern tree c_start_case (tree); ...@@ -577,7 +577,6 @@ extern tree c_start_case (tree);
extern void c_finish_case (tree); extern void c_finish_case (tree);
extern tree build_asm_expr (tree, tree, tree, tree, bool); extern tree build_asm_expr (tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree); extern tree build_asm_stmt (tree, tree);
extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
extern int c_types_compatible_p (tree, tree); extern int c_types_compatible_p (tree, tree);
extern tree c_begin_compound_stmt (bool); extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (tree, bool); extern tree c_end_compound_stmt (tree, bool);
......
...@@ -4247,37 +4247,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, ...@@ -4247,37 +4247,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
return error_mark_node; return error_mark_node;
} }
/* Convert VALUE for assignment into inlined parameter PARM. ARGNUM
is used for error and warning reporting and indicates which argument
is being processed. */
tree
c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
{
tree ret, type;
/* If FN was prototyped at the call site, the value has been converted
already in convert_arguments.
However, we might see a prototype now that was not in place when
the function call was seen, so check that the VALUE actually matches
PARM before taking an early exit. */
if (!value
|| (TYPE_ARG_TYPES (TREE_TYPE (fn))
&& (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
return value;
type = TREE_TYPE (parm);
ret = convert_for_assignment (type, value,
ic_argpass_nonproto, fn,
fn, argnum);
if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
ret = default_conversion (ret);
return ret;
}
/* If VALUE is a compound expr all of whose expressions are constant, then /* If VALUE is a compound expr all of whose expressions are constant, then
return its value. Otherwise, return error_mark_node. return its value. Otherwise, return error_mark_node.
......
...@@ -99,6 +99,8 @@ initialize_inline_failed (struct cgraph_node *node) ...@@ -99,6 +99,8 @@ initialize_inline_failed (struct cgraph_node *node)
"considered for inlining"); "considered for inlining");
else if (!node->local.inlinable) else if (!node->local.inlinable)
e->inline_failed = N_("function not inlinable"); e->inline_failed = N_("function not inlinable");
else if (CALL_CANNOT_INLINE_P (e->call_stmt))
e->inline_failed = N_("mismatched arguments");
else else
e->inline_failed = N_("function not considered for inlining"); e->inline_failed = N_("function not considered for inlining");
} }
......
...@@ -2058,7 +2058,7 @@ gimplify_arg (tree *expr_p, tree *pre_p) ...@@ -2058,7 +2058,7 @@ gimplify_arg (tree *expr_p, tree *pre_p)
static enum gimplify_status static enum gimplify_status
gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
{ {
tree decl; tree decl, parms, p;
enum gimplify_status ret; enum gimplify_status ret;
int i, nargs; int i, nargs;
...@@ -2124,6 +2124,48 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value) ...@@ -2124,6 +2124,48 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
nargs = call_expr_nargs (*expr_p); nargs = call_expr_nargs (*expr_p);
/* Get argument types for verification. */
decl = get_callee_fndecl (*expr_p);
parms = NULL_TREE;
if (decl)
parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
/* Verify if the type of the argument matches that of the function
declaration. If we cannot verify this or there is a mismatch,
mark the call expression so it doesn't get inlined later. */
if (parms)
{
for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
if (!p
|| TREE_VALUE (p) == error_mark_node
|| CALL_EXPR_ARG (*expr_p, i) == error_mark_node
|| !lang_hooks.types_compatible_p
(TREE_TYPE (CALL_EXPR_ARG (*expr_p, i)), TREE_VALUE (p)))
{
CALL_CANNOT_INLINE_P (*expr_p) = 1;
break;
}
}
else if (decl && DECL_ARGUMENTS (decl))
{
for (i = 0, p = DECL_ARGUMENTS (decl); i < nargs;
i++, p = TREE_CHAIN (p))
if (!p
|| p == error_mark_node
|| CALL_EXPR_ARG (*expr_p, i) == error_mark_node
|| !lang_hooks.types_compatible_p
(TREE_TYPE (CALL_EXPR_ARG (*expr_p, i)), TREE_TYPE (p)))
{
CALL_CANNOT_INLINE_P (*expr_p) = 1;
break;
}
}
else if (nargs != 0)
CALL_CANNOT_INLINE_P (*expr_p) = 1;
/* Finally, gimplify the function arguments. */
for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0); for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
PUSH_ARGS_REVERSED ? i >= 0 : i < nargs; PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
PUSH_ARGS_REVERSED ? i-- : i++) PUSH_ARGS_REVERSED ? i-- : i++)
......
...@@ -288,22 +288,21 @@ cgraph_mark_inline (struct cgraph_edge *edge) ...@@ -288,22 +288,21 @@ cgraph_mark_inline (struct cgraph_edge *edge)
struct cgraph_node *to = edge->caller; struct cgraph_node *to = edge->caller;
struct cgraph_node *what = edge->callee; struct cgraph_node *what = edge->callee;
struct cgraph_edge *e, *next; struct cgraph_edge *e, *next;
int times = 0;
/* Look for all calls, mark them inline and clone recursively /* Look for all calls, mark them inline and clone recursively
all inlined functions. */ all inlined functions. */
for (e = what->callers; e; e = next) for (e = what->callers; e; e = next)
{ {
next = e->next_caller; next = e->next_caller;
if (e->caller == to && e->inline_failed) if (e->caller == to && e->inline_failed
&& !CALL_CANNOT_INLINE_P (e->call_stmt))
{ {
cgraph_mark_inline_edge (e, true); cgraph_mark_inline_edge (e, true);
if (e == edge) if (e == edge)
edge = next; edge = next;
times++;
} }
} }
gcc_assert (times);
return edge; return edge;
} }
...@@ -885,7 +884,7 @@ cgraph_decide_inlining_of_small_functions (void) ...@@ -885,7 +884,7 @@ cgraph_decide_inlining_of_small_functions (void)
} }
gcc_assert (edge->aux); gcc_assert (edge->aux);
edge->aux = NULL; edge->aux = NULL;
if (!edge->inline_failed) if (!edge->inline_failed || CALL_CANNOT_INLINE_P (edge->call_stmt))
continue; continue;
/* When not having profile info ready we don't weight by any way the /* When not having profile info ready we don't weight by any way the
...@@ -1076,7 +1075,7 @@ cgraph_decide_inlining (void) ...@@ -1076,7 +1075,7 @@ cgraph_decide_inlining (void)
for (e = node->callers; e; e = next) for (e = node->callers; e; e = next)
{ {
next = e->next_caller; next = e->next_caller;
if (!e->inline_failed) if (!e->inline_failed || CALL_CANNOT_INLINE_P (e->call_stmt))
continue; continue;
if (cgraph_recursive_inlining_p (e->caller, e->callee, if (cgraph_recursive_inlining_p (e->caller, e->callee,
&e->inline_failed)) &e->inline_failed))
......
...@@ -73,7 +73,6 @@ extern tree lhd_tree_inlining_walk_subtrees (tree *, int *, walk_tree_fn, ...@@ -73,7 +73,6 @@ extern tree lhd_tree_inlining_walk_subtrees (tree *, int *, walk_tree_fn,
extern int lhd_tree_inlining_cannot_inline_tree_fn (tree *); extern int lhd_tree_inlining_cannot_inline_tree_fn (tree *);
extern int lhd_tree_inlining_disregard_inline_limits (tree); extern int lhd_tree_inlining_disregard_inline_limits (tree);
extern int lhd_tree_inlining_auto_var_in_fn_p (tree, tree); extern int lhd_tree_inlining_auto_var_in_fn_p (tree, tree);
extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree, int);
extern void lhd_initialize_diagnostics (struct diagnostic_context *); extern void lhd_initialize_diagnostics (struct diagnostic_context *);
extern tree lhd_callgraph_analyze_expr (tree *, int *, tree); extern tree lhd_callgraph_analyze_expr (tree *, int *, tree);
...@@ -145,8 +144,6 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, ...@@ -145,8 +144,6 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
lhd_tree_inlining_auto_var_in_fn_p lhd_tree_inlining_auto_var_in_fn_p
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \ #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
hook_bool_tree_tree_false hook_bool_tree_tree_false
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
lhd_tree_inlining_convert_parm_for_inlining
#define LANG_HOOKS_TREE_INLINING_INITIALIZER { \ #define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \ LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \
...@@ -154,7 +151,6 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, ...@@ -154,7 +151,6 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS, \ LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS, \
LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \ LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \ LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
} }
#define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR lhd_callgraph_analyze_expr #define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR lhd_callgraph_analyze_expr
......
...@@ -330,18 +330,6 @@ lhd_tree_inlining_auto_var_in_fn_p (tree var, tree fn) ...@@ -330,18 +330,6 @@ lhd_tree_inlining_auto_var_in_fn_p (tree var, tree fn)
|| TREE_CODE (var) == RESULT_DECL)); || TREE_CODE (var) == RESULT_DECL));
} }
/* lang_hooks.tree_inlining.convert_parm_for_inlining performs any
language-specific conversion before assigning VALUE to PARM. */
tree
lhd_tree_inlining_convert_parm_for_inlining (tree parm ATTRIBUTE_UNUSED,
tree value,
tree fndecl ATTRIBUTE_UNUSED,
int argnum ATTRIBUTE_UNUSED)
{
return value;
}
/* lang_hooks.tree_dump.dump_tree: Dump language-specific parts of tree /* lang_hooks.tree_dump.dump_tree: Dump language-specific parts of tree
nodes. Returns nonzero if it does not want the usual dumping of the nodes. Returns nonzero if it does not want the usual dumping of the
second argument. */ second argument. */
......
...@@ -42,7 +42,6 @@ struct lang_hooks_for_tree_inlining ...@@ -42,7 +42,6 @@ struct lang_hooks_for_tree_inlining
int (*disregard_inline_limits) (tree); int (*disregard_inline_limits) (tree);
int (*auto_var_in_fn_p) (tree, tree); int (*auto_var_in_fn_p) (tree, tree);
bool (*var_mod_type_p) (tree, tree); bool (*var_mod_type_p) (tree, tree);
tree (*convert_parm_for_inlining) (tree, tree, tree, int);
}; };
struct lang_hooks_for_callgraph struct lang_hooks_for_callgraph
......
2007-06-23 Richard Guenther <rguenther@suse.de>
PR tree-optimization/16876
PR middle-end/29478
* gcc.dg/pr29254.c: The warning is bogus.
* gcc.dg/warn-1.c: Likewise.
* gcc.dg/assign-warn-3.c: Likewise.
* gcc.dg/noncompile/pr16876.c: The testcase is bogus, remove.
2007-06-23 Richard Earnshaw <rearnsha@arm.com> 2007-06-23 Richard Earnshaw <rearnsha@arm.com>
* gcc.c-torture/execute/20070623-1.c: New. * gcc.c-torture/execute/20070623-1.c: New.
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
/* This is valid to execute, so maybe shouldn't warn at all. */ /* This is valid to execute, so maybe shouldn't warn at all. */
void f0(x) signed char *x; { } void f0(x) signed char *x; { }
void g0(unsigned char *x) { f0(x); } /* { dg-warning "warning: pointer targets in passing argument 1 of 'f0' differ in signedness" } */ void g0(unsigned char *x) { f0(x); } /* { dg-bogus "warning: pointer targets in passing argument 1 of 'f0' differ in signedness" } */
/* This is undefined on execution but still must compile. */ /* This is undefined on execution but still must compile. */
void f1(x) int *x; { } void f1(x) int *x; { }
void g1(unsigned int *x) { f1(x); } /* { dg-warning "warning: pointer targets in passing argument 1 of 'f1' differ in signedness" } */ void g1(unsigned int *x) { f1(x); } /* { dg-bogus "warning: pointer targets in passing argument 1 of 'f1' differ in signedness" } */
/* { dg-options "-O -finline-functions" } */
static void g();
struct bigstack {
char space[4096];
};
void f() {
g(0); /* { dg-error "incompatible type for argument 1 of 'g'" } */
}
static void g(struct bigstack bstack) {
g(bstack);
}
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O3 -Werror" } */ /* { dg-options "-O3 -Werror" } */
/* { dg-message "warnings being treated as errors" "" {target "*-*-*"} 0 } */
list_compare (int * list1) list_compare (int * list1)
{ {
...@@ -18,5 +17,5 @@ value_compare (int * a) ...@@ -18,5 +17,5 @@ value_compare (int * a)
func2 (const int * fb) func2 (const int * fb)
{ {
func1 ((int *) fb); /* { dg-error "discards qualifiers" } */ func1 ((int *) fb); /* { dg-bogus "discards qualifiers" } */
} }
...@@ -12,5 +12,5 @@ void bar (void) ...@@ -12,5 +12,5 @@ void bar (void)
{ {
void *vp; void *vp;
foo (vp); /* { dg-warning "passing argument 1 of" } */ foo (vp); /* { dg-bogus "passing argument 1 of" } */
} }
...@@ -1451,7 +1451,6 @@ initialize_inlined_parameters (copy_body_data *id, tree exp, ...@@ -1451,7 +1451,6 @@ initialize_inlined_parameters (copy_body_data *id, tree exp,
tree a; tree a;
tree p; tree p;
tree vars = NULL_TREE; tree vars = NULL_TREE;
int argnum = 0;
call_expr_arg_iterator iter; call_expr_arg_iterator iter;
tree static_chain = CALL_EXPR_STATIC_CHAIN (exp); tree static_chain = CALL_EXPR_STATIC_CHAIN (exp);
...@@ -1462,17 +1461,7 @@ initialize_inlined_parameters (copy_body_data *id, tree exp, ...@@ -1462,17 +1461,7 @@ initialize_inlined_parameters (copy_body_data *id, tree exp,
equivalent VAR_DECL, appropriately initialized. */ equivalent VAR_DECL, appropriately initialized. */
for (p = parms, a = first_call_expr_arg (exp, &iter); p; for (p = parms, a = first_call_expr_arg (exp, &iter); p;
a = next_call_expr_arg (&iter), p = TREE_CHAIN (p)) a = next_call_expr_arg (&iter), p = TREE_CHAIN (p))
{ setup_one_parameter (id, p, a, fn, bb, &vars);
tree value;
++argnum;
/* Find the initializer. */
value = lang_hooks.tree_inlining.convert_parm_for_inlining
(p, a, fn, argnum);
setup_one_parameter (id, p, value, fn, bb, &vars);
}
/* Initialize the static chain. */ /* Initialize the static chain. */
p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl; p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
......
...@@ -449,7 +449,10 @@ struct gimple_stmt GTY(()) ...@@ -449,7 +449,10 @@ struct gimple_stmt GTY(())
POINTER_TYPE, REFERENCE_TYPE POINTER_TYPE, REFERENCE_TYPE
MOVE_NONTEMPORAL in MOVE_NONTEMPORAL in
GIMPLE_MODIFY_STMT GIMPLE_MODIFY_STMT
CASE_HIGH_SEEN in CASE_LABEL_EXPR CASE_HIGH_SEEN in
CASE_LABEL_EXPR
CALL_CANNOT_INLINE_P in
CALL_EXPR
public_flag: public_flag:
...@@ -1144,6 +1147,9 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, ...@@ -1144,6 +1147,9 @@ extern void omp_clause_range_check_failed (const tree, const char *, int,
#define CASE_HIGH_SEEN(NODE) \ #define CASE_HIGH_SEEN(NODE) \
(CASE_LABEL_EXPR_CHECK (NODE)->base.static_flag) (CASE_LABEL_EXPR_CHECK (NODE)->base.static_flag)
/* Used to mark a CALL_EXPR as not suitable for inlining. */
#define CALL_CANNOT_INLINE_P(NODE) ((NODE)->base.static_flag)
/* In an expr node (usually a conversion) this means the node was made /* In an expr node (usually a conversion) this means the node was made
implicitly and should not lead to any sort of warning. In a decl node, implicitly and should not lead to any sort of warning. In a decl node,
warnings concerning the decl should be suppressed. This is used at warnings concerning the decl should be suppressed. This is used at
......
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