aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/Makefile.in12
-rw-r--r--gcc/c-decl.c1
-rw-r--r--gcc/c-objc-common.c1
-rw-r--r--gcc/cfgcleanup.c3
-rw-r--r--gcc/cgraph.c377
-rw-r--r--gcc/cgraph.h80
-rw-r--r--gcc/cgraphunit.c360
-rw-r--r--gcc/config/i386/i386.md4
-rw-r--r--gcc/expmed.c17
-rw-r--r--gcc/toplev.c13
-rw-r--r--gcc/tree-inline.c1
-rw-r--r--gcc/tree.h10
13 files changed, 506 insertions, 399 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f52abfa..59050a5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,29 @@
+Sat Feb 22 03:13:36 CET 2003 Jan Hubicka <jh@suse.cz>
+
+ * expmed.c (expand_divmod): Undo sign extensions for unsigned operands
+
+ * cfgcleanup.c (try_forward_edges): Don't check loop structures
+ when not optimizing.
+ (cleanup_cfg): Do not iterate trought delete_trivially_dead_insns
+ when not expensive.
+ * toplev.c (rest_of_compilation): Duplicate loop headers only when
+ optimizing; Delete trivially dead insns early; fix optimize check.
+
+ * Makefile.in (c-decl.o, c-objc-common.o, cgraph.o, tree-inline.o): Add
+ dependency on cgraph.h
+ * c-decl.c: Include cgraph.h
+ (finish_function): Update call of tree_inlinable_function_p.
+ * c-objc-common.c: Include cgraph.h
+ * cgraph.h: New file.
+ * cgraphunit.c: New file.
+ * cgraph.c (cgraph_node, cgraph_edge): Move into cgraph.h
+ (cgraph_nodes, cgraph_n_nodes): Globalize.
+ (cgraph_finalize_function, cgraph_finalize_compilation_unit
+ cgraph_create_edges, cgraph_optimize, cgraph_mark_needed_node):
+ Move into cgraphunit.c
+ * tree-inline.c: Include cgraph.h
+ * tree-inline.c: Include cgraph.h
+
2003-02-22 Josef Zlomek <zlomekj@suse.cz>
* config/i386/i386.md: Use gen_lowpart instead of gen_rtx_REG
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e00b288..271f3e0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -785,7 +785,7 @@ OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
- alloc-pool.o et-forest.o cgraph.o \
+ alloc-pool.o et-forest.o cgraph.o cgraphunit.o \
$(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
BACKEND = main.o libbackend.a
@@ -1221,7 +1221,7 @@ $(parsedir)/c-parse.y: c-parse.in
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
$(C_TREE_H) $(GGC_H) $(TARGET_H) flags.h function.h output.h $(EXPR_H) \
debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h \
- gt-c-decl.h
+ gt-c-decl.h cgraph.h
c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
$(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
@@ -1233,7 +1233,7 @@ c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H)
c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(RTL_H) insn-config.h integrate.h $(EXPR_H) $(C_TREE_H) \
flags.h toplev.h tree-inline.h diagnostic.h integrate.h $(VARRAY_H) \
- langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H)
+ langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H) cgraph.h
c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) flags.h toplev.h
c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
@@ -1413,7 +1413,7 @@ tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) expr.h flags.h params.h input.h insn-config.h $(INTEGRATE_H) \
$(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h langhooks.h \
- $(C_COMMON_H) tree-inline.h
+ $(C_COMMON_H) tree-inline.h cgraph.h
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) langhooks.h real.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
@@ -1532,7 +1532,9 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RT
$(REGS_H) hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H) $(TARGET_H)
cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- langhooks.h tree-inline.h toplev.h flags.h ggc.h $(TARGET_H)
+ langhooks.h tree-inline.h toplev.h flags.h ggc.h $(TARGET_H) cgraph.h
+cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+ langhooks.h tree-inline.h toplev.h flags.h ggc.h $(TARGET_H) cgraph.h
cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index a0c1d56..df3390c 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "cgraph.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index a84ddc8..4ef748c 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "langhooks.h"
#include "target.h"
+#include "cgraph.h"
static bool c_tree_printer PARAMS ((output_buffer *, text_info *));
static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 3607fc3..eaefdf2 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -502,7 +502,7 @@ try_forward_edges (mode, b)
For fallthru forwarders, the LOOP_BEG note must appear between
the header of block and CODE_LABEL of the loop, for non forwarders
it must appear before the JUMP_INSN. */
- if (mode & CLEANUP_PRE_LOOP)
+ if ((mode & CLEANUP_PRE_LOOP) && optimize)
{
rtx insn = (target->succ->flags & EDGE_FALLTHRU
? target->head : prev_nonnote_insn (target->end));
@@ -1795,6 +1795,7 @@ cleanup_cfg (mode)
break;
}
else if (!(mode & (CLEANUP_NO_INSN_DEL | CLEANUP_PRE_SIBCALL))
+ && (mode & CLEANUP_EXPENSIVE)
&& !reload_completed)
{
if (!delete_trivially_dead_insns (get_insns(), max_reg_num ()))
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index f1fffca..7df18f1 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -32,67 +32,22 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "debug.h"
#include "target.h"
-
-/* The cgraph data strutcture.
- Each function decl has assigned cgraph_node listing calees and callers. */
-
-struct cgraph_node
-{
- tree decl;
- struct cgraph_edge *callees;
- struct cgraph_edge *callers;
- struct cgraph_node *next;
- /* For nested functions points to function the node is nested in. */
- struct cgraph_node *origin;
- /* Points to first nested function, if any. */
- struct cgraph_node *nested;
- /* Pointer to the next function with same origin, if any. */
- struct cgraph_node *next_nested;
- void *aux;
-
- /* Set when function must be output - it is externally visible
- or it's address is taken. */
- bool needed;
- /* Set when function is reachable by call from other function
- that is eighter reachable or needed. */
- bool reachable;
- /* Set when the frontend has been asked to lower representation of this
- function into trees. Callees lists are not available when lowered
- is not set. */
- bool lowered;
- /* Set when function is scheduled to be assembled. */
- bool output;
-};
-
-struct cgraph_edge
-{
- struct cgraph_node *caller, *callee;
- struct cgraph_edge *next_caller;
- struct cgraph_edge *next_callee;
-};
+#include "cgraph.h"
/* Hash table used to convert declarations into nodes. */
static htab_t cgraph_hash = 0;
/* The linked list of cgraph nodes. */
-static struct cgraph_node *cgraph_nodes;
+struct cgraph_node *cgraph_nodes;
/* Number of nodes in existence. */
-static int cgraph_n_nodes;
+int cgraph_n_nodes;
-static struct cgraph_node *cgraph_node PARAMS ((tree decl));
static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
struct cgraph_node *));
static void remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
-static struct cgraph_edge *record_call PARAMS ((tree, tree));
-static tree record_call_1 PARAMS ((tree *, int *, void *));
static hashval_t hash_node PARAMS ((const PTR));
static int eq_node PARAMS ((const PTR, const PTR));
-static struct cgraph_node *cgraph_node PARAMS ((tree));
-static void cgraph_expand_functions PARAMS ((void));
-static void cgraph_mark_functions_to_output PARAMS ((void));
-static void cgraph_expand_function PARAMS ((struct cgraph_node *));
-static void cgraph_mark_needed_node PARAMS ((struct cgraph_node *, int));
/* Returns a hash code for P. */
@@ -117,7 +72,7 @@ eq_node (p1, p2)
}
/* Return cgraph node assigned to DECL. Create new one when needed. */
-static struct cgraph_node *
+struct cgraph_node *
cgraph_node (decl)
tree decl;
{
@@ -190,8 +145,8 @@ remove_edge (caller, callee)
/* Record call from CALLER to CALLEE */
-static struct cgraph_edge *
-record_call (caller, callee)
+struct cgraph_edge *
+cgraph_record_call (caller, callee)
tree caller, callee;
{
return create_edge (cgraph_node (caller), cgraph_node (callee));
@@ -220,66 +175,6 @@ cgraph_calls_p (caller_decl, callee_decl)
return edge != NULL;
}
-/* Walk tree and record all calls. Called via walk_tree. */
-static tree
-record_call_1 (tp, walk_subtrees, data)
- tree *tp;
- int *walk_subtrees;
- void *data;
-{
- /* Record dereferences to the functions. This makes the functions
- reachable unconditionally. */
- if (TREE_CODE (*tp) == ADDR_EXPR)
- {
- tree decl = TREE_OPERAND (*tp, 0);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_mark_needed_node (cgraph_node (decl), 1);
- }
- else if (TREE_CODE (*tp) == CALL_EXPR)
- {
- tree decl = TREE_OPERAND (*tp, 0);
- if (TREE_CODE (decl) == ADDR_EXPR)
- decl = TREE_OPERAND (decl, 0);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- if (DECL_BUILT_IN (decl))
- return NULL;
- record_call (data, decl);
- walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL);
- *walk_subtrees = 0;
- }
- }
- return NULL;
-}
-
-/* Create cgraph edges for function calles via BODY. */
-
-void
-cgraph_create_edges (decl, body)
- tree decl;
- tree body;
-{
- walk_tree (&body, record_call_1, decl, NULL);
-}
-
-/* Analyze function once it is parsed. Set up the local information
- available - create cgraph edges for function calles via BODY. */
-
-void
-cgraph_finalize_function (decl, body)
- tree decl;
- tree body ATTRIBUTE_UNUSED;
-{
- struct cgraph_node *node = cgraph_node (decl);
-
- node->decl = decl;
-
- /* Set TREE_UNINLINABLE flag. */
- tree_inlinable_function_p (decl);
-
- (*debug_hooks->deferred_inline_function) (decl);
-}
-
/* Dump the callgraph. */
void
@@ -315,263 +210,3 @@ dump_cgraph (f)
fprintf (f, "\n");
}
}
-
-static struct cgraph_node *queue = NULL;
-
-/* Notify finalize_compilation_unit that given node is reachable
- or needed. */
-static void
-cgraph_mark_needed_node (node, needed)
- struct cgraph_node *node;
- int needed;
-{
- if (needed)
- {
- if (DECL_SAVED_TREE (node->decl))
- announce_function (node->decl);
- node->needed = 1;
- }
- if (!node->reachable)
- {
- node->reachable = 1;
- if (DECL_SAVED_TREE (node->decl))
- {
- node->aux = queue;
- queue = node;
- }
- }
-}
-
-/* Analyze the whole compilation unit once it is parsed completely. */
-
-void
-cgraph_finalize_compilation_unit ()
-{
- struct cgraph_node *node;
- struct cgraph_edge *edge;
-
- /* Collect entry points to the unit. */
-
- if (!quiet_flag)
- fprintf (stderr, "\n\nUnit entry points:");
-
- for (node = cgraph_nodes; node; node = node->next)
- {
- tree decl = node->decl;
-
- if (!DECL_SAVED_TREE (decl))
- continue;
- if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
- || (DECL_ASSEMBLER_NAME_SET_P (decl)
- && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
- {
- cgraph_mark_needed_node (node, 1);
- }
- }
-
- /* Propagate reachability flag and lower representation of all reachable
- functions. In the future, lowering will introduce new functions and
- new entry points on the way (by template instantiation and virtual
- method table generation for instance). */
- while (queue)
- {
- tree decl = queue->decl;
-
- node = queue;
- queue = queue->aux;
- if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
- abort ();
-
- /* At the moment frontend automatically emits all nested functions. */
- if (node->nested)
- {
- struct cgraph_node *node2;
-
- for (node2 = node->nested; node2; node2 = node2->next_nested)
- if (!node2->reachable)
- cgraph_mark_needed_node (node2, 0);
- }
-
- if (lang_hooks.callgraph.lower_function)
- (*lang_hooks.callgraph.lower_function) (decl);
- /* First kill forward declaration so reverse inling works properly. */
- cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
-
- for (edge = node->callees; edge; edge = edge->next_callee)
- {
- if (!edge->callee->reachable)
- cgraph_mark_needed_node (edge->callee, 0);
- }
- node->lowered = true;
- }
- if (!quiet_flag)
- fprintf (stderr, "\n\nReclaiming functions:");
-
- for (node = cgraph_nodes; node; node = node->next)
- {
- tree decl = node->decl;
-
- if (!node->reachable && DECL_SAVED_TREE (decl))
- {
- DECL_SAVED_TREE (decl) = NULL;
- announce_function (decl);
- }
- }
- ggc_collect ();
-}
-
-/* Figure out what functions we want to assemble. */
-
-static void
-cgraph_mark_functions_to_output ()
-{
- struct cgraph_node *node;
-
- /* Figure out functions we want to assemble. */
- for (node = cgraph_nodes; node; node = node->next)
- {
- tree decl = node->decl;
-
- if (DECL_SAVED_TREE (decl)
- && (node->needed
- || (DECL_UNINLINABLE (decl) && node->reachable)
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- && !TREE_ASM_WRITTEN (decl) && !node->origin
- && !DECL_EXTERNAL (decl))
- node->output = 1;
- }
-}
-
-/* Expand function specified by NODE. */
-static void
-cgraph_expand_function (node)
- struct cgraph_node *node;
-{
- tree decl = node->decl;
-
- announce_function (decl);
- if (flag_inline_trees)
- optimize_inline_calls (decl);
- (*lang_hooks.callgraph.expand_function) (decl);
- if (DECL_UNINLINABLE (decl))
- DECL_SAVED_TREE (decl) = NULL;
- current_function_decl = NULL;
-}
-
-
-/* Expand all functions that must be output.
-
- Attempt to topologically sort the nodes so function is output when
- all called functions are already assembled to allow data to be propagated
- accross the callgraph. Use stack to get smaller distance between function
- and it's callees (later we may use more sophisticated algorithm for
- function reordering, we will likely want to use subsections to make output
- functions to appear in top-down order, not bottom-up they are assembled). */
-
-static void
-cgraph_expand_functions ()
-{
- struct cgraph_node *node, *node2;
- struct cgraph_node **stack =
- xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
- struct cgraph_node **order =
- xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
- int stack_size = 0;
- int order_pos = 0;
- struct cgraph_edge *edge, last;
- int i;
-
- cgraph_mark_functions_to_output ();
-
- /* We have to deal with cycles nicely, so use depth first traversal
- 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 trought inlined
- functions. */
- for (node = cgraph_nodes; node; node = node->next)
- node->aux = NULL;
- for (node = cgraph_nodes; node; node = node->next)
- if (node->output && !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 (i = order_pos - 1; i >=0; i--)
- {
- node = order[i];
- if (node->output)
- {
- if (!node->reachable)
- abort ();
- node->output = 0;
- cgraph_expand_function (node);
- }
- }
- free (stack);
- free (order);
-}
-
-/* Perform simple optimizations based on callgraph. */
-
-void
-cgraph_optimize ()
-{
- struct cgraph_node *node;
- bool changed = true;
- struct cgraph_edge *edge;
-
- if (!quiet_flag)
- fprintf (stderr, "\n\nAssembling functions:");
-
- /* Output everything.
- ??? Our inline heuristic may decide to not inline functions previously
- marked as inlinable thus adding new function bodies that must be output.
- Later we should move all inlining decisions to callgraph code to make
- this impossible. */
- cgraph_expand_functions ();
- while (changed)
- {
- changed = false;
- for (node = cgraph_nodes; node; node = node->next)
- {
- if (!node->needed)
- continue;
-
- for (edge = node->callees; edge; edge = edge->next_callee)
- if (!edge->callee->needed)
- changed = edge->callee->needed = true;
- }
- }
- cgraph_expand_functions ();
-}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
new file mode 100644
index 0000000..8dd37ed
--- /dev/null
+++ b/gcc/cgraph.h
@@ -0,0 +1,80 @@
+/* Callgraph handling code.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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
+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 COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#ifndef GCC_CGRAPH_H
+#define GCC_CGRAPH_H
+
+/* The cgraph data strutcture.
+ Each function decl has assigned cgraph_node listing calees and callers. */
+
+struct cgraph_node
+{
+ tree decl;
+ struct cgraph_edge *callees;
+ struct cgraph_edge *callers;
+ struct cgraph_node *next;
+ /* For nested functions points to function the node is nested in. */
+ struct cgraph_node *origin;
+ /* Points to first nested function, if any. */
+ struct cgraph_node *nested;
+ /* Pointer to the next function with same origin, if any. */
+ struct cgraph_node *next_nested;
+ void *aux;
+
+ /* Set when function must be output - it is externally visible
+ or it's address is taken. */
+ bool needed;
+ /* Set when function is reachable by call from other function
+ that is eighter reachable or needed. */
+ bool reachable;
+ /* Set when the frontend has been asked to lower representation of this
+ function into trees. Callees lists are not available when lowered
+ is not set. */
+ bool lowered;
+ /* Set when function is scheduled to be assembled. */
+ bool output;
+};
+
+struct cgraph_edge
+{
+ struct cgraph_node *caller, *callee;
+ struct cgraph_edge *next_caller;
+ struct cgraph_edge *next_callee;
+};
+
+extern struct cgraph_node *cgraph_nodes;
+extern int cgraph_n_nodes;
+
+/* In cgraph.c */
+void dump_cgraph PARAMS ((FILE *));
+void cgraph_remove_call PARAMS ((tree, tree));
+struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
+struct cgraph_node *cgraph_node PARAMS ((tree decl));
+bool cgraph_calls_p PARAMS ((tree, tree));
+
+/* In cgraphunit.c */
+void cgraph_finalize_function PARAMS ((tree, tree));
+void cgraph_finalize_compilation_unit PARAMS ((void));
+void cgraph_create_edges PARAMS ((tree, tree));
+void cgraph_optimize PARAMS ((void));
+void cgraph_mark_needed_node PARAMS ((struct cgraph_node *, int));
+
+#endif /* GCC_CGRAPH_H */
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
new file mode 100644
index 0000000..0a12dda
--- /dev/null
+++ b/gcc/cgraphunit.c
@@ -0,0 +1,360 @@
+/* Callgraph handling code.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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
+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 COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "tree-inline.h"
+#include "langhooks.h"
+#include "hashtab.h"
+#include "toplev.h"
+#include "flags.h"
+#include "ggc.h"
+#include "debug.h"
+#include "target.h"
+#include "cgraph.h"
+
+static void cgraph_expand_functions PARAMS ((void));
+static void cgraph_mark_functions_to_output PARAMS ((void));
+static void cgraph_expand_function PARAMS ((struct cgraph_node *));
+static tree record_call_1 PARAMS ((tree *, int *, void *));
+
+/* Analyze function once it is parsed. Set up the local information
+ available - create cgraph edges for function calles via BODY. */
+
+void
+cgraph_finalize_function (decl, body)
+ tree decl;
+ tree body ATTRIBUTE_UNUSED;
+{
+ struct cgraph_node *node = cgraph_node (decl);
+
+ node->decl = decl;
+
+ /* Set TREE_UNINLINABLE flag. */
+ tree_inlinable_function_p (decl);
+
+ (*debug_hooks->deferred_inline_function) (decl);
+}
+
+static struct cgraph_node *queue = NULL;
+
+/* Notify finalize_compilation_unit that given node is reachable
+ or needed. */
+void
+cgraph_mark_needed_node (node, needed)
+ struct cgraph_node *node;
+ int needed;
+{
+ if (needed)
+ {
+ if (DECL_SAVED_TREE (node->decl))
+ announce_function (node->decl);
+ node->needed = 1;
+ }
+ if (!node->reachable)
+ {
+ node->reachable = 1;
+ if (DECL_SAVED_TREE (node->decl))
+ {
+ node->aux = queue;
+ queue = node;
+ }
+ }
+}
+
+/* Walk tree and record all calls. Called via walk_tree. */
+static tree
+record_call_1 (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees;
+ void *data;
+{
+ /* Record dereferences to the functions. This makes the functions
+ reachable unconditionally. */
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ {
+ tree decl = TREE_OPERAND (*tp, 0);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ cgraph_mark_needed_node (cgraph_node (decl), 1);
+ }
+ else if (TREE_CODE (*tp) == CALL_EXPR)
+ {
+ tree decl = TREE_OPERAND (*tp, 0);
+ if (TREE_CODE (decl) == ADDR_EXPR)
+ decl = TREE_OPERAND (decl, 0);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (DECL_BUILT_IN (decl))
+ return NULL;
+ cgraph_record_call (data, decl);
+ walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL);
+ *walk_subtrees = 0;
+ }
+ }
+ return NULL;
+}
+
+/* Create cgraph edges for function calles via BODY. */
+
+void
+cgraph_create_edges (decl, body)
+ tree decl;
+ tree body;
+{
+ walk_tree (&body, record_call_1, decl, NULL);
+}
+
+/* Analyze the whole compilation unit once it is parsed completely. */
+
+void
+cgraph_finalize_compilation_unit ()
+{
+ struct cgraph_node *node;
+ struct cgraph_edge *edge;
+
+ /* Collect entry points to the unit. */
+
+ if (!quiet_flag)
+ fprintf (stderr, "\n\nUnit entry points:");
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree decl = node->decl;
+
+ if (!DECL_SAVED_TREE (decl))
+ continue;
+ if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+ || (DECL_ASSEMBLER_NAME_SET_P (decl)
+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ {
+ cgraph_mark_needed_node (node, 1);
+ }
+ }
+
+ /* Propagate reachability flag and lower representation of all reachable
+ functions. In the future, lowering will introduce new functions and
+ new entry points on the way (by template instantiation and virtual
+ method table generation for instance). */
+ while (queue)
+ {
+ tree decl = queue->decl;
+
+ node = queue;
+ queue = queue->aux;
+ if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
+ abort ();
+
+ /* At the moment frontend automatically emits all nested functions. */
+ if (node->nested)
+ {
+ struct cgraph_node *node2;
+
+ for (node2 = node->nested; node2; node2 = node2->next_nested)
+ if (!node2->reachable)
+ cgraph_mark_needed_node (node2, 0);
+ }
+
+ if (lang_hooks.callgraph.lower_function)
+ (*lang_hooks.callgraph.lower_function) (decl);
+ /* First kill forward declaration so reverse inling works properly. */
+ cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
+
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ {
+ if (!edge->callee->reachable)
+ cgraph_mark_needed_node (edge->callee, 0);
+ }
+ node->lowered = true;
+ }
+ if (!quiet_flag)
+ fprintf (stderr, "\n\nReclaiming functions:");
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree decl = node->decl;
+
+ if (!node->reachable && DECL_SAVED_TREE (decl))
+ {
+ DECL_SAVED_TREE (decl) = NULL;
+ announce_function (decl);
+ }
+ }
+ ggc_collect ();
+}
+
+/* Figure out what functions we want to assemble. */
+
+static void
+cgraph_mark_functions_to_output ()
+{
+ struct cgraph_node *node;
+
+ /* Figure out functions we want to assemble. */
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree decl = node->decl;
+
+ if (DECL_SAVED_TREE (decl)
+ && (node->needed
+ || (DECL_UNINLINABLE (decl) && node->reachable)
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ && !TREE_ASM_WRITTEN (decl) && !node->origin
+ && !DECL_EXTERNAL (decl))
+ node->output = 1;
+ }
+}
+
+/* Expand function specified by NODE. */
+static void
+cgraph_expand_function (node)
+ struct cgraph_node *node;
+{
+ tree decl = node->decl;
+
+ announce_function (decl);
+ if (flag_inline_trees)
+ optimize_inline_calls (decl);
+ (*lang_hooks.callgraph.expand_function) (decl);
+ if (DECL_UNINLINABLE (decl))
+ DECL_SAVED_TREE (decl) = NULL;
+ current_function_decl = NULL;
+}
+
+
+/* Expand all functions that must be output.
+
+ Attempt to topologically sort the nodes so function is output when
+ all called functions are already assembled to allow data to be propagated
+ accross the callgraph. Use stack to get smaller distance between function
+ and it's callees (later we may use more sophisticated algorithm for
+ function reordering, we will likely want to use subsections to make output
+ functions to appear in top-down order, not bottom-up they are assembled). */
+
+static void
+cgraph_expand_functions ()
+{
+ struct cgraph_node *node, *node2;
+ struct cgraph_node **stack =
+ xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
+ struct cgraph_node **order =
+ xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
+ int stack_size = 0;
+ int order_pos = 0;
+ struct cgraph_edge *edge, last;
+ int i;
+
+ cgraph_mark_functions_to_output ();
+
+ /* We have to deal with cycles nicely, so use depth first traversal
+ 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 trought inlined
+ functions. */
+ for (node = cgraph_nodes; node; node = node->next)
+ node->aux = NULL;
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->output && !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 (i = order_pos - 1; i >=0; i--)
+ {
+ node = order[i];
+ if (node->output)
+ {
+ if (!node->reachable)
+ abort ();
+ node->output = 0;
+ cgraph_expand_function (node);
+ }
+ }
+ free (stack);
+ free (order);
+}
+
+/* Perform simple optimizations based on callgraph. */
+
+void
+cgraph_optimize ()
+{
+ struct cgraph_node *node;
+ bool changed = true;
+ struct cgraph_edge *edge;
+
+ if (!quiet_flag)
+ fprintf (stderr, "\n\nAssembling functions:");
+
+ /* Output everything.
+ ??? Our inline heuristic may decide to not inline functions previously
+ marked as inlinable thus adding new function bodies that must be output.
+ Later we should move all inlining decisions to callgraph code to make
+ this impossible. */
+ cgraph_expand_functions ();
+ while (changed)
+ {
+ changed = false;
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ if (!node->needed)
+ continue;
+
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ if (!edge->callee->needed)
+ changed = edge->callee->needed = true;
+ }
+ }
+ cgraph_expand_functions ();
+}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e6f1412..09cd54e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -22864,7 +22864,7 @@
"@
movq\t{%1, %0|%0, %1}
movdq2q\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
+ movd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "mode" "TI")])
@@ -22887,7 +22887,7 @@
"@
movq\t{%1, %0|%0, %1}
movq2dq\t{%1, %0|%0, %1}
- movq\t{%1, %0|%0, %1}"
+ movd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt,ssemov,ssecvt")
(set_attr "mode" "TI")])
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 9fe87b6..33d8152 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2955,14 +2955,20 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
int size;
rtx insn, set;
optab optab1, optab2;
- int op1_is_constant, op1_is_pow2;
+ int op1_is_constant, op1_is_pow2 = 0;
int max_cost, extra_cost;
static HOST_WIDE_INT last_div_const = 0;
+ static HOST_WIDE_INT ext_op1;
op1_is_constant = GET_CODE (op1) == CONST_INT;
- op1_is_pow2 = (op1_is_constant
- && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
- || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1))))));
+ if (op1_is_constant)
+ {
+ ext_op1 = INTVAL (op1);
+ if (unsignedp)
+ ext_op1 &= GET_MODE_MASK (mode);
+ op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
+ || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1))));
+ }
/*
This is the structure of expand_divmod:
@@ -3142,7 +3148,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
unsigned HOST_WIDE_INT mh, ml;
int pre_shift, post_shift;
int dummy;
- unsigned HOST_WIDE_INT d = INTVAL (op1);
+ unsigned HOST_WIDE_INT d = (INTVAL (op1)
+ & GET_MODE_MASK (compute_mode));
if (EXACT_POWER_OF_2_OR_ZERO_P (d))
{
diff --git a/gcc/toplev.c b/gcc/toplev.c
index e55d265..acb98ee 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2697,16 +2697,19 @@ rest_of_compilation (decl)
reg_scan (insns, max_reg_num (), 0);
rebuild_jump_labels (insns);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ delete_trivially_dead_insns (insns, max_reg_num ());
if (rtl_dump_file)
dump_flow_info (rtl_dump_file);
cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
| (flag_thread_jumps ? CLEANUP_THREADING : 0));
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- copy_loop_headers (insns);
+ if (optimize)
+ {
+ free_bb_for_insn ();
+ copy_loop_headers (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ }
purge_line_number_notes (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
timevar_pop (TV_JUMP);
close_dump_file (DFI_jump, print_rtl, insns);
@@ -3052,7 +3055,7 @@ rest_of_compilation (decl)
close_dump_file (DFI_bp, print_rtl_with_bb, insns);
timevar_pop (TV_BRANCH_PROB);
}
- if (optimize >= 0)
+ if (optimize > 0)
{
open_dump_file (DFI_ce1, decl);
if (flag_if_conversion)
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 19b7a4f..71c4018d 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "hashtab.h"
#include "splay-tree.h"
#include "langhooks.h"
+#include "cgraph.h"
/* This should be eventually be generalized to other languages, but
this would require a shared function-as-trees infrastructure. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 6cdf2c8..de9668b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3157,16 +3157,6 @@ extern const char *dump_flag_name PARAMS ((enum tree_dump_index));
/* Assign the RTX to declaration. */
extern void set_decl_rtl PARAMS ((tree, rtx));
-
-/* In callgraph.c */
-void cgraph_finalize_function PARAMS ((tree, tree));
-void cgraph_finalize_compilation_unit PARAMS ((void));
-void cgraph_create_edges PARAMS ((tree, tree));
-void dump_cgraph PARAMS ((FILE *));
-void cgraph_optimize PARAMS ((void));
-void cgraph_remove_call PARAMS ((tree, tree));
-bool cgraph_calls_p PARAMS ((tree, tree));
-
/* Redefine abort to report an internal error w/o coredump, and
reporting the location of the error in the source file. This logic