From b094d6c4bf572654a031ecc4afe675154c886dc5 Mon Sep 17 00:00:00 2001 From: Jing Yu Date: Thu, 22 Jul 2010 14:03:48 -0700 Subject: commit gcc-4.4.3 which is used to build gcc-4.4.3 Android toolchain in master. The source is based on fsf gcc-4.4.3 and contains local patches which are recorded in gcc-4.4.3/README.google. Change-Id: Id8c6d6927df274ae9749196a1cc24dbd9abc9887 --- gcc-4.4.3/gcc/ipa.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 gcc-4.4.3/gcc/ipa.c (limited to 'gcc-4.4.3/gcc/ipa.c') diff --git a/gcc-4.4.3/gcc/ipa.c b/gcc-4.4.3/gcc/ipa.c new file mode 100644 index 000000000..006cba8e9 --- /dev/null +++ b/gcc-4.4.3/gcc/ipa.c @@ -0,0 +1,291 @@ +/* Basic IPA optimizations and utilities. + Copyright (C) 2003, 2004, 2005, 2007, 2008 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 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +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 COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "cgraph.h" +#include "toplev.h" +#include "tree-pass.h" +#include "timevar.h" + +/* Fill array order with all nodes with output flag set in the reverse + topological order. */ + +int +cgraph_postorder (struct cgraph_node **order) +{ + struct cgraph_node *node, *node2; + int stack_size = 0; + int order_pos = 0; + struct cgraph_edge *edge, last; + + struct cgraph_node **stack = + XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); + + /* 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 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 = (struct cgraph_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; + } + } + } + free (stack); + for (node = cgraph_nodes; node; node = node->next) + node->aux = NULL; + return order_pos; +} + +/* 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 + removes unneeded bodies of extern inline functions. */ + +bool +cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) +{ + struct cgraph_node *first = (struct cgraph_node *) (void *) 1; + struct cgraph_node *node, *next; + bool changed = false; + +#ifdef ENABLE_CHECKING + verify_cgraph (); +#endif + if (file) + fprintf (file, "\nReclaiming functions:"); +#ifdef ENABLE_CHECKING + for (node = cgraph_nodes; node; node = node->next) + gcc_assert (!node->aux); +#endif + for (node = cgraph_nodes; node; node = node->next) + if (node->needed && !node->global.inlined_to + && ((!cgraph_is_decl_external (node)) + || !node->analyzed + || before_inlining_p)) + { + node->aux = first; + first = node; + } + else + gcc_assert (!node->aux); + + /* Perform reachability analysis. As a special case do not consider + extern inline functions not inlined as live because we won't output + them at all. */ + while (first != (void *) 1) + { + struct cgraph_edge *e; + node = first; + first = (struct cgraph_node *) first->aux; + + for (e = node->callees; e; e = e->next_callee) + if (!e->callee->aux + && node->analyzed + && (!e->inline_failed || !e->callee->analyzed + || (!cgraph_is_decl_external (e->callee)) + || before_inlining_p)) + { + e->callee->aux = first; + first = e->callee; + } + } + + /* Remove unreachable nodes. Extern inline functions need special care; + Unreachable extern inline functions shall be removed. + Reachable extern inline functions we never inlined shall get their bodies + eliminated. + Reachable extern inline functions we sometimes inlined will be turned into + unanalyzed nodes so they look like for true extern functions to the rest + of code. Body of such functions is released via remove_node once the + inline clones are eliminated. */ + for (node = cgraph_nodes; node; node = next) + { + next = node->next; + if (!node->aux) + { + node->global.inlined_to = NULL; + if (file) + fprintf (file, " %s", cgraph_node_name (node)); + if (!node->analyzed || !cgraph_is_decl_external (node) + || before_inlining_p) + cgraph_remove_node (node); + else + { + struct cgraph_edge *e; + + for (e = node->callers; e; e = e->next_caller) + if (e->caller->aux) + break; + if (e || node->needed) + { + struct cgraph_node *clone; + + for (clone = node->next_clone; clone; + clone = clone->next_clone) + if (clone->aux) + break; + if (!clone) + { + cgraph_release_function_body (node); + node->analyzed = false; + } + cgraph_node_remove_callees (node); + node->analyzed = false; + node->local.inlinable = false; + } + else + cgraph_remove_node (node); + } + changed = true; + } + } + for (node = cgraph_nodes; node; node = node->next) + node->aux = NULL; +#ifdef ENABLE_CHECKING + verify_cgraph (); +#endif + return changed; +} + +/* Mark visibility of all functions. + + A local function is one whose calls can occur only in the current + compilation unit and all its calls are explicit, so we can change + its calling convention. We simply mark all static functions whose + address is not taken as local. + + We also change the TREE_PUBLIC flag of all declarations that are public + in language point of view but we want to overwrite this default + via visibilities for the backend point of view. */ + +static unsigned int +function_and_variable_visibility (void) +{ + 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; + 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; + } + node->local.local = (!node->needed + && node->analyzed + && !DECL_EXTERNAL (node->decl) + && !node->local.externally_visible); + } + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) + { + if (vnode->needed + && !flag_whole_program + && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))) + vnode->externally_visible = 1; + if (!vnode->externally_visible) + { + gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl)); + TREE_PUBLIC (vnode->decl) = 0; + } + /* Static variables defined in auxiliary modules are externalized to + allow cross module inlining. */ + gcc_assert (TREE_STATIC (vnode->decl) + || varpool_is_auxiliary (vnode)); + } + + if (dump_file) + { + fprintf (dump_file, "\nMarking local functions:"); + for (node = cgraph_nodes; node; node = node->next) + if (node->local.local) + fprintf (dump_file, " %s", cgraph_node_name (node)); + fprintf (dump_file, "\n\n"); + fprintf (dump_file, "\nMarking externally visible functions:"); + for (node = cgraph_nodes; node; node = node->next) + if (node->local.externally_visible) + fprintf (dump_file, " %s", cgraph_node_name (node)); + fprintf (dump_file, "\n\n"); + } + cgraph_function_flags_ready = true; + return 0; +} + +struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility = +{ + { + SIMPLE_IPA_PASS, + "visibility", /* name */ + NULL, /* gate */ + 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_remove_functions | TODO_dump_cgraph/* todo_flags_finish */ + } +}; -- cgit v1.2.3