+2008-08-09 Richard Guenther <rguenther@suse.de>
+
+ * gimple.c (gimple_build_call_1): Deal with FUNCTION_DECL fn.
+ * gimple.h (gimple_call_fn): Adjust comment.
+ (gimple_call_set_fndecl): New function.
+ (gimple_call_fndecl): Adjust for GIMPLE_CALL no
+ longer having bare FUNCTION_DECL operand.
+ (gimple_call_return_type): Likewise.
+ * tree-cfg.c (verify_stmt): Verify function operand of a GIMPLE_CALL.
+
+ * value-prof.c (gimple_divmod_fixed_value): Do not emit labels.
+ (gimple_mod_pow2): Likewise.
+ (gimple_mod_subtract): Likewise.
+ (gimple_ic): Likewise.
+ (gimple_stringop_fixed_value): Likewise.
+ (gimple_indirect_call_to_profile): Fix for GIMPLE_CALL no
+ longer having bare FUNCTION_DECL operand.
+ * ipa-cp.c (ipcp_update_callgraph): Use gimple_call_set_fndecl.
+ * omp-low.c (optimize_omp_library_calls): Likewise.
+ * cgraphunit.c (update_call_expr): Likewise.
+ * tree-ssa-math-opts.c (execute_cse_reciprocals): Likewise.
+ (execute_convert_to_rsqrt): Likewise.
+ * cfgexpand.c (gimple_to_tree): Simplify.
+ (release_stmt_tree): Fix for GIMPLE_CALL no longer having
+ bare FUNCTION_DECL operand.
+ * tree-nested.c (init_tmp_var_with_call): Use gimple_call_return_type.
+ (convert_gimple_call): Use gimple_call_fndecl.
+ * c-common.c (c_warn_unused_result): Likewise.
+
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/17880
/* This is a naked call, as opposed to a GIMPLE_CALL with an
LHS. All calls whose value is ignored should be
represented like this. Look for the attribute. */
- fdecl = gimple_call_fn (g);
- if (TREE_CODE (fdecl) == FUNCTION_DECL)
- ftype = TREE_TYPE (fdecl);
- else
- {
- ftype = TREE_TYPE (fdecl);
- /* Look past pointer-to-function to the function type itself. */
- ftype = TREE_TYPE (ftype);
- }
+ fdecl = gimple_call_fndecl (g);
+ ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{
t = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
- fn = gimple_call_fn (stmt);
- if (TREE_CODE (fn) == FUNCTION_DECL)
- CALL_EXPR_FN (t) = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (fn)),
- fn);
- else
- CALL_EXPR_FN (t) = fn;
-
+ CALL_EXPR_FN (t) = gimple_call_fn (stmt);
TREE_TYPE (t) = gimple_call_return_type (stmt);
-
CALL_EXPR_STATIC_CHAIN (t) = gimple_call_chain (stmt);
for (i = 0; i < gimple_call_num_args (stmt); i++)
/* Record the original call statement, as it may be used
to retrieve profile information during expansion. */
- if (TREE_CODE (fn) == FUNCTION_DECL && DECL_BUILT_IN (fn))
+
+ if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
+ && DECL_BUILT_IN (fn))
{
ann = get_tree_common_ann (t);
ann->stmt = stmt;
case GIMPLE_CALL:
if (gimple_call_lhs (stmt))
{
- if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
- ggc_free (CALL_EXPR_FN (TREE_OPERAND (stmt_tree, 1)));
ann = tree_common_ann (TREE_OPERAND (stmt_tree, 1));
if (ann)
ggc_free (ann);
ggc_free (TREE_OPERAND (stmt_tree, 1));
}
- else if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
- ggc_free (CALL_EXPR_FN (stmt_tree));
break;
default:
break;
/* Update the call expr on the edges to call the new version. */
for (e = new_version->callers; e; e = e->next_caller)
- gimple_call_set_fn (e->call_stmt, new_version->decl);
+ gimple_call_set_fndecl (e->call_stmt, new_version->decl);
}
gimple_build_call_1 (tree fn, unsigned nargs)
{
gimple s = gimple_build_with_ops (GIMPLE_CALL, 0, nargs + 3);
+ if (TREE_CODE (fn) == FUNCTION_DECL)
+ fn = build_fold_addr_expr (fn);
gimple_set_op (s, 1, fn);
return s;
}
/* Return the tree node representing the function called by call
- statement GS. This may or may not be a FUNCTION_DECL node. */
+ statement GS. */
static inline tree
gimple_call_fn (const_gimple gs)
}
+/* Set FNDECL to be the function called by call statement GS. */
+
+static inline void
+gimple_call_set_fndecl (gimple gs, tree decl)
+{
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ gimple_set_op (gs, 1, build_fold_addr_expr (decl));
+}
+
+
/* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
Otherwise return NULL. This function is analogous to
get_callee_fndecl in tree land. */
static inline tree
gimple_call_fndecl (const_gimple gs)
{
- tree decl = gimple_call_fn (gs);
- return (TREE_CODE (decl) == FUNCTION_DECL) ? decl : NULL_TREE;
+ tree addr = gimple_call_fn (gs);
+ if (TREE_CODE (addr) == ADDR_EXPR)
+ {
+ gcc_assert (TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL);
+ return TREE_OPERAND (addr, 0);
+ }
+ return NULL_TREE;
}
tree fn = gimple_call_fn (gs);
tree type = TREE_TYPE (fn);
- /* See through pointers. */
- if (POINTER_TYPE_P (type))
- type = TREE_TYPE (type);
+ /* See through the pointer. */
+ gcc_assert (POINTER_TYPE_P (type));
+ type = TREE_TYPE (type);
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE);
if (ipcp_need_redirect_p (cs))
{
cgraph_redirect_edge_callee (cs, orig_callee);
- gimple_call_set_fn (cs->call_stmt, orig_callee->decl);
+ gimple_call_set_fndecl (cs->call_stmt, orig_callee->decl);
}
}
}
!= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
continue;
- gimple_call_set_fn (call, build_fold_addr_expr (built_in));
+ gimple_call_set_fndecl (call, built_in);
}
}
}
+2008-08-09 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/inline-2.c: New testcase.
+
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/17880
--- /dev/null
+/* { dg-do link } */
+/* { dg-options "-O" } */
+
+/* When optimized we expect the call to foo () in bar to be inlined
+ and the call to link_error optimized away. */
+
+extern void link_error (void);
+int __attribute__((always_inline)) foo(void) { return 0; }
+
+int main()
+{
+ int (*fn)(void) = foo;
+ if (fn())
+ link_error ();
+ return 0;
+}
+
didn't see a function declaration before the call. */
if (is_gimple_call (stmt))
{
- tree decl = gimple_call_fn (stmt);
+ tree decl;
- if (TREE_CODE (decl) == FUNCTION_DECL
+ if (!is_gimple_call_addr (gimple_call_fn (stmt)))
+ {
+ error ("invalid function in call statement");
+ return true;
+ }
+
+ decl = gimple_call_fndecl (stmt);
+ if (decl
+ && TREE_CODE (decl) == FUNCTION_DECL
&& DECL_LOOPING_CONST_OR_PURE_P (decl)
&& (!DECL_PURE_P (decl))
&& (!TREE_READONLY (decl)))
{
tree t;
- t = create_tmp_var_for (info, TREE_TYPE (TREE_TYPE (gimple_call_fn (call))),
- NULL);
+ t = create_tmp_var_for (info, gimple_call_return_type (call), NULL);
gimple_call_set_lhs (call, t);
if (! gsi_end_p (*gsi))
gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
switch (gimple_code (stmt))
{
case GIMPLE_CALL:
- decl = gimple_call_fn (stmt);
- if (TREE_CODE (decl) != FUNCTION_DECL)
+ decl = gimple_call_fndecl (stmt);
+ if (!decl)
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
if (!fndecl)
continue;
- gimple_call_set_fn (stmt1, fndecl);
+ gimple_call_set_fndecl (stmt1, fndecl);
update_stmt (stmt1);
gimple_assign_set_rhs_code (stmt, MULT_EXPR);
fold_stmt_inplace (stmt1);
update_stmt (stmt1);
- gimple_call_set_fn (stmt, fndecl);
+ gimple_call_set_fndecl (stmt, fndecl);
update_stmt (stmt);
}
}
gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gcov_type all)
{
- gimple stmt1, stmt2, stmt3, label1, label2;
+ gimple stmt1, stmt2, stmt3;
tree tmp1, tmp2, tmpv;
- tree label_decl1 = create_artificial_label ();
- tree label_decl2 = create_artificial_label ();
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
bb1end = stmt3;
tmp2 = create_tmp_var (optype, "PROF");
- label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
op1, tmpv);
- gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
- label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
op1, op2);
- gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
{
gimple stmt1, stmt2, stmt3, stmt4;
tree tmp2, tmp3;
- tree label_decl1 = create_artificial_label ();
- tree label_decl2 = create_artificial_label ();
- gimple label1, label2;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
bb1end = stmt4;
/* tmp2 == op2-1 inherited from previous block. */
- label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (BIT_AND_EXPR, result, op1, tmp2);
- gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
- label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), result,
op1, op2);
- gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
{
gimple stmt1, stmt2, stmt3;
tree tmp1;
- tree label_decl1 = create_artificial_label ();
- tree label_decl2 = create_artificial_label ();
- tree label_decl3 = create_artificial_label ();
- gimple label1, label2, label3;
gimple bb1end, bb2end = NULL, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
if (ncounts) /* Assumed to be 0 or 1 */
{
- label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (MINUS_EXPR, result, result, tmp1);
stmt2 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
- gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
bb2end = stmt2;
}
/* Fallback case. */
- label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), result,
result, tmp1);
- gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
- label3 = gimple_build_label (label_decl3);
- gsi_insert_before (&gsi, label3, GSI_SAME_STMT);
-
/* Fix CFG. */
/* Edge e23 connects bb2 to bb3, etc. */
/* However block 3 is optional; if it is not there, references
{
gimple stmt1, stmt2, stmt3;
tree tmp1, tmpv, tmp;
- tree label_decl1 = create_artificial_label ();
- tree label_decl2 = create_artificial_label ();
- gimple label1, label2;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype = build_pointer_type (void_type_node);
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
- label1 = gimple_build_label (label_decl1);
stmt1 = gimple_copy (stmt);
gimple_call_set_fn (stmt,
build_addr (direct_call->decl, current_function_decl));
- gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
-
- label2 = gimple_build_label (label_decl2);
- gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
bb3end = stmt;
/* Fix CFG. */
{
gimple stmt1, stmt2, stmt3;
tree tmp1, tmpv;
- tree label_decl1 = create_artificial_label ();
- tree label_decl2 = create_artificial_label ();
- gimple label1, label2;
gimple bb1end, bb2end;
basic_block bb, bb2, bb3, bb4;
edge e12, e13, e23, e24, e34;
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
- label1 = gimple_build_label (label_decl1);
stmt1 = gimple_copy (stmt);
gimple_call_set_arg (stmt1, 2, value);
- gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
region = lookup_stmt_eh_region (stmt);
if (region >= 0)
add_stmt_to_eh_region (stmt1, region);
bb2end = stmt1;
- label2 = gimple_build_label (label_decl2);
- gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
/* Fix CFG. */
/* Edge e23 connects bb2 to bb3, etc. */
{
tree callee;
- if (gimple_code (stmt) != GIMPLE_CALL)
+ if (gimple_code (stmt) != GIMPLE_CALL
+ || gimple_call_fndecl (stmt) != NULL_TREE)
return;
callee = gimple_call_fn (stmt);
-
- if (TREE_CODE (callee) == FUNCTION_DECL)
- return;
VEC_reserve (histogram_value, heap, *values, 3);