Changes in include:

* partition.h: New file.

Changes in libiberty:

	* Makefile.in (CFILES): Add partition.c.
	(REQUIRED_OFILES): Add partition.o.
	(partition.o): New rule.
	* partition.c: New file.

Changes in gcc:

	* Makefile.in (ssa.o): New rule.
	(OBJS): Add ssa.o.
	(STAGESTUFF): Add *.ssa and *.ussa.
	(mostlyclean): Delete *.ssa, *.ussa, */*.ssa, */*.ussa.
	* rtl.def (PHI): New RTL expression.
	* rtl.h (clear_log_links): New declaration.
	(convert_to_ssa): Likewise.
	(convert_from_ssa): Likewise.
	* flow.c (split_edge): If the entry node falls through to the
	split edge's source block, split the entry edge.
	(clear_log_links): New function.
	* toplev.c (ssa_dump): New variable.
	(flag_ssa): Likewise.
	(f_options): Add "ssa".
	(compile_file): Create SSA dump files.
	(rest_of_compilation): Go to and from SSA if enabled.
	(decide_d_option): Handle -de for SSA dump files.
	* ssa.c: New file.

From-SVN: r32465
This commit is contained in:
Alex Samuel 2000-03-10 08:16:55 +00:00
parent ea7f51a4af
commit d9d4fb433e
12 changed files with 1893 additions and 15 deletions

View File

@ -1,3 +1,25 @@
2000-03-09 Richard Henderson <rth@cygnus.com>
Alex Samuel <samuel@codesourcery.com> and others
* Makefile.in (ssa.o): New rule.
(OBJS): Add ssa.o.
(STAGESTUFF): Add *.ssa and *.ussa.
(mostlyclean): Delete *.ssa, *.ussa, */*.ssa, */*.ussa.
* rtl.def (PHI): New RTL expression.
* rtl.h (clear_log_links): New declaration.
(convert_to_ssa): Likewise.
(convert_from_ssa): Likewise.
* flow.c (split_edge): If the entry node falls through to the
split edge's source block, split the entry edge.
(clear_log_links): New function.
* toplev.c (ssa_dump): New variable.
(flag_ssa): Likewise.
(f_options): Add "ssa".
(compile_file): Create SSA dump files.
(rest_of_compilation): Go to and from SSA if enabled.
(decide_d_option): Handle -de for SSA dump files.
* ssa.c: New file.
Thu Mar 9 20:01:38 2000 Jim Wilson <wilson@cygnus.com>
* expr.c (expand_assignment): For a CALL_EXPR, special case PARM_DECL

View File

@ -674,7 +674,7 @@ OBJS = diagnostic.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o \
predict.o lists.o ggc-common.o $(GGC) simplify-rtx.o
predict.o lists.o ggc-common.o $(GGC) simplify-rtx.o ssa.o
# GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
@ -704,6 +704,7 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
gcov$(exeext) *.bp \
*.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop \
*.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse *.flow2 *.peephole2 \
*.ssa *.ussa \
*.[si] libcpp.a \
$(LANG_STAGESTUFF)
@ -1565,6 +1566,8 @@ resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h system.h \
insn-attr.h
lcm.o : lcm.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h insn-attr.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H)
ssa.o : ssa.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) $(BASIC_BLOCK_H) \
output.h insn-config.h
profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \
gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h function.h insn-config.h \
ggc.h
@ -2355,11 +2358,11 @@ mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean
# Delete debugging dump files.
-rm -f *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop
-rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.addressof
-rm -f *.regmove *.mach *.bp *.gcse *.flow2 *.peephole2
-rm -f *.regmove *.mach *.bp *.gcse *.flow2 *.peephole2 *.ssa *.ussa
-rm -f */*.greg */*.lreg */*.combine */*.flow */*.cse */*.jump */*.rtl
-rm -f */*.tree */*.loop */*.dbr */*.jump2 */*.sched */*.cse2
-rm -f */*.sched2 */*.stack */*.regmove */*.gcse */*.flow2
-rm -f */*.peephole2
-rm -f */*.peephole2 */*.ssa */*.ussa
# Delete some files made during installation.
-rm -f specs float.h-* enquire SYSCALLS.c.X SYSCALLS.c
-rm -f collect collect2 mips-tfile mips-tdump alloca.s

View File

@ -362,6 +362,7 @@ static void fixup_reorder_chain PARAMS ((void));
it being unused. */
void verify_flow_info PARAMS ((void));
int flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
void clear_log_links PARAMS ((rtx));
/* Find basic blocks of the current function.
F is the first insn of the function and NREGS the number of register
@ -1369,7 +1370,8 @@ split_edge (edge_in)
basic_block jump_block;
rtx pos;
if ((e->flags & EDGE_CRITICAL) == 0)
if ((e->flags & EDGE_CRITICAL) == 0
&& e->src != ENTRY_BLOCK_PTR)
{
/* Non critical -- we can simply add a jump to the end
of the existing predecessor. */
@ -7047,7 +7049,6 @@ flow_loop_outside_edge_p (loop, e)
}
typedef struct reorder_block_def {
int flags;
int index;
@ -7769,3 +7770,14 @@ reorder_basic_blocks ()
flow_loops_free (&loops_info);
}
/* Clear LOG_LINKS fields of insns in a chain. */
void
clear_log_links (insns)
rtx insns;
{
rtx i;
for (i = insns; i; i = NEXT_INSN (i))
if (GET_RTX_CLASS (GET_CODE (i)) == 'i')
LOG_LINKS (i) = 0;
}

View File

@ -880,6 +880,21 @@ DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p_rtx", "e", 'x')
after we select a call method. */
DEF_RTL_EXPR(CALL_PLACEHOLDER, "call_placeholder", "uuuu", 'x')
/* The SSA phi operator.
The argument is a vector of 2N rtxes. Element 2N+1 is a CONST_INT
containing the block number of the predecessor through which control
has passed when the register at element 2N is used.
Note that PHI may only appear at the beginning of a basic block.
??? There may be multiple PHI insns, but they are all evaluated
in parallel. This probably ought to be changed to use a real
PARALLEL, as that would be less confusing and more in the spirit
of canonical RTL. It is, however, easier to manipulate this way. */
DEF_RTL_EXPR(PHI, "phi", "E", 'x')
/*
Local variables:
mode:c

View File

@ -1149,6 +1149,7 @@ void free_EXPR_LIST_node PARAMS ((rtx));
void free_INSN_LIST_node PARAMS ((rtx));
rtx alloc_INSN_LIST PARAMS ((rtx, rtx));
rtx alloc_EXPR_LIST PARAMS ((int, rtx, rtx));
void clear_log_links PARAMS ((rtx));
/* regclass.c */
@ -1710,6 +1711,10 @@ extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
extern int stack_regs_mentioned PARAMS ((rtx insn));
#endif
/* In ssa.c */
extern void convert_to_ssa PARAMS ((void));
extern void convert_from_ssa PARAMS ((void));
/* In toplev.c */
extern rtx stack_limit_rtx;

1503
gcc/ssa.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -257,6 +257,7 @@ int stack_reg_dump = 0;
#ifdef MACHINE_DEPENDENT_REORG
int mach_dep_reorg_dump = 0;
#endif
int ssa_dump = 0;
static int flag_print_mem = 0;
static int version_flag = 0;
static char * filename = 0;
@ -695,6 +696,9 @@ int flag_gnu_linker = 0;
int flag_gnu_linker = 1;
#endif
/* Enable SSA. */
int flag_ssa = 0;
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0;
@ -997,6 +1001,8 @@ lang_independent_options f_options[] =
"Suppress output of instruction numbers and line number notes in debugging dumps"},
{"instrument-functions", &flag_instrument_function_entry_exit, 1,
"Instrument function entry/exit with profiling calls"},
{"ssa", &flag_ssa, 1,
"Enable SSA optimizations" },
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
@ -2152,6 +2158,11 @@ compile_file (name)
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".03.addressof");
}
if (ssa_dump)
{
clean_dump_file (".033.ssa");
clean_dump_file (".037.ussa");
}
if (gcse_dump)
{
clean_dump_file (".04.gcse");
@ -3125,6 +3136,30 @@ rest_of_compilation (decl)
if (ggc_p)
ggc_collect ();
if (flag_ssa)
{
if (ssa_dump)
open_dump_file (".033.ssa", decl_printable_name (decl, 2));
convert_to_ssa ();
if (ssa_dump)
close_dump_file (print_rtl_with_bb, insns);
if (ssa_dump)
open_dump_file (".037.ussa", decl_printable_name (decl, 2));
convert_from_ssa ();
/* New registers have been created. Rescan their usage. */
reg_scan (insns, max_reg_num (), 1);
if (ssa_dump)
close_dump_file (print_rtl_with_bb, insns);
/* Life analysis used in SSA adds log_links but these shouldn't
be there until the flow stage, so clear them away. */
clear_log_links (insns);
if (ggc_p)
ggc_collect ();
}
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
@ -4021,6 +4056,7 @@ decode_d_option (arg)
mach_dep_reorg_dump = 1;
#endif
peephole2_dump = 1;
ssa_dump = 1;
break;
case 'A':
flag_debug_asm = 1;
@ -4039,6 +4075,9 @@ decode_d_option (arg)
dbr_sched_dump = 1;
break;
#endif
case 'e':
ssa_dump = 1;
break;
case 'f':
flow_dump = 1;
break;

View File

@ -1,3 +1,7 @@
2000-03-09 Alex Samuel <samuel@codesourcery.com>
* partition.h: New file.
2000-03-09 Zack Weinberg <zack@wolery.cumb.org>
* hashtab.h (struct htab): Add del_f.

81
include/partition.h Normal file
View File

@ -0,0 +1,81 @@
/* List implentation of a partition of consecutive integers.
Copyright (C) 2000 Free Software Foundation, Inc.
Contributed by CodeSourcery, LLC.
This file is part of GNU CC.
GNU CC 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.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This package implements a partition of consecutive integers. The
elements are partitioned into classes. Each class is represented
by one of its elements, the canonical element, which is chosen
arbitrarily from elements in the class. The principal operations
on a partition are FIND, which takes an element, determines its
class, and returns the canonical element for that class, and UNION,
which unites the two classes that contain two given elements into a
single class.
The list implementation used here provides constant-time finds. By
storing the size of each class with the class's canonical element,
it is able to perform unions over all the classes in the partition
in O (N log N) time. */
#ifndef _PARTITION_H
#define _PARTITION_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <ansidecl.h>
#include <stdio.h>
struct partition_elem
{
/* The canonical element that represents the class containing this
element. */
int class_element;
/* The next element in this class. Elements in each class form a
circular list. */
struct partition_elem* next;
/* The number of elements in this class. Valid only if this is the
canonical element for its class. */
unsigned class_count;
};
typedef struct partition_def
{
/* The number of elements in this partition. */
int num_elements;
/* The elements in the partition. */
struct partition_elem elements[1];
} *partition;
extern partition partition_new PARAMS((int));
extern void partition_delete PARAMS((partition));
extern int partition_union PARAMS((partition,
int,
int));
extern void partition_print PARAMS((partition,
FILE*));
/* Returns the canonical element corresponding to the class containing
ELEMENT__ in PARTITION__. */
#define partition_find(partition__, element__) \
((partition__)->elements[(element__)].class_element)
#endif /* _PARTITION_H */

View File

@ -1,3 +1,10 @@
2000-03-09 Alex Samuel <samuel@codesourcery.com>
* Makefile.in (CFILES): Add partition.c.
(REQUIRED_OFILES): Add partition.o.
(partition.o): New rule.
* partition.c: New file.
2000-03-09 Zack Weinberg <zack@wolery.cumb.org>
* hashtab.c (htab_create): Set del_f.

View File

@ -123,21 +123,22 @@ HFILES = alloca-conf.h
# NOTE: If you add new files to the library, add them to this list
# (alphabetical), and add them to REQUIRED_OFILES or funcs in
# configure.in.
CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \
CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \
bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c fdmatch.c \
fnmatch.c getcwd.c getpwd.c getopt.c getopt1.c getpagesize.c \
getruntime.c floatformat.c hashtab.c hex.c index.c insque.c memchr.c \
memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \
pexecute.c putenv.c random.c rename.c rindex.c setenv.c sigsetmask.c \
spaces.c splay-tree.c strcasecmp.c strncasecmp.c strchr.c strdup.c \
strerror.c strrchr.c strsignal.c strstr.c strtod.c strtol.c strtoul.c \
tmpnam.c vasprintf.c vfork.c vfprintf.c vprintf.c vsprintf.c \
waitpid.c xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c xstrerror.c
fnmatch.c getcwd.c getpwd.c getopt.c getopt1.c getpagesize.c \
getruntime.c floatformat.c hashtab.c hex.c index.c insque.c memchr.c \
memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \
partition.c pexecute.c putenv.c random.c rename.c rindex.c \
setenv.c sigsetmask.c spaces.c splay-tree.c strcasecmp.c \
strncasecmp.c strchr.c strdup.c strerror.c strrchr.c \
strsignal.c strstr.c strtod.c strtol.c strtoul.c tmpnam.c \
vasprintf.c vfork.c vfprintf.c vprintf.c vsprintf.c waitpid.c \
xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c xstrerror.c
# These are always included in the library.
REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o \
fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o hashtab.o \
hex.o floatformat.o objalloc.o obstack.o pexecute.o spaces.o \
hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o spaces.o \
splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \
xmemdup.o xstrdup.o xstrerror.o
@ -271,6 +272,7 @@ floatformat.o: $(INCDIR)/floatformat.h
mkstemps.o: config.h
objalloc.o: $(INCDIR)/objalloc.h
obstack.o: config.h $(INCDIR)/obstack.h
partition.o: $(INCDIR)/partition.h
pexecute.o: config.h $(INCDIR)/libiberty.h
setenv.o: config.h
spaces.o: $(INCDIR)/libiberty.h

185
libiberty/partition.c Normal file
View File

@ -0,0 +1,185 @@
/* List implentation of a partition of consecutive integers.
Copyright (C) 2000 Free Software Foundation, Inc.
Contributed by CodeSourcery, LLC.
This file is part of GNU CC.
GNU CC 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.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include "libiberty.h"
#include "partition.h"
/* Creates a partition of NUM_ELEMENTS elements. Initially each
element is in a class by itself. */
partition
partition_new (num_elements)
int num_elements;
{
int e;
partition part = (partition)
xmalloc (sizeof (struct partition_def) +
(num_elements - 1) * sizeof (struct partition_elem));
part->num_elements = num_elements;
for (e = 0; e < num_elements; ++e)
{
part->elements[e].class_element = e;
part->elements[e].next = &(part->elements[e]);
part->elements[e].class_count = 1;
}
return part;
}
/* Freeds a partition. */
void
partition_delete (part)
partition part;
{
free (part);
}
/* Unites the classes containing ELEM1 and ELEM2 into a single class
of partition PART. If ELEM1 and ELEM2 are already in the same
class, does nothing. Returns the canonical element of the
resulting union class. */
int
partition_union (part, elem1, elem2)
partition part;
int elem1;
int elem2;
{
struct partition_elem *elements = part->elements;
struct partition_elem *e1;
struct partition_elem *e2;
struct partition_elem *p;
struct partition_elem *old_next;
/* The canonical element of the resulting union class. */
int class_element = elements[elem1].class_element;
/* If they're already in the same class, do nothing. */
if (class_element == elements[elem2].class_element)
return class_element;
/* Make sure ELEM1 is in the larger class of the two. If not, swap
them. This way we always scan the shorter list. */
if (elements[elem1].class_count < elements[elem2].class_count)
{
int temp = elem1;
elem1 = elem2;
elem2 = temp;
class_element = elements[elem1].class_element;
}
e1 = &(elements[elem1]);
e2 = &(elements[elem2]);
/* Keep a count of the number of elements in the list. */
elements[class_element].class_count
+= elements[e2->class_element].class_count;
/* Update the class fields in elem2's class list. */
e2->class_element = class_element;
for (p = e2->next; p != e2; p = p->next)
p->class_element = class_element;
/* Splice ELEM2's class list into ELEM1's. These are circular
lists. */
old_next = e1->next;
e1->next = e2->next;
e2->next = old_next;
return class_element;
}
/* Compare elements ELEM1 and ELEM2 from array of integers, given a
pointer to each. Used to qsort such an array. */
static int
elem_compare (elem1, elem2)
const void *elem1;
const void *elem2;
{
int e1 = * (int *) elem1;
int e2 = * (int *) elem2;
if (e1 < e2)
return -1;
else if (e1 > e2)
return 1;
else
return 0;
}
/* Prints PART to the file pointer FP. The elements of each
class are sorted. */
void
partition_print (part, fp)
partition part;
FILE *fp;
{
char *done;
int num_elements = part->num_elements;
struct partition_elem *elements = part->elements;
int *class_elements;
int e;
/* Flag the elements we've already printed. */
done = (char *) xmalloc (num_elements);
memset (done, 0, num_elements);
/* A buffer used to sort elements in a class. */
class_elements = (int *) xmalloc (num_elements * sizeof (int));
fputc ('[', fp);
for (e = 0; e < num_elements; ++e)
/* If we haven't printed this element, print its entire class. */
if (! done[e])
{
int c = e;
int count = elements[elements[e].class_element].class_count;
int i;
/* Collect the elements in this class. */
for (i = 0; i < count; ++i) {
class_elements[i] = c;
done[c] = 1;
c = elements[c].next - elements;
}
/* Sort them. */
qsort ((void *) class_elements, count, sizeof (int), &elem_compare);
/* Print them. */
fputc ('(', fp);
for (i = 0; i < count; ++i)
fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]);
fputc (')', fp);
}
fputc (']', fp);
free (done);
}