From 0acacf9e39c2885869ed8cea6b583626b83d13ee Mon Sep 17 00:00:00 2001 From: rguenth Date: Sat, 9 Aug 2008 17:28:39 +0000 Subject: [PATCH] 2008-08-09 Richard Guenther * 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. * gcc.dg/tree-ssa/inline-2.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138907 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 29 ++++++++++++++++++++ gcc/c-common.c | 11 ++------ gcc/cfgexpand.c | 18 +++--------- gcc/cgraphunit.c | 2 +- gcc/gimple.c | 2 ++ gcc/gimple.h | 28 +++++++++++++++---- gcc/ipa-cp.c | 2 +- gcc/omp-low.c | 2 +- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/tree-ssa/inline-2.c | 17 ++++++++++++ gcc/tree-cfg.c | 12 ++++++-- gcc/tree-nested.c | 7 ++--- gcc/tree-ssa-math-opts.c | 4 +-- gcc/value-prof.c | 47 ++------------------------------ 14 files changed, 101 insertions(+), 84 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/inline-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12b9e4fafb9..71a8477cf57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2008-08-09 Richard Guenther + + * 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 PR c/17880 diff --git a/gcc/c-common.c b/gcc/c-common.c index bf75fe78e7b..59da62f7ecc 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -7546,15 +7546,8 @@ c_warn_unused_result (gimple_seq seq) /* 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))) { diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 296d74858b4..ac228f9b79f 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -216,16 +216,8 @@ gimple_to_tree (gimple stmt) 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++) @@ -253,7 +245,9 @@ gimple_to_tree (gimple stmt) /* 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; @@ -368,15 +362,11 @@ release_stmt_tree (gimple stmt, tree stmt_tree) 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; diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 48dd70bcac7..ae3dee417da 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1420,7 +1420,7 @@ update_call_expr (struct cgraph_node *new_version) /* 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); } diff --git a/gcc/gimple.c b/gcc/gimple.c index 2d097c733e7..6e8971f4ec1 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -285,6 +285,8 @@ static inline gimple 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; } diff --git a/gcc/gimple.h b/gcc/gimple.h index f32600daf91..3799e062b37 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1905,7 +1905,7 @@ gimple_call_set_lhs (gimple gs, tree lhs) /* 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) @@ -1937,6 +1937,17 @@ gimple_call_set_fn (gimple gs, tree fn) } +/* 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. */ @@ -1944,8 +1955,13 @@ gimple_call_set_fn (gimple gs, tree fn) 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; } @@ -1957,9 +1973,9 @@ gimple_call_return_type (const_gimple gs) 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); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 8ad6ddb3fec..a129a74c7ff 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -809,7 +809,7 @@ ipcp_update_callgraph (void) 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); } } } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index cda05a449ca..d6c5500319a 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3222,7 +3222,7 @@ optimize_omp_library_calls (gimple entry_stmt) != 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); } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e3cf60c62b..4c98fca979f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-08-09 Richard Guenther + + * gcc.dg/tree-ssa/inline-2.c: New testcase. + 2008-08-09 Manuel Lopez-Ibanez PR c/17880 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c new file mode 100644 index 00000000000..8a7b9070de5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c @@ -0,0 +1,17 @@ +/* { 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; +} + diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 00979bd82ab..99978efe35b 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -3810,9 +3810,17 @@ verify_stmt (gimple_stmt_iterator *gsi) 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))) diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 8f4ab047ae9..cfa1dd4b1ee 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -363,8 +363,7 @@ init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi, { 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))); @@ -1851,8 +1850,8 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p, 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)) diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index dfc00bcdd12..844ec9d1ad0 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -533,7 +533,7 @@ execute_cse_reciprocals (void) 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); @@ -840,7 +840,7 @@ execute_convert_to_rsqrt (void) fold_stmt_inplace (stmt1); update_stmt (stmt1); - gimple_call_set_fn (stmt, fndecl); + gimple_call_set_fndecl (stmt, fndecl); update_stmt (stmt); } } diff --git a/gcc/value-prof.c b/gcc/value-prof.c index da35008ca8e..7f776ccaf89 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -541,10 +541,8 @@ static tree 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; @@ -573,17 +571,13 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count, 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; @@ -702,9 +696,6 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all) { 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; @@ -736,16 +727,12 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all) 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; @@ -861,10 +848,6 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts, { 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; @@ -894,26 +877,19 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts, 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 @@ -1098,9 +1074,6 @@ gimple_ic (gimple stmt, gimple call, struct cgraph_node *direct_call, { 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); @@ -1124,16 +1097,11 @@ gimple_ic (gimple stmt, gimple call, struct cgraph_node *direct_call, 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. */ @@ -1287,9 +1255,6 @@ gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count, { 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; @@ -1325,17 +1290,13 @@ gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count, 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. */ @@ -1581,13 +1542,11 @@ gimple_indirect_call_to_profile (gimple stmt, histogram_values *values) { 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); -- 2.11.4.GIT