X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fipa.c;h=d559ab2f285f6fd6421b243238439ba3e3552181;hb=304d9d629e6cba170a5191663dfe1a15ea7b2d59;hp=9997f6cb79f8b5c38998e7ca0b194e972ed5f8ee;hpb=09a2e41255c0a0440f4ed6776545bbccc06a1e04;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/ipa.c b/gcc/ipa.c index 9997f6cb79f..d559ab2f285 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -1,11 +1,12 @@ /* Basic IPA optimizations and utilities. - Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -14,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -25,6 +25,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "cgraph.h" #include "tree-pass.h" #include "timevar.h" +#include "gimple.h" +#include "ggc.h" /* Fill array order with all nodes with output flag set in the reverse topological order. */ @@ -36,6 +38,7 @@ cgraph_postorder (struct cgraph_node **order) int stack_size = 0; int order_pos = 0; struct cgraph_edge *edge, last; + int pass; struct cgraph_node **stack = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); @@ -43,65 +46,90 @@ cgraph_postorder (struct cgraph_node **order) /* We have to deal with cycles nicely, so use a depth first traversal output algorithm. Ignore the fact that some functions won't need to be output and put them into order as well, so we get dependencies - right through intline functions. */ + right through inline functions. */ for (node = cgraph_nodes; node; node = node->next) node->aux = NULL; - for (node = cgraph_nodes; node; node = node->next) - if (!node->aux) - { - node2 = node; - if (!node->callers) - node->aux = &last; - else - node->aux = node->callers; - while (node2) - { - while (node2->aux != &last) - { - edge = node2->aux; - if (edge->next_caller) - node2->aux = edge->next_caller; - else - node2->aux = &last; - if (!edge->caller->aux) - { - if (!edge->caller->callers) - edge->caller->aux = &last; - else - edge->caller->aux = edge->caller->callers; - stack[stack_size++] = node2; - node2 = edge->caller; - break; - } - } - if (node2->aux == &last) - { - order[order_pos++] = node2; - if (stack_size) - node2 = stack[--stack_size]; - else - node2 = NULL; - } - } - } + for (pass = 0; pass < 2; pass++) + for (node = cgraph_nodes; node; node = node->next) + if (!node->aux + && (pass + || (!cgraph_only_called_directly_p (node) + && !node->address_taken))) + { + node2 = node; + if (!node->callers) + node->aux = &last; + else + node->aux = node->callers; + while (node2) + { + while (node2->aux != &last) + { + edge = (struct cgraph_edge *) node2->aux; + if (edge->next_caller) + node2->aux = edge->next_caller; + else + node2->aux = &last; + /* Break possible cycles involving always-inline + functions by ignoring edges from always-inline + functions to non-always-inline functions. */ + if (edge->caller->local.disregard_inline_limits + && !edge->callee->local.disregard_inline_limits) + continue; + if (!edge->caller->aux) + { + if (!edge->caller->callers) + edge->caller->aux = &last; + else + edge->caller->aux = edge->caller->callers; + stack[stack_size++] = node2; + node2 = edge->caller; + break; + } + } + if (node2->aux == &last) + { + order[order_pos++] = node2; + if (stack_size) + node2 = stack[--stack_size]; + else + node2 = NULL; + } + } + } free (stack); for (node = cgraph_nodes; node; node = node->next) node->aux = NULL; return order_pos; } +/* Look for all functions inlined to NODE and update their inlined_to pointers + to INLINED_TO. */ + +static void +update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to) +{ + struct cgraph_edge *e; + for (e = node->callees; e; e = e->next_callee) + if (e->callee->global.inlined_to) + { + e->callee->global.inlined_to = inlined_to; + update_inlined_to_pointer (e->callee, inlined_to); + } +} + /* Perform reachability analysis and reclaim all unreachable nodes. If BEFORE_INLINING_P is true this function is called before inlining - decisions has been made. If BEFORE_INLINING_P is false this function also + decisions has been made. If BEFORE_INLINING_P is false this function also removes unneeded bodies of extern inline functions. */ bool cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) { - struct cgraph_node *first = (void *) 1; + struct cgraph_node *first = (struct cgraph_node *) (void *) 1; + struct cgraph_node *processed = (struct cgraph_node *) (void *) 2; struct cgraph_node *node, *next; bool changed = false; - int insns = 0; #ifdef ENABLE_CHECKING verify_cgraph (); @@ -113,16 +141,21 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) gcc_assert (!node->aux); #endif for (node = cgraph_nodes; node; node = node->next) - if (node->needed && !node->global.inlined_to - && ((!DECL_EXTERNAL (node->decl)) + if (!cgraph_can_remove_if_no_direct_calls_p (node) + && ((!DECL_EXTERNAL (node->decl)) || !node->analyzed || before_inlining_p)) { + gcc_assert (!node->global.inlined_to); node->aux = first; first = node; + node->reachable = true; } else - gcc_assert (!node->aux); + { + gcc_assert (!node->aux); + node->reachable = false; + } /* Perform reachability analysis. As a special case do not consider extern inline functions not inlined as live because we won't output @@ -131,18 +164,61 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) { struct cgraph_edge *e; node = first; - first = first->aux; - - for (e = node->callees; e; e = e->next_callee) - if (!e->callee->aux - && node->analyzed - && (!e->inline_failed || !e->callee->analyzed - || (!DECL_EXTERNAL (e->callee->decl)) - || before_inlining_p)) - { - e->callee->aux = first; - first = e->callee; - } + first = (struct cgraph_node *) first->aux; + node->aux = processed; + + if (node->reachable) + for (e = node->callees; e; e = e->next_callee) + if (!e->callee->reachable + && node->analyzed + && (!e->inline_failed || !e->callee->analyzed + || (!DECL_EXTERNAL (e->callee->decl)) + || before_inlining_p)) + { + bool prev_reachable = e->callee->reachable; + e->callee->reachable |= node->reachable; + if (!e->callee->aux + || (e->callee->aux == processed + && prev_reachable != e->callee->reachable)) + { + e->callee->aux = first; + first = e->callee; + } + } + + /* If any function in a comdat group is reachable, force + all other functions in the same comdat group to be + also reachable. */ + if (node->same_comdat_group + && node->reachable + && !node->global.inlined_to) + { + for (next = node->same_comdat_group; + next != node; + next = next->same_comdat_group) + if (!next->reachable) + { + next->aux = first; + first = next; + next->reachable = true; + } + } + + /* We can freely remove inline clones even if they are cloned, however if + function is clone of real clone, we must keep it around in order to + make materialize_clones produce function body with the changes + applied. */ + while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl)) + { + bool noninline = node->clone_of->decl != node->decl; + node = node->clone_of; + if (noninline) + { + node->aux = first; + first = node; + break; + } + } } /* Remove unreachable nodes. Extern inline functions need special care; @@ -156,62 +232,127 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) for (node = cgraph_nodes; node; node = next) { next = node->next; + if (node->aux && !node->reachable) + { + cgraph_node_remove_callees (node); + node->analyzed = false; + node->local.inlinable = false; + } if (!node->aux) { - int local_insns; - tree decl = node->decl; - node->global.inlined_to = NULL; - if (DECL_STRUCT_FUNCTION (decl)) - local_insns = node->local.self_insns; - else - local_insns = 0; if (file) fprintf (file, " %s", cgraph_node_name (node)); - if (!node->analyzed || !DECL_EXTERNAL (node->decl) - || before_inlining_p) + if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p) cgraph_remove_node (node); else { struct cgraph_edge *e; + /* See if there is reachable caller. */ for (e = node->callers; e; e = e->next_caller) if (e->caller->aux) break; + + /* If so, we need to keep node in the callgraph. */ if (e || node->needed) { struct cgraph_node *clone; - for (clone = node->next_clone; clone; - clone = clone->next_clone) + /* If there are still clones, we must keep body around. + Otherwise we can just remove the body but keep the clone. */ + for (clone = node->clones; clone; + clone = clone->next_sibling_clone) if (clone->aux) break; if (!clone) { cgraph_release_function_body (node); node->analyzed = false; + node->local.inlinable = false; } cgraph_node_remove_callees (node); - node->analyzed = false; + if (node->prev_sibling_clone) + node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; + else if (node->clone_of) + node->clone_of->clones = node->next_sibling_clone; + if (node->next_sibling_clone) + node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone; + node->clone_of = NULL; + node->next_sibling_clone = NULL; + node->prev_sibling_clone = NULL; } else cgraph_remove_node (node); } - if (!DECL_SAVED_TREE (decl)) - insns += local_insns; changed = true; } } for (node = cgraph_nodes; node; node = node->next) - node->aux = NULL; - if (file) - fprintf (file, "\nReclaimed %i insns", insns); + { + /* Inline clones might be kept around so their materializing allows further + cloning. If the function the clone is inlined into is removed, we need + to turn it into normal cone. */ + if (node->global.inlined_to + && !node->callers) + { + gcc_assert (node->clones); + node->global.inlined_to = NULL; + update_inlined_to_pointer (node, node); + } + node->aux = NULL; + } #ifdef ENABLE_CHECKING verify_cgraph (); #endif + + /* Reclaim alias pairs for functions that have disappeared from the + call graph. */ + remove_unreachable_alias_pairs (); + return changed; } +static bool +cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program) +{ + if (!node->local.finalized) + return false; + if (!DECL_COMDAT (node->decl) + && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))) + return false; + if (!whole_program) + return true; + if (DECL_PRESERVE_P (node->decl)) + return true; + /* COMDAT functions must be shared only if they have address taken, + otherwise we can produce our own private implementation with + -fwhole-program. */ + if (DECL_COMDAT (node->decl)) + { + if (node->address_taken || !node->analyzed) + return true; + if (node->same_comdat_group) + { + struct cgraph_node *next; + + /* If more than one function is in the same COMDAT group, it must + be shared even if just one function in the comdat group has + address taken. */ + for (next = node->same_comdat_group; + next != node; + next = next->same_comdat_group) + if (next->address_taken || !next->analyzed) + return true; + } + } + if (MAIN_NAME_P (DECL_NAME (node->decl))) + return true; + if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl))) + return true; + return false; +} + /* Mark visibility of all functions. A local function is one whose calls can occur only in the current @@ -224,39 +365,105 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) via visibilities for the backend point of view. */ static unsigned int -function_and_variable_visibility (void) +function_and_variable_visibility (bool whole_program) { struct cgraph_node *node; struct varpool_node *vnode; for (node = cgraph_nodes; node; node = node->next) { - if (node->reachable - && (DECL_COMDAT (node->decl) - || (!flag_whole_program - && TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl)))) - node->local.externally_visible = true; + /* C++ FE on lack of COMDAT support create local COMDAT functions + (that ought to be shared but can not due to object format + limitations). It is neccesary to keep the flag to make rest of C++ FE + happy. Clear the flag here to avoid confusion in middle-end. */ + if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl)) + DECL_COMDAT (node->decl) = 0; + /* For external decls stop tracking same_comdat_group, it doesn't matter + what comdat group they are in when they won't be emitted in this TU, + and simplifies later passes. */ + if (node->same_comdat_group && DECL_EXTERNAL (node->decl)) + { + struct cgraph_node *n = node, *next; + do + { + /* If at least one of same comdat group functions is external, + all of them have to be, otherwise it is a front-end bug. */ + gcc_assert (DECL_EXTERNAL (n->decl)); + next = n->same_comdat_group; + n->same_comdat_group = NULL; + n = next; + } + while (n != node); + } + gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl)) + || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)); + if (cgraph_externally_visible_p (node, whole_program)) + { + gcc_assert (!node->global.inlined_to); + node->local.externally_visible = true; + } + else + node->local.externally_visible = false; if (!node->local.externally_visible && node->analyzed && !DECL_EXTERNAL (node->decl)) { - gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl)); - TREE_PUBLIC (node->decl) = 0; + gcc_assert (whole_program || !TREE_PUBLIC (node->decl)); + cgraph_make_decl_local (node->decl); } - node->local.local = (!node->needed + node->local.local = (cgraph_only_called_directly_p (node) && node->analyzed && !DECL_EXTERNAL (node->decl) && !node->local.externally_visible); } + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + { + /* weak flag makes no sense on local variables. */ + gcc_assert (!DECL_WEAK (vnode->decl) + || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl)); + /* In several cases declarations can not be common: + + - when declaration has initializer + - when it is in weak + - when it has specific section + - when it resides in non-generic address space. + - if declaration is local, it will get into .local common section + so common flag is not needed. Frontends still produce these in + certain cases, such as for: + + static int a __attribute__ ((common)) + + Canonicalize things here and clear the redundant flag. */ + if (DECL_COMMON (vnode->decl) + && (!(TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl)) + || (DECL_INITIAL (vnode->decl) + && DECL_INITIAL (vnode->decl) != error_mark_node) + || DECL_WEAK (vnode->decl) + || DECL_SECTION_NAME (vnode->decl) != NULL + || ! (ADDR_SPACE_GENERIC_P + (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl)))))) + DECL_COMMON (vnode->decl) = 0; + } for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) { + if (!vnode->finalized) + continue; if (vnode->needed - && !flag_whole_program - && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))) - vnode->externally_visible = 1; + && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)) + && (!whole_program + /* We can privatize comdat readonly variables whose address is not taken, + but doing so is not going to bring us optimization oppurtunities until + we start reordering datastructures. */ + || DECL_COMDAT (vnode->decl) + || DECL_WEAK (vnode->decl) + || lookup_attribute ("externally_visible", + DECL_ATTRIBUTES (vnode->decl)))) + vnode->externally_visible = true; + else + vnode->externally_visible = false; if (!vnode->externally_visible) { - gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl)); - TREE_PUBLIC (vnode->decl) = 0; + gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl)); + cgraph_make_decl_local (vnode->decl); } gcc_assert (TREE_STATIC (vnode->decl)); } @@ -273,16 +480,32 @@ function_and_variable_visibility (void) if (node->local.externally_visible) fprintf (dump_file, " %s", cgraph_node_name (node)); fprintf (dump_file, "\n\n"); + fprintf (dump_file, "\nMarking externally visible variables:"); + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) + if (vnode->externally_visible) + fprintf (dump_file, " %s", varpool_node_name (vnode)); + fprintf (dump_file, "\n\n"); } cgraph_function_flags_ready = true; return 0; } -struct tree_opt_pass pass_ipa_function_and_variable_visibility = +/* Local function pass handling visibilities. This happens before LTO streaming + so in particular -fwhole-program should be ignored at this level. */ + +static unsigned int +local_function_and_variable_visibility (void) +{ + return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr); +} + +struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility = { + { + SIMPLE_IPA_PASS, "visibility", /* name */ NULL, /* gate */ - function_and_variable_visibility, /* execute */ + local_function_and_variable_visibility,/* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ @@ -291,6 +514,227 @@ struct tree_opt_pass pass_ipa_function_and_variable_visibility = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_remove_functions | TODO_dump_cgraph,/* todo_flags_finish */ - 0 /* letter */ + TODO_remove_functions | TODO_dump_cgraph/* todo_flags_finish */ + } }; + +/* Do not re-run on ltrans stage. */ + +static bool +gate_whole_program_function_and_variable_visibility (void) +{ + return !flag_ltrans; +} + +/* Bring functionss local at LTO time whith -fwhole-program. */ + +static unsigned int +whole_program_function_and_variable_visibility (void) +{ + struct cgraph_node *node; + struct varpool_node *vnode; + + function_and_variable_visibility (flag_whole_program); + + for (node = cgraph_nodes; node; node = node->next) + if ((node->local.externally_visible && !DECL_COMDAT (node->decl)) + && node->local.finalized) + cgraph_mark_needed_node (node); + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) + if (vnode->externally_visible && !DECL_COMDAT (vnode->decl)) + varpool_mark_needed_node (vnode); + if (dump_file) + { + fprintf (dump_file, "\nNeeded variables:"); + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) + if (vnode->needed) + fprintf (dump_file, " %s", varpool_node_name (vnode)); + fprintf (dump_file, "\n\n"); + } + return 0; +} + +struct ipa_opt_pass_d pass_ipa_whole_program_visibility = +{ + { + IPA_PASS, + "whole-program", /* name */ + gate_whole_program_function_and_variable_visibility,/* gate */ + whole_program_function_and_variable_visibility,/* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_CGRAPHOPT, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */ + }, + NULL, /* generate_summary */ + NULL, /* write_summary */ + NULL, /* read_summary */ + NULL, /* function_read_summary */ + NULL, /* stmt_fixup */ + 0, /* TODOs */ + NULL, /* function_transform */ + NULL, /* variable_transform */ +}; + +/* Hash a cgraph node set element. */ + +static hashval_t +hash_cgraph_node_set_element (const void *p) +{ + const_cgraph_node_set_element element = (const_cgraph_node_set_element) p; + return htab_hash_pointer (element->node); +} + +/* Compare two cgraph node set elements. */ + +static int +eq_cgraph_node_set_element (const void *p1, const void *p2) +{ + const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1; + const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2; + + return e1->node == e2->node; +} + +/* Create a new cgraph node set. */ + +cgraph_node_set +cgraph_node_set_new (void) +{ + cgraph_node_set new_node_set; + + new_node_set = GGC_NEW (struct cgraph_node_set_def); + new_node_set->hashtab = htab_create_ggc (10, + hash_cgraph_node_set_element, + eq_cgraph_node_set_element, + NULL); + new_node_set->nodes = NULL; + return new_node_set; +} + +/* Add cgraph_node NODE to cgraph_node_set SET. */ + +void +cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node) +{ + void **slot; + cgraph_node_set_element element; + struct cgraph_node_set_element_def dummy; + + dummy.node = node; + slot = htab_find_slot (set->hashtab, &dummy, INSERT); + + if (*slot != HTAB_EMPTY_ENTRY) + { + element = (cgraph_node_set_element) *slot; + gcc_assert (node == element->node + && (VEC_index (cgraph_node_ptr, set->nodes, element->index) + == node)); + return; + } + + /* Insert node into hash table. */ + element = + (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def); + element->node = node; + element->index = VEC_length (cgraph_node_ptr, set->nodes); + *slot = element; + + /* Insert into node vector. */ + VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node); +} + +/* Remove cgraph_node NODE from cgraph_node_set SET. */ + +void +cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node) +{ + void **slot, **last_slot; + cgraph_node_set_element element, last_element; + struct cgraph_node *last_node; + struct cgraph_node_set_element_def dummy; + + dummy.node = node; + slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT); + if (slot == NULL) + return; + + element = (cgraph_node_set_element) *slot; + gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index) + == node); + + /* Remove from vector. We do this by swapping node with the last element + of the vector. */ + last_node = VEC_pop (cgraph_node_ptr, set->nodes); + if (last_node != node) + { + dummy.node = last_node; + last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT); + last_element = (cgraph_node_set_element) *last_slot; + gcc_assert (last_element); + + /* Move the last element to the original spot of NODE. */ + last_element->index = element->index; + VEC_replace (cgraph_node_ptr, set->nodes, last_element->index, + last_node); + } + + /* Remove element from hash table. */ + htab_clear_slot (set->hashtab, slot); + ggc_free (element); +} + +/* Find NODE in SET and return an iterator to it if found. A null iterator + is returned if NODE is not in SET. */ + +cgraph_node_set_iterator +cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node) +{ + void **slot; + struct cgraph_node_set_element_def dummy; + cgraph_node_set_element element; + cgraph_node_set_iterator csi; + + dummy.node = node; + slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT); + if (slot == NULL) + csi.index = (unsigned) ~0; + else + { + element = (cgraph_node_set_element) *slot; + gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index) + == node); + csi.index = element->index; + } + csi.set = set; + + return csi; +} + +/* Dump content of SET to file F. */ + +void +dump_cgraph_node_set (FILE *f, cgraph_node_set set) +{ + cgraph_node_set_iterator iter; + + for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter)) + { + struct cgraph_node *node = csi_node (iter); + dump_cgraph_node (f, node); + } +} + +/* Dump content of SET to stderr. */ + +void +debug_cgraph_node_set (cgraph_node_set set) +{ + dump_cgraph_node_set (stderr, set); +} +