aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Macleod <amacleod@redhat.com>2007-09-24 13:35:37 +0000
committerAndrew Macleod <amacleod@redhat.com>2007-09-24 13:35:37 +0000
commit8028052c75113e6984ea056878c6891db9a02850 (patch)
treed33d6a4dfeba1e2afcaa7ea130f80a21f0ae61e2
parent64c62824ba04882338ca0f5f87f97cde89453a89 (diff)
temp checking of files so they dont get lostssa-pressure-branch
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ssa-pressure-branch@128715 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/Makefile.in5
-rw-r--r--gcc/tree-outof-ssa.c9
-rw-r--r--gcc/tree-ssa-live.c50
-rw-r--r--gcc/tree-ssa-live.h23
-rw-r--r--gcc/tree-ssa-pressure.c433
-rw-r--r--gcc/tree-ssa-pressure.h200
6 files changed, 718 insertions, 2 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 051dacf3bc7..685fb7dd075 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1127,6 +1127,7 @@ OBJS-common = \
tree-ssa-operands.o \
tree-ssa-phiopt.o \
tree-ssa-pre.o \
+ tree-ssa-pressure.o \
tree-ssa-propagate.o \
tree-ssa-reassoc.o \
tree-ssa-sink.o \
@@ -1924,6 +1925,10 @@ tree-ssa-ter.o : tree-ssa-ter.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
tree-ssa-coalesce.o : tree-ssa-coalesce.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
$(TREE_SSA_LIVE_H) bitmap.h $(FLAGS_H) $(HASHTAB_H) toplev.h
+tree-ssa-pressure.o : tree-ssa-pressure.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ $(TREE_SSA_LIVE_H) bitmap.h $(FLAGS_H) $(HASHTAB_H) toplev.h \
+ tree-ssa-pressure.h
tree-outof-ssa.o : tree-outof-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) bitmap.h $(GGC_H) toplev.h
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 7e759ba8176..6092770793c 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -34,6 +34,7 @@ Boston, MA 02110-1301, USA. */
#include "tree-ssa-live.h"
#include "tree-pass.h"
#include "toplev.h"
+#include "tree-ssa-pressure.h"
/* Used to hold all the components required to do SSA PHI elimination.
@@ -1139,6 +1140,14 @@ remove_ssa_form (bool perform_ter)
map = coalesce_ssa_name ();
+ if (dump_file)
+ {
+ pressure_table_p p;
+ p = calculate_name_pressure (PRESS_INTEGER|PRESS_FLOAT, NULL);
+ dump_ssa_pressure (dump_file, p);
+ delete_pressure_table (p);
+ }
+
/* Return to viewing the variable list as just all reference variables after
coalescing has been performed. */
partition_view_normal (map, false);
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 7e98e2cf8e8..b60e89528fa 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -542,6 +542,8 @@ new_tree_live_info (var_map map)
live->work_stack = XNEWVEC (int, last_basic_block);
live->stack_top = live->work_stack;
+ live->dead_on_exit = NULL;
+
live->global = BITMAP_ALLOC (NULL);
return live;
}
@@ -565,6 +567,11 @@ delete_tree_live_info (tree_live_info_p live)
BITMAP_FREE (live->livein[x]);
free (live->livein);
+ if (live->dead_on_exit)
+ for (x = live->num_blocks - 1; x >= 0; x--)
+ BITMAP_FREE (live->dead_on_exit[x]);
+ free (live->dead_on_exit);
+
free (live);
}
@@ -716,7 +723,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
/* Calculate the live on exit vectors based on the entry info in LIVEINFO. */
-void
+static void
calculate_live_on_exit (tree_live_info_p liveinfo)
{
unsigned i;
@@ -757,6 +764,47 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
}
+/* Calculate the dead on exit vectors based on the entry and exit info in
+ LIVEINFO. Dead on exit are partitions which are used as PHI arguments in
+ successor blocks, but have no further uses. */
+
+void
+calculate_dead_on_exit (tree_live_info_p live)
+{
+ bitmap *doe, b;
+ basic_block bb;
+ edge e;
+ edge_iterator ei;
+ bitmap l = BITMAP_ALLOC (NULL);
+
+ gcc_assert (live->liveout);
+ gcc_assert (n_basic_blocks == live->num_blocks);
+
+ doe = XCNEWVEC (bitmap, n_basic_blocks);
+
+ FOR_EACH_BB (bb)
+ {
+ b = BITMAP_ALLOC (NULL);
+ bitmap_clear (l);
+ /* Calculate all partitions which are live on entry to a successor. */
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ if (e->dest == EXIT_BLOCK_PTR)
+ continue;
+ bitmap_ior_into (l, live_on_entry (live, e->dest));
+ }
+ /* Now calculate dead on exit by finding those that are live at exit
+ and NOT live on entry to a successor. Thse are the ssa_names which
+ go dead in PHI's, and thus go dead in a copy on an exit edge to BB. */
+ bitmap_and_compl (b, live_on_exit (live, bb), l);
+ doe[bb->index] = b;
+ }
+
+ BITMAP_FREE (l);
+ live->dead_on_exit = doe;
+}
+
+
/* Given partition map MAP, calculate all the live on entry bitmaps for
each partition. Return a new live info object. */
diff --git a/gcc/tree-ssa-live.h b/gcc/tree-ssa-live.h
index d0aeedf08df..85437e7ff91 100644
--- a/gcc/tree-ssa-live.h
+++ b/gcc/tree-ssa-live.h
@@ -274,11 +274,17 @@ typedef struct tree_live_info_d
/* Bitmap of what variables are live on exit for a basic blocks. */
bitmap *liveout;
+
+ /* Bitmap of what variables are dead on exit. This is defined as the
+ variables which are used in PHI arguments on at least one exit edge
+ from a block, but are not used beyond that. These are variables which
+ will have a use inserted on the exit edge during out of ssa. */
+ bitmap *dead_on_exit;
} *tree_live_info_p;
extern tree_live_info_p calculate_live_ranges (var_map);
-extern void calculate_live_on_exit (tree_live_info_p);
+extern void calculate_dead_on_exit (tree_live_info_p);
extern void delete_tree_live_info (tree_live_info_p);
#define LIVEDUMP_ENTRY 0x01
@@ -325,6 +331,21 @@ live_on_exit (tree_live_info_p live, basic_block bb)
}
+/* Return the bitmap from LIVE representing the dead on exit partitions from
+ block BB. */
+
+static inline bitmap
+dead_on_exit (tree_live_info_p live, basic_block bb)
+{
+ gcc_assert (live->dead_on_exit);
+ gcc_assert (bb != ENTRY_BLOCK_PTR);
+ gcc_assert (bb != EXIT_BLOCK_PTR);
+
+ return live->dead_on_exit[bb->index];
+}
+
+
+
/* Return the partition map which the information in LIVE utilizes. */
static inline var_map
diff --git a/gcc/tree-ssa-pressure.c b/gcc/tree-ssa-pressure.c
new file mode 100644
index 00000000000..0846b59e874
--- /dev/null
+++ b/gcc/tree-ssa-pressure.c
@@ -0,0 +1,433 @@
+/* Calculate and Manage SSA_NAME pressure.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+
+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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "diagnostic.h"
+#include "bitmap.h"
+#include "tree-flow.h"
+#include "hashtab.h"
+#include "tree-dump.h"
+#include "tree-ssa-live.h"
+#include "toplev.h"
+#include "tree-ssa-pressure.h"
+
+
+/* Initialize pressure unit object PTR with NUM stmt's. */
+
+static void
+init_pressure_unit (pressure_unit_p ptr, unsigned num)
+{
+ ptr->bb_start_pressure = XCNEWVEC (int, n_basic_blocks);
+ ptr->stmt_pressure = XCNEWVEC (struct stmt_pressure_unit_d, num);
+ ptr->uid_limit = num;
+}
+
+
+/* Clear pressure unit PTR, freeing any memory associated with it. */
+
+static void
+clear_pressure_unit (pressure_unit_p ptr)
+{
+ unsigned x;
+
+ for (x = 0; x < ptr->uid_limit; x++)
+ if (ptr->stmt_pressure[x].dead_partitions)
+ VEC_free (int, heap, ptr->stmt_pressure[x].dead_partitions);
+
+ free (ptr->stmt_pressure);
+ free (ptr->bb_start_pressure);
+}
+
+
+/* Create a new pressure table with UID_LIMIT stmt's and using FLAGS to select
+ functional units. */
+
+static pressure_table_p
+new_pressure_table (int uid_limit, int flags)
+{
+ pressure_table_p tab;
+ int unit_count = 0;
+ int *ftu;
+ int x;
+
+ ftu = xmalloc (sizeof (int) * (PRESS_MAX_FLAG + 1));
+ memset (ftu, 0xff, sizeof (int) * (PRESS_MAX_FLAG + 1));
+
+ if (flags & PRESS_INTEGER)
+ ftu[PRESS_INTEGER] = unit_count++;
+ if (flags & PRESS_FLOAT)
+ ftu[PRESS_FLOAT] = unit_count++;
+
+ tab = xmalloc (sizeof (struct pressure_table_d)
+ + sizeof (struct pressure_unit_d) * (unit_count - 1));
+
+ tab->flags = flags;
+ tab->unit_count = unit_count;
+ tab->flag_to_unit = ftu;
+
+ for (x = 0; x < unit_count; x++)
+ init_pressure_unit (&(tab->unit[x]), uid_limit);
+
+ return tab;
+}
+
+
+/* Delete pressure table TAB, freeing all associated memory. */
+
+void
+delete_pressure_table (pressure_table_p tab)
+{
+ int x;
+
+ for (x = 0; x < tab->unit_count; x++)
+ clear_pressure_unit (&(tab->unit[x]));
+
+ delete_tree_live_info (tab->live_info);
+ if (tab->owns_map)
+ delete_var_map (tab->map);
+ free (tab->flag_to_unit);
+ free (tab);
+}
+
+
+/* Get stmt pressure info for functional unit UNIT in STMT from table PTR. */
+
+static inline stmt_pressure_unit_p
+get_stmt_pressure_from_table (tree stmt, pressure_table_p ptr, int unit)
+{
+ unsigned uid = stmt_ann (stmt)->uid;
+ pressure_unit_p p;
+
+ gcc_assert (unit < ptr->unit_count);
+
+ p = &(ptr->unit[unit]);
+ gcc_assert (uid < p->uid_limit);
+ return &(p->stmt_pressure[uid]);
+}
+
+
+
+/* Add SSA_VAR to MAP if it is a type specified in FLAGS. */
+
+static void
+register_ssa_name (var_map map, tree ssa_var, int flags)
+{
+ /* Checking to see if its a partition already is a lot cheaper than
+ determining the type first. */
+ if (var_to_partition (map, ssa_var) != NO_PARTITION)
+ {
+ if (unit_type (ssa_var) & flags)
+ register_ssa_partition (map, ssa_var);
+ }
+}
+
+
+
+/* Add PARTITION to thr dead list of SP if it isn't already there. */
+
+static void
+add_to_dead_list (int partition, stmt_pressure_unit_p sp)
+{
+ if (sp->dead_partitions == NULL)
+ sp->dead_partitions = VEC_alloc (int, heap, 3);
+ else
+ if (in_dead_list_p (partition, sp))
+ return;
+
+ VEC_safe_push (int, heap, sp->dead_partitions, partition);
+}
+
+
+/* Process a use of PARTITION in STMT. If it is already in LIVE, then no action
+ needs to be taken. Otherwise this represents the last use of the partition.
+ That means the partition is dead at this stmt, and should be added to the
+ live list (since the block is being processed in reverse. TAB is the
+ pressure table. */
+
+
+static inline void
+maybe_goes_dead (int partition, tree stmt, bitmap live, pressure_table_p tab)
+{
+ pressure_unit_p press;
+ stmt_pressure_unit_p ptr;
+
+ /* If its already live, then it doesn't go dead at this stmt. */
+ if (bitmap_bit_p (live, partition))
+ return;
+
+ bitmap_set_bit (live, partition);
+ press = get_partition_unit (partition, tab);
+ ptr = get_stmt_pressure (stmt, press);
+ ptr->pressure_change -= 1;
+ add_to_dead_list (partition, ptr);
+}
+
+
+/* Process a def of PARTITION in STMT. If the def is dead (has no uses) it
+ will not be in LIVE. In any case, it must be removed from LIVE since this
+ marks the beginning of a live range, and the block is being stepped through
+ in reverse. TAB is the pressure table. */
+
+static inline void
+comes_alive (int partition, tree stmt, bitmap live, pressure_table_p tab)
+{
+ pressure_unit_p press = get_partition_unit (partition, tab);
+ stmt_pressure_unit_p ptr = get_stmt_pressure (stmt, press);
+
+ if (bitmap_bit_p (live, partition))
+ {
+ bitmap_clear_bit (live, partition);
+ ptr->pressure_change += 1;
+ }
+ else
+ add_to_dead_list (partition, ptr);
+}
+
+
+/* Main entry point which creates a pressure table for the functional units
+ specified in FLAGS. */
+
+pressure_table_p
+calculate_name_pressure (int flags, var_map vmap)
+{
+ var_map map;
+ tree var, stmt, phi;
+ tree_live_info_p live_info;
+ bitmap live;
+ pressure_table_p press;
+ basic_block bb;
+ block_stmt_iterator bsi;
+ ssa_op_iter iter;
+ int i;
+ unsigned uid = 0;
+ unsigned x;
+ bitmap_iterator bi;
+
+ if (vmap == NULL)
+ {
+ map = init_var_map (num_ssa_names + 1);
+
+ /* register all the partitions the pressure table cares about. */
+ FOR_EACH_BB (bb)
+ {
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ if (!is_gimple_reg (PHI_RESULT (phi)))
+ continue;
+
+ register_ssa_name (map, PHI_RESULT (phi), flags);
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ {
+ var = PHI_ARG_DEF (phi, i);
+ if (TREE_CODE (var) == SSA_NAME)
+ register_ssa_name (map, var, flags);
+ }
+ }
+
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ stmt = bsi_stmt (bsi);
+ stmt_ann (stmt)->uid = uid++;
+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter,
+ (SSA_OP_DEF|SSA_OP_USE))
+ register_ssa_name (map, var, flags);
+ }
+ }
+ }
+ else
+ {
+ map = vmap;
+ /* Calculate a UID for each stmt. */
+ FOR_EACH_BB (bb)
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ stmt_ann (bsi_stmt (bsi))->uid = uid++;
+ }
+
+ /* Now view the partition normally, with all unused ssa_names removed. */
+ partition_view_normal (map, false);
+
+ press = new_pressure_table (uid, flags);
+ press->map = map;
+ press->owns_map = (vmap == NULL);
+
+ /* calculate the live range info. */
+ live_info = calculate_live_ranges (map);
+ calculate_dead_on_exit (live_info);
+ press->live_info = live_info;
+
+
+ /* Walk through each basic block in reversem tracking which partitions are
+ live, and creating entries in the pressure table for each stmt. */
+ live = BITMAP_ALLOC (NULL);
+ FOR_EACH_BB (bb)
+ {
+ int p;
+
+ /* Walk each stmt. */
+ bitmap_copy (live, live_on_exit (live_info, bb));
+ for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
+ {
+ stmt = bsi_stmt (bsi);
+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF)
+ if ((p = var_to_partition (map, var)) != NO_PARTITION)
+ comes_alive (p, stmt, live, press);
+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
+ if ((p = var_to_partition (map, var)) != NO_PARTITION)
+ maybe_goes_dead (p, stmt, live, press);
+ }
+
+ /* Calculate starting register pressure in each block for each unit. */
+ EXECUTE_IF_SET_IN_BITMAP (live_on_entry (live_info, bb), 0, x, bi)
+ {
+ pressure_unit_p p = get_partition_unit (x, press);
+ p->bb_start_pressure[bb->index]++;
+ }
+
+ /* Add PHI results to the starting register pressure since they map to
+ copies on incoming edges during out-of-ssa. */
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ int part = var_to_partition (map, PHI_RESULT (phi));
+ if (part != NO_PARTITION)
+ {
+ pressure_unit_p p = get_partition_unit (part, press);
+ p->bb_start_pressure[bb->index]++;
+ }
+ }
+ }
+ BITMAP_FREE (live);
+
+ return press;
+}
+
+
+/* Dump table PRESS to output file F in a readable form. */
+
+void
+dump_ssa_pressure (FILE *f, pressure_table_p press)
+{
+ basic_block bb;
+ block_stmt_iterator bsi;
+ tree stmt, phi, var;
+ int i;
+ unsigned x;
+ stmt_pressure_unit_p sp;
+ bitmap_iterator bi;
+ int *curr_press;
+
+ curr_press = alloca (press->unit_count * sizeof (int));
+ FOR_EACH_BB (bb)
+ {
+ for (i = 0; i < press->unit_count; i++)
+ {
+ curr_press[i] = get_start_unit_pressure (press, bb, i);
+ fprintf (f, "[%3d] ", curr_press[i]);
+ }
+ fprintf (f, "Basic Block %d. Live on entry: ",
+ bb->index);
+
+ EXECUTE_IF_SET_IN_BITMAP (live_on_entry (press->live_info, bb), 0, x, bi)
+ {
+ print_generic_expr (f, partition_to_var (press->map, x), TDF_SLIM);
+ fprintf(f, " ");
+ }
+ fprintf(f, "\n");
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ {
+ for (i = 0; i < press->unit_count; i++)
+ fprintf (f, " ");
+ if (var_to_partition (press->map, PHI_RESULT (phi)) == NO_PARTITION)
+ print_generic_stmt (f, phi, TDF_SLIM);
+ else
+ {
+ print_generic_expr (f, PHI_RESULT(phi), TDF_SLIM);
+ fprintf (f, " = PHI <");
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ {
+ basic_block bb_src= PHI_ARG_EDGE (phi, i)->src;
+ if (i != 0)
+ fprintf (f, ", ");
+ var = PHI_ARG_DEF (phi, i);
+ print_generic_expr (f, var, TDF_SLIM);
+ if (TREE_CODE (var) == SSA_NAME &&
+ var_to_partition (press->map, var) != NO_PARTITION)
+ {
+ if (bitmap_bit_p (dead_on_exit(press->live_info, bb_src),
+ var_to_partition (press->map, var)))
+ fprintf (f, "##");
+ }
+ fprintf (f, "(%1d)", bb_src->index);
+ }
+ fprintf (f, ">;\n");
+ }
+ }
+
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ bool dead_printed = false;
+ stmt = bsi_stmt (bsi);
+ for (i = 0; i < press->unit_count; i++)
+ {
+ sp = get_stmt_pressure_from_table (stmt, press, i);
+ curr_press[i] += sp->pressure_change;
+ fprintf (f, "[%3d] ", curr_press[i]);
+ }
+ print_generic_expr (f, stmt, TDF_SLIM);
+ for (i = 0; i < press->unit_count; i++)
+ {
+ sp = get_stmt_pressure_from_table (stmt, press, i);
+ if (sp->dead_partitions)
+ {
+ if (!dead_printed)
+ {
+ fprintf (f, " ##dead list## - ");
+ dead_printed = true;
+ }
+ for (x = 0; x < VEC_length (int, sp->dead_partitions); x++)
+ {
+ if (x != 0)
+ fprintf (f, ", ");
+ print_generic_expr (f,
+ partition_to_var (press->map,
+ VEC_index (int,
+ sp->dead_partitions,
+ x)),
+ TDF_SLIM);
+ }
+ }
+ }
+ fprintf (f, "\n");
+ }
+
+ fprintf (f, "Dead on exit : ");
+ EXECUTE_IF_SET_IN_BITMAP (dead_on_exit (press->live_info, bb), 0, x, bi)
+ {
+ print_generic_expr (f, partition_to_var (press->map, x), TDF_SLIM);
+ fprintf(f, " ");
+ }
+ fprintf (f, "\n\n");
+ }
+}
diff --git a/gcc/tree-ssa-pressure.h b/gcc/tree-ssa-pressure.h
new file mode 100644
index 00000000000..a6a05431b42
--- /dev/null
+++ b/gcc/tree-ssa-pressure.h
@@ -0,0 +1,200 @@
+/* Header file for calculating and Managing SSA_NAME pressure.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+
+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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "vec.h"
+
+#ifndef _TREE_SSA_PRESSURE_H
+#define _TREE_SSA_PRESSURE_H
+
+
+/* This structure represents the changes in register pressure within a stmt. */
+
+typedef struct stmt_pressure_unit_d
+{
+ int pressure_change; /* Change in register pressure. */
+ VEC(int,heap) *dead_partitions; /* List of dead registers. */
+} *stmt_pressure_unit_p;
+
+
+/* Dynamic vector used to represent register pressure changes for any
+ new stmt's which have been created since the table was created. */
+DEF_VEC_P(stmt_pressure_unit_p);
+DEF_VEC_ALLOC_P(stmt_pressure_unit_p,heap);
+
+
+/* This represents the register pressure in the function for a single register
+ type. */
+
+typedef struct pressure_unit_d
+{
+ unsigned uid_limit; /* Upper UID of original stmts. */
+ int *bb_start_pressure; /* Vector of starting pressures. */
+ stmt_pressure_unit_p stmt_pressure; /* Stmt pressure vector. */
+} *pressure_unit_p;
+
+
+/* This represents register pressure for the entire function for multiple
+ functional units. It also contains all the live range info. */
+
+typedef struct pressure_table_d
+{
+ int flags; /* Flag for selecting units. */
+ int unit_count; /* Number of functional units. */
+ int *flag_to_unit; /* Convert flag bit to unit number. */
+ bool owns_map; /* Created var_map. */
+ var_map map; /* Partition map. */
+ tree_live_info_p live_info; /* Live range info. */
+ struct pressure_unit_d unit[1]; /* Stmt pressure units. */
+} *pressure_table_p;
+
+extern pressure_table_p calculate_name_pressure (int, var_map);
+extern void delete_pressure_table (pressure_table_p);
+extern void dump_ssa_pressure (FILE *, pressure_table_p);
+
+/* Funcitonal unit flags. */
+
+#define PRESS_INTEGER 0x01
+#define PRESS_FLOAT 0x02
+#define PRESS_MAX_FLAG (PRESS_FLOAT|PRESS_INTEGER)
+
+
+/* Return the BB starting pressure for UNIT in TAB. */
+
+static inline int
+get_start_unit_pressure (pressure_table_p tab, basic_block bb, int unit)
+{
+#ifdef ENABLE_CHECKING
+ gcc_assert (unit >= 0 && unit < tab->unit_count);
+#endif
+ return tab->unit[unit].bb_start_pressure[bb->index];
+}
+
+
+/* Return the BB starting pressure for the unit specified by FLAG in TAB. */
+
+static inline int
+get_start_pressure (pressure_table_p tab, basic_block bb, int flag)
+{
+ int unit;
+
+#ifdef ENABLE_CHECKING
+ /* Make sure 'flags' is in a valid range. */
+ gcc_assert ((flag & ~PRESS_MAX_FLAG) == 0);
+#endif
+
+ unit = tab->flag_to_unit[flag];
+ return get_start_unit_pressure (tab, bb, unit);
+}
+
+
+
+/* Return the flag representing the functional unit for SSA_NAME. */
+static int
+unit_type (tree ssa_name)
+{
+ tree type;
+ int ret = 0;
+ gcc_assert (TREE_CODE (ssa_name) == SSA_NAME);
+
+ type = TREE_TYPE (SSA_NAME_VAR (ssa_name));
+
+ if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
+ ret = PRESS_INTEGER;
+ else
+ if (SCALAR_FLOAT_TYPE_P (type) || COMPLEX_FLOAT_TYPE_P (type))
+ ret = PRESS_FLOAT;
+
+ return ret;
+}
+
+
+/* Return the unit number PARTITION belongs to in table PRESS. */
+
+static inline int
+partition_unit (int partition, pressure_table_p press)
+{
+ tree name = partition_to_var (press->map, partition);
+ int ret = unit_type (name);
+
+ gcc_assert (ret != 0);
+ return press->flag_to_unit[ret];
+}
+
+
+/* Return the pressure unit pointer which PARITION belongs to in TAB. */
+
+static pressure_unit_p
+get_partition_unit (int partition, pressure_table_p tab)
+{
+ int u = partition_unit (partition, tab);
+ return &(tab->unit[u]);
+}
+
+
+/* Get stmt pressure info from function unit PTR for STMT. */
+
+static inline stmt_pressure_unit_p
+get_stmt_pressure (tree stmt, pressure_unit_p ptr)
+{
+ unsigned uid = stmt_ann (stmt)->uid;
+ gcc_assert (uid < ptr->uid_limit);
+ return &(ptr->stmt_pressure[uid]);
+}
+
+
+/* Return TRUE if PARTITION is in the dead list of SP. */
+
+static inline bool
+in_dead_list_p (int partition, stmt_pressure_unit_p sp)
+{
+ unsigned x;
+
+ for (x = 0; x < VEC_length (int, sp->dead_partitions); x++)
+ if (VEC_index (int, sp->dead_partitions, x) == partition)
+ return true;
+
+ return false;
+}
+
+
+static inline bool
+dead_partition_in_stmt_p (pressure_table_p tab, tree stmt, int partition)
+{
+ pressure_unit_p unit_p;
+ stmt_pressure_unit_p stmt_press;
+
+#ifdef ENABLE_CHECKING
+ gcc_assert (partition != NO_PARTITION);
+#endif
+
+ unit_p = get_partition_unit (partition, tab);
+ stmt_press = get_stmt_pressure (stmt, unit_p);
+ return in_dead_list_p (partition, stmt_press);
+}
+
+static inline bool
+dead_name_in_stmt_p (pressure_table_p tab, tree stmt, tree ssa_name)
+{
+ int p = var_to_partition (tab->map, ssa_name);
+ return dead_partition_in_stmt_p (tab, stmt, p);
+}
+
+#endif