aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Jaeger <aj@suse.de>2001-08-04 08:08:00 +0200
committerAndreas Jaeger <aj@gcc.gnu.org>2001-08-04 08:08:00 +0200
commitaaa4ca30d8d379dd66fa64be94380b1edc250070 (patch)
treef2aaaa047da4a9f10c9f8e1fd2dfb9a363bb6a69
parentda9314d50b777a4ba3071557e52d82ba8ee40e29 (diff)
downloadgcc-aaa4ca30d8d379dd66fa64be94380b1edc250070.zip
gcc-aaa4ca30d8d379dd66fa64be94380b1edc250070.tar.gz
gcc-aaa4ca30d8d379dd66fa64be94380b1edc250070.tar.bz2
As requested by Daniel Berlin since bootstrapping on i686-linux-gnu fails:
As requested by Daniel Berlin since bootstrapping on i686-linux-gnu fails: * gcse.c: Revert Daniel's last patch. From-SVN: r44626
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/gcse.c453
2 files changed, 145 insertions, 312 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 80c427b..92bf8d4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2001-08-04 Andreas Jaeger <aj@suse.de>
+
+ * gcse.c: Revert Daniel's last patch.
+
2001-08-03 Zack Weinberg <zackw@stanford.edu>
* sparc-protos.h: Add prototypes for fp_zero_operand and
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 349eae6..4fe1b3b 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -160,8 +160,8 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "ggc.h"
#include "params.h"
+
#include "obstack.h"
-#include "df.h"
#define obstack_chunk_alloc gmalloc
#define obstack_chunk_free free
@@ -305,10 +305,6 @@ static char can_copy_p[(int) NUM_MACHINE_MODES];
/* Non-zero if can_copy_p has been initialized. */
static int can_copy_init_p;
-/* Dataflow analyzer */
-struct df *df_analyzer;
-
-
struct reg_use {rtx reg_rtx; };
/* Hash table of expressions. */
@@ -470,8 +466,8 @@ struct ls_expr
{
struct expr * expr; /* Gcse expression reference for LM. */
rtx pattern; /* Pattern of this mem. */
- rtx loads; /* INSN list for where load appears */
- rtx stores; /* INSN list for where store appears */
+ rtx loads; /* INSN list of loads seen. */
+ rtx stores; /* INSN list of stores seen. */
struct ls_expr * next; /* Next in the list. */
int invalid; /* Invalid for some reason. */
int index; /* If it maps to a bitmap index. */
@@ -680,13 +676,14 @@ static void invalidate_any_buried_refs PARAMS ((rtx));
static void compute_ld_motion_mems PARAMS ((void));
static void trim_ld_motion_mems PARAMS ((void));
static void update_ld_motion_stores PARAMS ((struct expr *));
-static int store_ops_ok PARAMS ((rtx, basic_block, rtx, int));
+static void reg_set_info PARAMS ((rtx, rtx, void *));
+static int store_ops_ok PARAMS ((rtx, basic_block));
static void find_moveable_store PARAMS ((rtx));
static int compute_store_table PARAMS ((void));
static int load_kills_store PARAMS ((rtx, rtx));
static int find_loads PARAMS ((rtx, rtx));
static int store_killed_in_insn PARAMS ((rtx, rtx));
-static int store_killed_after PARAMS ((rtx, rtx, basic_block, int));
+static int store_killed_after PARAMS ((rtx, rtx, basic_block));
static int store_killed_before PARAMS ((rtx, rtx, basic_block));
static void build_store_vectors PARAMS ((void));
static void insert_insn_start_bb PARAMS ((rtx, basic_block));
@@ -1469,6 +1466,7 @@ mems_conflict_for_gcse_p (dest, setter, data)
elsewhere. */
if (GET_CODE (dest) != MEM)
return;
+
/* If we are setting a MEM in our list of specially recognized MEMs,
don't mark as killed this time. */
@@ -1478,6 +1476,7 @@ mems_conflict_for_gcse_p (dest, setter, data)
gcse_mems_conflict_p = 1;
return;
}
+
if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand,
rtx_addr_varies_p))
gcse_mems_conflict_p = 1;
@@ -1755,7 +1754,6 @@ hash_expr_1 (x, mode, do_not_record_p)
hash += hash_string_1 (XSTR (x, i));
else if (fmt[i] == 'i')
hash += (unsigned int) XINT (x, i);
- else if (fmt[i] == 't');
else
abort ();
}
@@ -1914,9 +1912,8 @@ expr_equiv_p (x, y)
break;
case '0':
- case 't':
break;
-
+
default:
abort ();
}
@@ -5899,9 +5896,9 @@ static void
free_ldst_entry (ptr)
struct ls_expr * ptr;
{
+ free_INSN_LIST_list (& ptr->loads);
+ free_INSN_LIST_list (& ptr->stores);
- free_INSN_LIST_list (&ptr->stores);
- free_INSN_LIST_list (&ptr->loads);
free (ptr);
}
@@ -6022,11 +6019,10 @@ simple_mem (x)
if (GET_MODE (x) == BLKmode)
return 0;
-#if 0
- /* See comment in find_moveable_store */
- if (!rtx_addr_varies_p (XEXP (x, 0), 0))
+
+ if (!rtx_varies_p (XEXP (x, 0), 0))
return 1;
-#endif
+
return 0;
}
@@ -6108,6 +6104,7 @@ compute_ld_motion_mems ()
/* Make sure there isn't a buried load somewhere. */
invalidate_any_buried_refs (src);
}
+
/* Check for stores. Don't worry about aliased ones, they
will block any movement we might do later. We only care
about this exact pattern since those are the only
@@ -6254,59 +6251,37 @@ update_ld_motion_stores (expr)
/* Store motion code. */
+/* This is used to communicate the target bitvector we want to use in the
+ reg_set_info routine when called via the note_stores mechanism. */
+static sbitmap * regvec;
+
/* Used in computing the reverse edge graph bit vectors. */
static sbitmap * st_antloc;
/* Global holding the number of store expressions we are dealing with. */
static int num_stores;
+/* Checks to set if we need to mark a register set. Called from note_stores. */
-/* Mark which registers are used by the mem, in the sbitmap used. */
-static int
-mark_mem_regs (x, used)
- rtx x;
- sbitmap used;
+static void
+reg_set_info (dest, setter, data)
+ rtx dest, setter ATTRIBUTE_UNUSED;
+ void * data ATTRIBUTE_UNUSED;
{
- register const char *fmt;
- int i, j;
-
- if (GET_CODE (x) == REG)
- {
- if (!TEST_BIT (used, REGNO (x)))
- {
- SET_BIT (used, REGNO (x));
- return 1;
-}
- return 0;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (mark_mem_regs (XEXP (x, i),used))
- return 1;
- }
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (mark_mem_regs (XVECEXP (x, i, j),used))
- return 1;
- }
+ if (GET_CODE (dest) == SUBREG)
+ dest = SUBREG_REG (dest);
- return 0;
+ if (GET_CODE (dest) == REG)
+ SET_BIT (*regvec, REGNO (dest));
}
-
/* Return non-zero if the register operands of expression X are killed
- before/after insn in basic block BB. */
+ anywhere in basic block BB. */
static int
-store_ops_ok (x, bb,insn, before)
+store_ops_ok (x, bb)
rtx x;
basic_block bb;
- rtx insn;
- int before;
{
int i;
enum rtx_code code;
@@ -6322,46 +6297,10 @@ store_ops_ok (x, bb,insn, before)
switch (code)
{
case REG:
- {
- /* Okay, since the reg def chains are ordered by bb/insn
- (since that's how it calculates them, and even if it didn't,
- we could just sort them), we just walk until we find a def
- in our BB, then walk until we find a def after/before our
- insn, and if we find a reg def after/before our insn, in the
- same bb, we return the approriate value. If there is no
- such def, to prevent walking *every* reg def, we stop once
- we are out of our BB again. */
- struct df_link *currref;
- bool thereyet=FALSE;
- for (currref = df_analyzer->regs[REGNO(x)].defs;
- currref;
- currref = currref->next)
- {
- if (! (DF_REF_BB (currref->ref) == bb))
- {
- if (!thereyet)
- continue;
- else
- return 1;
- }
- if (before)
- {
- if (INSN_UID (DF_REF_INSN (currref->ref)) >= INSN_UID (insn))
- continue;
- }
- else
- {
- if (INSN_UID (DF_REF_INSN (currref->ref)) < INSN_UID (insn))
- continue;
- }
- thereyet = TRUE;
- if (DF_REF_TYPE (currref->ref) == DF_REF_REG_DEF)
- return 0;
- }
- return 1;
- }
+ /* If a reg has changed after us in this
+ block, the operand has been killed. */
+ return TEST_BIT (reg_set_in_block[bb->index], REGNO (x));
-
case MEM:
x = XEXP (x, 0);
goto repeat;
@@ -6405,7 +6344,7 @@ store_ops_ok (x, bb,insn, before)
goto repeat;
}
- if (! store_ops_ok (tem, bb, insn, before))
+ if (! store_ops_ok (tem, bb))
return 0;
}
else if (fmt[i] == 'E')
@@ -6414,7 +6353,7 @@ store_ops_ok (x, bb,insn, before)
for (j = 0; j < XVECLEN (x, i); j++)
{
- if (! store_ops_ok (XVECEXP (x, i, j), bb, insn, before))
+ if (! store_ops_ok (XVECEXP (x, i, j), bb))
return 0;
}
}
@@ -6423,9 +6362,7 @@ store_ops_ok (x, bb,insn, before)
return 1;
}
-/* Determine whether insn is MEM store pattern that we will consider
- moving. We'll consider moving pretty much anything that we can
- move safely. */
+/* Determine whether insn is MEM store pattern that we will consider moving. */
static void
find_moveable_store (insn)
@@ -6434,9 +6371,6 @@ find_moveable_store (insn)
struct ls_expr * ptr;
rtx dest = PATTERN (insn);
- /* It's it's not a set, it's not a mem store we want to consider.
- Also, if it's an ASM, we certainly don't want to try to touch
- it. */
if (GET_CODE (dest) != SET
|| GET_CODE (SET_SRC (dest)) == ASM_OPERANDS)
return;
@@ -6445,43 +6379,66 @@ find_moveable_store (insn)
if (GET_CODE (dest) != MEM || MEM_VOLATILE_P (dest)
|| GET_MODE (dest) == BLKmode)
+ return;
+
+ if (GET_CODE (XEXP (dest, 0)) != SYMBOL_REF)
return;
-#if 0
- /* ??? Is this conservative, or just correct? We get more
- *candidates* without it, but i don't think we ever remove any
- stores where the address did vary. */
- if (rtx_addr_varies_p (XEXP (dest, 0), 0))
+
+ if (rtx_varies_p (XEXP (dest, 0), 0))
return;
-#endif
+
ptr = ldst_entry (dest);
ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
}
-/* Perform store motion.
- Store motion is modeled as a lazy code motion problem, like PRE is
- above. The main diffence is that we want to move stores down as far
- as possible, so we have LCM work on the reverse flowgraph. */
+/* Perform store motion. Much like gcse, except we move expressions the
+ other way by looking at the flowgraph in reverse. */
static int
compute_store_table ()
{
int bb, ret;
+ unsigned regno;
rtx insn, pat;
+
max_gcse_regno = max_reg_num ();
+ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
+ max_gcse_regno);
+ sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
pre_ldst_mems = 0;
+
/* Find all the stores we care about. */
for (bb = 0; bb < n_basic_blocks; bb++)
{
+ regvec = & (reg_set_in_block[bb]);
for (insn = BLOCK_END (bb);
insn && insn != PREV_INSN (BLOCK_HEAD (bb));
insn = PREV_INSN (insn))
{
- /* Ignore anything that is not a normal insn. */
- if (!INSN_P (insn))
+#ifdef NON_SAVING_SETJMP
+ if (NON_SAVING_SETJMP && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ {
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ SET_BIT (reg_set_in_block[bb], regno);
+ continue;
+ }
+#endif
+ /* Ignore anything that is not a normal insn. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
+ SET_BIT (reg_set_in_block[bb], regno);
+ }
+
pat = PATTERN (insn);
+ note_stores (pat, reg_set_info, NULL);
+
/* Now that we've marked regs, look for stores. */
if (GET_CODE (pat) == SET)
find_moveable_store (insn);
@@ -6499,8 +6456,7 @@ compute_store_table ()
return ret;
}
-/* Check to see if the load X is aliased with STORE_PATTERN.
- If it is, it means that load kills the store.*/
+/* Check to see if the load X is aliased with STORE_PATTERN. */
static int
load_kills_store (x, store_pattern)
@@ -6511,8 +6467,8 @@ load_kills_store (x, store_pattern)
return 0;
}
-/* Go through the entire insn X, looking for any loads which might
- alias, and therefore, kill, STORE_PATTERN. Return 1 if found. */
+/* Go through the entire insn X, looking for any loads which might alias
+ STORE_PATTERN. Return 1 if found. */
static int
find_loads (x, store_pattern)
@@ -6568,10 +6524,9 @@ store_killed_in_insn (x, insn)
rtx pat = PATTERN (insn);
/* Check for memory stores to aliased objects. */
if (GET_CODE (SET_DEST (pat)) == MEM && !expr_equiv_p (SET_DEST (pat), x))
- {
+ /* pretend its a load and check for aliasing. */
if (find_loads (SET_DEST (pat), x))
return 1;
- }
return find_loads (SET_SRC (pat), x);
}
else
@@ -6582,31 +6537,31 @@ store_killed_in_insn (x, insn)
within basic block BB. */
static int
-store_killed_after (x, insn, bb, testops)
+store_killed_after (x, insn, bb)
rtx x, insn;
basic_block bb;
- int testops;
{
rtx last = bb->end;
if (insn == last)
return 0;
-
- if (testops)
- /* Check if the register operands of the store are OK in this block.*/
- if (!store_ops_ok (XEXP (x, 0), bb, insn, 0))
+
+ /* Check if the register operands of the store are OK in this block.
+ Note that if registers are changed ANYWHERE in the block, we'll
+ decide we can't move it, regardless of whether it changed above
+ or below the store. This could be improved by checking the register
+ operands while lookinng for aliasing in each insn. */
+ if (!store_ops_ok (XEXP (x, 0), bb))
return 1;
- for ( ;
- insn && insn != NEXT_INSN (last);
- insn = NEXT_INSN (insn))
+ for ( ; insn && insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
if (store_killed_in_insn (x, insn))
return 1;
return 0;
}
-/* Returns 1 if the expression X is loaded or clobbered before INSN
+/* Returns 1 if the expression X is loaded or clobbered on or before INSN
within basic block BB. */
static int
store_killed_before (x, insn, bb)
@@ -6617,14 +6572,16 @@ store_killed_before (x, insn, bb)
if (insn == first)
return store_killed_in_insn (x, insn);
- /* Check if the register operands of the store are OK in this block.*/
- if (!store_ops_ok (XEXP (x, 0), bb, insn, 1))
+
+ /* Check if the register operands of the store are OK in this block.
+ Note that if registers are changed ANYWHERE in the block, we'll
+ decide we can't move it, regardless of whether it changed above
+ or below the store. This could be improved by checking the register
+ operands while lookinng for aliasing in each insn. */
+ if (!store_ops_ok (XEXP (x, 0), bb))
return 1;
- for (insn = PREV_INSN (insn) ;
- insn && insn != PREV_INSN (first);
- insn = PREV_INSN (insn))
-
+ for ( ; insn && insn != PREV_INSN (first); insn = PREV_INSN (insn))
if (store_killed_in_insn (x, insn))
return 1;
@@ -6641,11 +6598,9 @@ static void
build_store_vectors ()
{
basic_block bb;
- int b,i,j;
+ int b;
rtx insn, st;
struct ls_expr * ptr;
- sbitmap tested, *result;
- sbitmap used;
/* Build the gen_vector. This is any store in the table which is not killed
by aliasing later in its block. */
@@ -6654,16 +6609,7 @@ build_store_vectors ()
st_antloc = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
sbitmap_vector_zero (st_antloc, n_basic_blocks);
-
- /* Note: In case someone needs something to optimize about store
- motion, here's the next place to look. We currently test one more
- basic block per store than necessary (at least). Since we know, at
- the end of this for loop, whether a store was killed in one of the
- basic blocks (We know both whether it's killed before, and killed
- after, the insn in the bb it resides in. So unless the insn
- consists of multiple store/loads, we know whether it was killed
- in the entire bb), we could avoid testing it for kill and transp in
- the next for loop. */
+
for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
{
/* Put all the stores into either the antic list, or the avail list,
@@ -6675,7 +6621,8 @@ build_store_vectors ()
{
insn = XEXP (st, 0);
bb = BLOCK_FOR_INSN (insn);
- if (!store_killed_after (ptr->pattern, insn, bb, 1))
+
+ if (!store_killed_after (ptr->pattern, insn, bb))
{
/* If we've already seen an availale expression in this block,
we can delete the one we saw already (It occurs earlier in
@@ -6719,142 +6666,50 @@ build_store_vectors ()
ae_kill = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
sbitmap_vector_zero (ae_kill, n_basic_blocks);
-
transp = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
- sbitmap_vector_ones (transp, n_basic_blocks);
-
- tested = sbitmap_alloc (max_gcse_regno);
- sbitmap_zero (tested);
- result = sbitmap_vector_alloc (n_basic_blocks, max_gcse_regno);
- sbitmap_vector_zero (result, n_basic_blocks);
- used = sbitmap_alloc (max_gcse_regno);
- sbitmap_zero (used);
-
- /* This whole big nasty thing computes kill and transparent.
- It's done in this nasty way because profiling showed store motion
- taking twice as long as GCSE, with the cause being 1 million calls
- to store_ops_ok taking 30% of the entire runtime of the
- compiler.
- Since store most expressions use the same registers, there's no
- point in checking them 8 million times for the same basic blocks. If
- they weren't okay in a BB the last time we checked, they won't be
- okay now. Since we check all the bb's on each iteration, we don't
- need a vector for which registers we've tested, just the results.
- We then proceed to use the results of what store_ops_ok was for a
- given reg and bb, and if the results were a kill, we don't even need
- to check if the store was killed in the basic block, it'll be
- in the kill set because it's regs changed between here and there.
-
-
- If the whole store had no registers, we just skip store_ops_okay
- anyway (since it's checking reg operands), and proceed to see if
- it's okay in each bb, setting the approriate bits.
-
- With this in place, we now take almost no time at all to perform
- store motion. (It's not on the first page of the profile, it
- takes less than a second).
-
- */
+ sbitmap_vector_zero (transp, n_basic_blocks);
for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
+ for (b = 0; b < n_basic_blocks; b++)
{
- /* Make sure we don't have a load-only expr, which we never seem
- to, but i don't think there's actually a guarantee */
- if (ptr->stores != NULL)
+ if (store_killed_after (ptr->pattern, BLOCK_HEAD (b), BASIC_BLOCK (b)))
{
- /* First mark the regs used by the mem */
- mark_mem_regs (ptr->pattern, used);
- /* Now see if it had any regs */
- if (!(sbitmap_first_set_bit (used) == -1))
- {
- /* For each register, see if we've tested it */
- EXECUTE_IF_SET_IN_SBITMAP (used, 0, i,
- {
- if (TEST_BIT (tested, i))
- {
- /* Already tested the register, so check the
- result, and if we had an okay result, check the
- store itself. */
- for (j = 0; j < n_basic_blocks; j++)
- {
- if (!TEST_BIT (result[j], i)
- || store_killed_after (ptr->pattern, BLOCK_HEAD (j),
- BASIC_BLOCK (j), FALSE))
- {
- SET_BIT (ae_kill[j], ptr->index);
- if (!TEST_BIT (ae_gen[j], ptr->index)
- || !TEST_BIT (st_antloc[j], ptr->index))
- RESET_BIT (transp[j], ptr->index);
- }
- }
- }
- else
- {
- /* We haven't tested it yet, so mark it tested,
- and perform the tests */
- SET_BIT (tested, i);
- /* Check if it's okay in each BB */
- for (j = 0; j < n_basic_blocks; j++)
- {
- if (store_ops_ok (XEXP (ptr->pattern, 0),
- BASIC_BLOCK (j), BLOCK_HEAD (j), 0))
- {
- SET_BIT (result[j], ptr->index);
- }
- else
- {
- /* It's not okay, so it's killed and maybe
- not transparent */
- SET_BIT (ae_kill[j], ptr->index);
- if (!TEST_BIT (ae_gen[j], ptr->index)
- || !TEST_BIT (st_antloc[j], ptr->index))
- {
- RESET_BIT (transp[j], ptr->index);
- }
- continue;
- }
- /* The ops were okay, so check the store
- itself */
- if (store_killed_after (ptr->pattern, BLOCK_HEAD (j),
- BASIC_BLOCK (j), FALSE))
- {
- SET_BIT (ae_kill[j], ptr->index);
- if (!TEST_BIT (ae_gen[j], ptr->index)
- || !TEST_BIT (st_antloc[j], ptr->index))
- {
- RESET_BIT (transp[j], ptr->index);
- }
- }
- }
- }
- });
- /* Reset the used list */
- sbitmap_zero (used);
- }
- /* If it had no registers, we come here, and do the
- approriate testing */
- else
- {
- for (j = 0; j < n_basic_blocks; j++)
- {
- if (store_killed_after (ptr->pattern, BLOCK_HEAD (j),
- BASIC_BLOCK (j), FALSE))
- {
- SET_BIT (ae_kill[j], ptr->index);
- if (!TEST_BIT (ae_gen[j], ptr->index)
- || !TEST_BIT (st_antloc[j], ptr->index))
- {
- RESET_BIT (transp[j], ptr->index);
- }
- }
- }
- }
+ /* The anticipatable expression is not killed if it's gen'd. */
+ /*
+ We leave this check out for now. If we have a code sequence
+ in a block which looks like:
+ ST MEMa = x
+ L y = MEMa
+ ST MEMa = z
+ We should flag this as having an ANTIC expression, NOT
+ transparent, NOT killed, and AVAIL.
+ Unfortunately, since we haven't re-written all loads to
+ use the reaching reg, we'll end up doing an incorrect
+ Load in the middle here if we push the store down. It happens in
+ gcc.c-torture/execute/960311-1.c with -O3
+ If we always kill it in this case, we'll sometimes do
+ uneccessary work, but it shouldn't actually hurt anything.
+ if (!TEST_BIT (ae_gen[b], ptr->index)). */
+ SET_BIT (ae_kill[b], ptr->index);
+ }
+ else
+ SET_BIT (transp[b], ptr->index);
+ }
+
+ /* Any block with no exits calls some non-returning function, so
+ we better mark the store killed here, or we might not store to
+ it at all. If we knew it was abort, we wouldn't have to store,
+ but we don't know that for sure. */
+ if (gcse_file)
+ {
+ fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
+ print_ldst_list (gcse_file);
+ dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, n_basic_blocks);
+ dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, n_basic_blocks);
+ dump_sbitmap_vector (gcse_file, "Transpt", "", transp, n_basic_blocks);
+ dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, n_basic_blocks);
}
}
- sbitmap_free (tested);
- sbitmap_free (used);
- sbitmap_vector_free (result);
-}
/* Insert an instruction at the begining of a basic block, and update
the BLOCK_HEAD if needed. */
@@ -7033,6 +6888,7 @@ static void
free_store_memory ()
{
free_ldst_mems ();
+
if (ae_gen)
sbitmap_vector_free (ae_gen);
if (ae_kill)
@@ -7045,6 +6901,8 @@ free_store_memory ()
sbitmap_vector_free (pre_insert_map);
if (pre_delete_map)
sbitmap_vector_free (pre_delete_map);
+ if (reg_set_in_block)
+ sbitmap_vector_free (reg_set_in_block);
ae_gen = ae_kill = transp = st_antloc = NULL;
pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
@@ -7058,10 +6916,8 @@ store_motion ()
{
int x;
struct ls_expr * ptr;
- sbitmap trapping_expr;
- int i;
-
int update_flow = 0;
+
if (gcse_file)
{
fprintf (gcse_file, "before store motion\n");
@@ -7070,13 +6926,12 @@ store_motion ()
init_alias_analysis ();
- df_analyzer = df_init();
- df_analyse (df_analyzer, 0, DF_RD_CHAIN | DF_HARD_REGS);
+
/* Find all the stores that are live to the end of their block. */
num_stores = compute_store_table ();
if (num_stores == 0)
{
- df_finish (df_analyzer);
+ sbitmap_vector_free (reg_set_in_block);
end_alias_analysis ();
return;
}
@@ -7085,31 +6940,6 @@ store_motion ()
add_noreturn_fake_exit_edges ();
build_store_vectors ();
- /* Collect expressions which might trap. */
- trapping_expr = sbitmap_alloc (num_stores);
- sbitmap_zero (trapping_expr);
- for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr(ptr))
- {
- if (may_trap_p (ptr->pattern))
- SET_BIT (trapping_expr, ptr->index);
- }
- for (i = 0; i < n_basic_blocks; i++)
- {
- edge e;
-
- /* If the current block is the destination of an abnormal edge, we
- kill all trapping expressions because we won't be able to properly
- place the instruction on the edge. So make them neither
- anticipatable nor transparent. This is fairly conservative. */
- for (e = BASIC_BLOCK (i)->pred; e ; e = e->pred_next)
- if (e->flags & EDGE_ABNORMAL)
- {
- sbitmap_difference (st_antloc[i], st_antloc[i], trapping_expr);
- sbitmap_difference (transp[i], transp[i], trapping_expr);
- break;
- }
- }
-
edge_list = pre_edge_rev_lcm (gcse_file, num_stores, transp, ae_gen,
st_antloc, ae_kill, &pre_insert_map,
&pre_delete_map);
@@ -7128,10 +6958,9 @@ store_motion ()
if (update_flow)
commit_edge_insertions ();
- sbitmap_free (trapping_expr);
+
free_store_memory ();
free_edge_list (edge_list);
remove_fake_edges ();
end_alias_analysis ();
- df_finish (df_analyzer);
}