From patchwork Tue Jul 6 01:50:37 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: remove build_function_call_expr Date: Mon, 05 Jul 2010 15:50:37 -0000 From: Nathan Froyd X-Patchwork-Id: 57962 Message-Id: <20100706015036.GN17877@codesourcery.com> To: gcc-patches@gcc.gnu.org The patch below continues the TREE_LIST removal by eliminating build_function_call_expr calls and using array-ish interfaces instead. We now have an even more dizzying array of ways to build CALL_EXPRs and more confusing-named ways (quick, what's the difference between build_call_expr and build_call_list?) but I don't see a better way. Suggestions welcome. (I'm pretty sure most of the call sites I modified never actually get folded, so they could just as well use the build_call_* functions in tree.c, but I'm not sure how to test for that...) Tested on x86_64-unknown-linux-gnu (all languages + Ada, libgomp, etc.). There are some Fortran-specific pieces I need approval for. OK to commit? -Nathan gcc/ * tree.h (build_function_call_expr): Delete. (build_call_expr_loc_array): New function. (build_call_expr_loc_vec): New function. * tree-flow.h (struct omp_region): Change type of ws_args field to a VEC. * builtins.c (build_function_call_expr): Delete. (build_call_expr_loc_array): New function. (build_call_expr_loc): Call it. Use XALLOCAVEC. (build_call_expr): Likewise. (build_call_expr_loc_vec): New function. * cgraphunit.c (build_cdtor): Call build_call_expr instead of build_function_call_expr. * expr.c (emutls_var_address): Likewise. * varasm.c (emutls_common_1): Likewise. * omp-low.c (expand_omp_atomic_mutex): Likewise. (expand_omp_taskreg): Adjust for new type of region->ws_args. (get_ws_args_for): Return a VEC instead of a tree. (expand_parallel_call): Call build_call_expr_loc_vec instead of build_function_call_expr. * stor-layout.c (self_referential_size): Likewise. gcc/fortran/ * trans-decl.c (build_entry_thunks): Call build_call_expr_loc_vec instead of build_function_call_expr. * trans-intrinsic.c (gfc_conv_intrinsic_sr_kind): Likewise. diff --git a/gcc/builtins.c b/gcc/builtins.c index 046593e..0bb9383 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -10676,23 +10676,31 @@ fold_call_expr (location_t loc, tree exp, bool ignore) } /* Conveniently construct a function call expression. FNDECL names the - function to be called and ARGLIST is a TREE_LIST of arguments. */ + function to be called and N arguments are passed in the array + ARGARRAY. */ tree -build_function_call_expr (location_t loc, tree fndecl, tree arglist) +build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray) { tree fntype = TREE_TYPE (fndecl); tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); - int n = list_length (arglist); - tree *argarray = (tree *) alloca (n * sizeof (tree)); - int i; - - for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist)) - argarray[i] = TREE_VALUE (arglist); + return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray); } /* Conveniently construct a function call expression. FNDECL names the + function to be called and the arguments are passed in the vector + VEC. */ + +tree +build_call_expr_loc_vec (location_t loc, tree fndecl, VEC(tree,gc) *vec) +{ + return build_call_expr_loc_array (loc, fndecl, VEC_length (tree, vec), + VEC_address (tree, vec)); +} + + +/* Conveniently construct a function call expression. FNDECL names the function to be called, N is the number of arguments, and the "..." parameters are the argument expressions. */ @@ -10700,16 +10708,14 @@ tree build_call_expr_loc (location_t loc, tree fndecl, int n, ...) { va_list ap; - tree fntype = TREE_TYPE (fndecl); - tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); - tree *argarray = (tree *) alloca (n * sizeof (tree)); + tree *argarray = XALLOCAVEC (tree, n); int i; va_start (ap, n); for (i = 0; i < n; i++) argarray[i] = va_arg (ap, tree); va_end (ap); - return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray); + return build_call_expr_loc_array (loc, fndecl, n, argarray); } /* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because @@ -10719,17 +10725,14 @@ tree build_call_expr (tree fndecl, int n, ...) { va_list ap; - tree fntype = TREE_TYPE (fndecl); - tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); - tree *argarray = (tree *) alloca (n * sizeof (tree)); + tree *argarray = XALLOCAVEC (tree, n); int i; va_start (ap, n); for (i = 0; i < n; i++) argarray[i] = va_arg (ap, tree); va_end (ap); - return fold_builtin_call_array (UNKNOWN_LOCATION, TREE_TYPE (fntype), - fn, n, argarray); + return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray); } /* Construct a CALL_EXPR with type TYPE with FN as the function expression. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2988f1c..64f2798 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -210,15 +210,15 @@ build_cdtor (bool ctor_p, tree *cdtors, size_t len) do { priority_type p; + tree call; fn = cdtors[i]; p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn); if (!body) priority = p; else if (p != priority) break; - append_to_statement_list (build_function_call_expr (UNKNOWN_LOCATION, - fn, 0), - &body); + call = build_call_expr (fn, 0); + append_to_statement_list (call, &body); ++i; } while (i < len); diff --git a/gcc/expr.c b/gcc/expr.c index a43d708..d7144d3 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -6837,8 +6837,7 @@ emutls_var_address (tree var) tree emuvar = emutls_decl (var); tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS]; tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node); - tree arglist = build_tree_list (NULL_TREE, arg); - tree call = build_function_call_expr (UNKNOWN_LOCATION, fn, arglist); + tree call = build_call_expr (fn, 1, arg); return fold_convert (build_pointer_type (TREE_TYPE (var)), call); } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 1c7226c..447a73e 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1980,8 +1980,6 @@ build_entry_thunks (gfc_namespace * ns) gfc_symbol *thunk_sym; stmtblock_t body; tree thunk_fndecl; - tree args; - tree string_args; tree tmp; locus old_loc; @@ -1991,6 +1989,9 @@ build_entry_thunks (gfc_namespace * ns) gfc_get_backend_locus (&old_loc); for (el = ns->entries; el; el = el->next) { + VEC(tree,gc) *args = NULL; + VEC(tree,gc) *string_args = NULL; + thunk_sym = el->sym; build_function_decl (thunk_sym); @@ -2004,18 +2005,16 @@ build_entry_thunks (gfc_namespace * ns) /* Pass extra parameter identifying this entry point. */ tmp = build_int_cst (gfc_array_index_type, el->id); - args = tree_cons (NULL_TREE, tmp, NULL_TREE); - string_args = NULL_TREE; + VEC_safe_push (tree, gc, args, tmp); if (thunk_sym->attr.function) { if (gfc_return_by_reference (ns->proc_name)) { tree ref = DECL_ARGUMENTS (current_function_decl); - args = tree_cons (NULL_TREE, ref, args); + VEC_safe_push (tree, gc, args, ref); if (ns->proc_name->ts.type == BT_CHARACTER) - args = tree_cons (NULL_TREE, TREE_CHAIN (ref), - args); + VEC_safe_push (tree, gc, args, TREE_CHAIN (ref)); } } @@ -2039,31 +2038,29 @@ build_entry_thunks (gfc_namespace * ns) { /* Pass the argument. */ DECL_ARTIFICIAL (thunk_formal->sym->backend_decl) = 1; - args = tree_cons (NULL_TREE, thunk_formal->sym->backend_decl, - args); + VEC_safe_push (tree, gc, args, thunk_formal->sym->backend_decl); if (formal->sym->ts.type == BT_CHARACTER) { tmp = thunk_formal->sym->ts.u.cl->backend_decl; - string_args = tree_cons (NULL_TREE, tmp, string_args); + VEC_safe_push (tree, gc, string_args, tmp); } } else { /* Pass NULL for a missing argument. */ - args = tree_cons (NULL_TREE, null_pointer_node, args); + VEC_safe_push (tree, gc, args, null_pointer_node); if (formal->sym->ts.type == BT_CHARACTER) { tmp = build_int_cst (gfc_charlen_type_node, 0); - string_args = tree_cons (NULL_TREE, tmp, string_args); + VEC_safe_push (tree, gc, string_args, tmp); } } } /* Call the master function. */ - args = nreverse (args); - args = chainon (args, nreverse (string_args)); + VEC_safe_splice (tree, gc, args, string_args); tmp = ns->proc_name->backend_decl; - tmp = build_function_call_expr (input_location, tmp, args); + tmp = build_call_expr_loc_vec (input_location, tmp, args); if (ns->proc_name->attr.mixed_entry_master) { tree union_decl, field; diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 7f583da..6938bcc 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -4567,10 +4567,10 @@ static void gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr) { gfc_actual_arglist *actual; - tree args, type; + tree type; gfc_se argse; + VEC(tree,gc) *args = NULL; - args = NULL_TREE; for (actual = expr->value.function.actual; actual; actual = actual->next) { gfc_init_se (&argse, se); @@ -4595,13 +4595,13 @@ gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr) gfc_add_block_to_block (&se->pre, &argse.pre); gfc_add_block_to_block (&se->post, &argse.post); - args = gfc_chainon_list (args, argse.expr); + VEC_safe_push (tree, gc, args, argse.expr); } /* Convert it to the required type. */ type = gfc_typenode_for_spec (&expr->ts); - se->expr = build_function_call_expr (input_location, - gfor_fndecl_sr_kind, args); + se->expr = build_call_expr_loc_vec (input_location, + gfor_fndecl_sr_kind, args); se->expr = fold_convert (type, se->expr); } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index eca27c8..cd5faf6 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -555,34 +555,35 @@ workshare_safe_to_combine_p (basic_block ws_entry_bb) parallel+workshare call. WS_STMT is the workshare directive being expanded. */ -static tree +static VEC(tree,gc) * get_ws_args_for (gimple ws_stmt) { tree t; location_t loc = gimple_location (ws_stmt); + VEC(tree,gc) *ws_args; if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR) { struct omp_for_data fd; - tree ws_args; extract_omp_for_data (ws_stmt, &fd, NULL); - ws_args = NULL_TREE; - if (fd.chunk_size) - { - t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size); - ws_args = tree_cons (NULL, t, ws_args); - } + ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0)); - t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step); - ws_args = tree_cons (NULL, t, ws_args); + t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1); + VEC_quick_push (tree, ws_args, t); t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2); - ws_args = tree_cons (NULL, t, ws_args); + VEC_quick_push (tree, ws_args, t); - t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1); - ws_args = tree_cons (NULL, t, ws_args); + t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step); + VEC_quick_push (tree, ws_args, t); + + if (fd.chunk_size) + { + t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size); + VEC_quick_push (tree, ws_args, t); + } return ws_args; } @@ -593,8 +594,9 @@ get_ws_args_for (gimple ws_stmt) the exit of the sections region. */ basic_block bb = single_succ (gimple_bb (ws_stmt)); t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1); - t = tree_cons (NULL, t, NULL); - return t; + ws_args = VEC_alloc (tree, gc, 1); + VEC_quick_push (tree, ws_args, t); + return ws_args; } gcc_unreachable (); @@ -2899,13 +2901,14 @@ gimple_build_cond_empty (tree cond) static void expand_parallel_call (struct omp_region *region, basic_block bb, - gimple entry_stmt, tree ws_args) + gimple entry_stmt, VEC(tree,gc) *ws_args) { tree t, t1, t2, val, cond, c, clauses; gimple_stmt_iterator gsi; gimple stmt; int start_ix; location_t clause_loc; + VEC(tree,gc) *args; clauses = gimple_omp_parallel_clauses (entry_stmt); @@ -3036,16 +3039,14 @@ expand_parallel_call (struct omp_region *region, basic_block bb, t1 = build_fold_addr_expr (t); t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt)); - if (ws_args) - { - tree args = tree_cons (NULL, t2, - tree_cons (NULL, t1, - tree_cons (NULL, val, ws_args))); - t = build_function_call_expr (UNKNOWN_LOCATION, - built_in_decls[start_ix], args); - } - else - t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val); + args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args)); + VEC_quick_push (tree, args, t2); + VEC_quick_push (tree, args, t1); + VEC_quick_push (tree, args, val); + VEC_splice (tree, args, ws_args); + + t = build_call_expr_loc_vec (UNKNOWN_LOCATION, + built_in_decls[start_ix], args); force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false, GSI_CONTINUE_LINKING); @@ -3334,11 +3335,12 @@ expand_omp_taskreg (struct omp_region *region) { basic_block entry_bb, exit_bb, new_bb; struct function *child_cfun; - tree child_fn, block, t, ws_args, *tp; + tree child_fn, block, t, *tp; tree save_current; gimple_stmt_iterator gsi; gimple entry_stmt, stmt; edge e; + VEC(tree,gc) *ws_args; entry_stmt = last_stmt (region->entry); child_fn = gimple_omp_taskreg_child_fn (entry_stmt); @@ -3353,7 +3355,7 @@ expand_omp_taskreg (struct omp_region *region) if (is_combined_parallel (region)) ws_args = region->ws_args; else - ws_args = NULL_TREE; + ws_args = NULL; if (child_cfun->cfg) { @@ -5225,7 +5227,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD); t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START]; - t = build_function_call_expr (UNKNOWN_LOCATION, t, 0); + t = build_call_expr (t, 0); force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT); stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr)); @@ -5240,7 +5242,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, gsi_insert_before (&si, stmt, GSI_SAME_STMT); t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END]; - t = build_function_call_expr (UNKNOWN_LOCATION, t, 0); + t = build_call_expr (t, 0); force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT); gsi_remove (&si, true); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 89f5fa9..a9acf1e 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -233,10 +233,11 @@ self_referential_size (tree size) { static unsigned HOST_WIDE_INT fnno = 0; VEC (tree, heap) *self_refs = NULL; - tree param_type_list = NULL, param_decl_list = NULL, arg_list = NULL; + tree param_type_list = NULL, param_decl_list = NULL; tree t, ref, return_type, fntype, fnname, fndecl; unsigned int i; char buf[128]; + VEC(tree,gc) *args = NULL; /* Do not factor out simple operations. */ t = skip_simple_arithmetic (size); @@ -255,6 +256,7 @@ self_referential_size (tree size) /* Build the parameter and argument lists in parallel; also substitute the former for the latter in the expression. */ + args = VEC_alloc (tree, gc, VEC_length (tree, self_refs)); for (i = 0; VEC_iterate (tree, self_refs, i, ref); i++) { tree subst, param_name, param_type, param_decl; @@ -290,7 +292,7 @@ self_referential_size (tree size) param_type_list = tree_cons (NULL_TREE, param_type, param_type_list); param_decl_list = chainon (param_decl, param_decl_list); - arg_list = tree_cons (NULL_TREE, ref, arg_list); + VEC_quick_push (tree, args, ref); } VEC_free (tree, heap, self_refs); @@ -301,7 +303,6 @@ self_referential_size (tree size) /* The 3 lists have been created in reverse order. */ param_type_list = nreverse (param_type_list); param_decl_list = nreverse (param_decl_list); - arg_list = nreverse (arg_list); /* Build the function type. */ return_type = TREE_TYPE (size); @@ -342,7 +343,7 @@ self_referential_size (tree size) VEC_safe_push (tree, gc, size_functions, fndecl); /* Replace the original expression with a call to the size function. */ - return build_function_call_expr (UNKNOWN_LOCATION, fndecl, arg_list); + return build_call_expr_loc_vec (input_location, fndecl, args); } /* Take, queue and compile all the size functions. It is essential that diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index fd9a542..6b12d08 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -368,7 +368,7 @@ struct omp_region /* If this is a combined parallel+workshare region, this is a list of additional arguments needed by the combined parallel+workshare library call. */ - tree ws_args; + VEC(tree,gc) *ws_args; /* The code for the omp directive of this region. */ enum gimple_code type; diff --git a/gcc/tree.h b/gcc/tree.h index 59f6b3a..1b1c3f2 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5018,8 +5018,9 @@ extern tree fold_builtin_strncpy_chk (location_t, tree, tree, tree, tree, tree); extern tree fold_builtin_snprintf_chk (location_t, tree, tree, enum built_in_function); extern bool fold_builtin_next_arg (tree, bool); extern enum built_in_function builtin_mathfn_code (const_tree); -extern tree build_function_call_expr (location_t, tree, tree); extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *); +extern tree build_call_expr_loc_array (location_t, tree, int, tree *); +extern tree build_call_expr_loc_vec (location_t, tree, VEC(tree,gc) *); extern tree build_call_expr_loc (location_t, tree, int, ...); extern tree build_call_expr (tree, int, ...); extern tree mathfn_built_in (tree, enum built_in_function fn); diff --git a/gcc/varasm.c b/gcc/varasm.c index f9a9d97..280e748 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -428,7 +428,7 @@ static int emutls_common_1 (void **loc, void *xstmts) { struct tree_map *h = *(struct tree_map **) loc; - tree args, x, *pstmts = (tree *) xstmts; + tree x, *pstmts = (tree *) xstmts; tree word_type_node; if (! DECL_COMMON (h->base.from) @@ -442,17 +442,14 @@ emutls_common_1 (void **loc, void *xstmts) do this and there is an initializer, -fanchor_section loses, because it would be too late to ensure the template is output. */ - x = null_pointer_node; - args = tree_cons (NULL, x, NULL); - x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->base.from)); - args = tree_cons (NULL, x, args); - x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->base.from)); - args = tree_cons (NULL, x, args); - x = build_fold_addr_expr (h->to); - args = tree_cons (NULL, x, args); - x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON]; - x = build_function_call_expr (UNKNOWN_LOCATION, x, args); + x = build_call_expr (x, 4, + build_fold_addr_expr (h->to), + fold_convert (word_type_node, + DECL_SIZE_UNIT (h->base.from)), + build_int_cst (word_type_node, + DECL_ALIGN_UNIT (h->base.from)), + null_pointer_node); append_to_statement_list (x, pstmts); return 1;