summaryrefslogtreecommitdiff
path: root/gcc/gcse.c
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-26 18:23:33 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-26 18:23:33 +0000
commit53ee16e4a8273d7fd600c9004ff1a1a0cca47c2e (patch)
tree5040023f54434be9483c111c7a2cbc52d48270c4 /gcc/gcse.c
parenta3cab1c2d25bf116f5931d5babbf9b554b168a6e (diff)
downloadgcc-53ee16e4a8273d7fd600c9004ff1a1a0cca47c2e.tar.gz
PR optimization/11741
* gcse.c (pre_insert_copy_insn): Tweak the logic for finding the appropriate set to match that in hash_scan_insn. Fall back to the original copy method, if we can't validate changing insn. (pre_delete): Only delete instructions that have a single_set, instead of aborting when we encounter an PARALLEL insn with more then one SET. * gcc.dg/20030926-1.c: New test case. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71827 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gcse.c')
-rw-r--r--gcc/gcse.c70
1 files changed, 48 insertions, 22 deletions
diff --git a/gcc/gcse.c b/gcc/gcse.c
index f50c2d9a01e..8e78e5b08e6 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -5353,14 +5353,14 @@ pre_edge_insert (struct edge_list *edge_list, struct expr **index_map)
return did_insert;
}
-/* Copy the result of INSN to REG. INDX is the expression number.
+/* Copy the result of EXPR->EXPR generated by INSN to EXPR->REACHING_REG.
Given "old_reg <- expr" (INSN), instead of adding after it
reaching_reg <- old_reg
it's better to do the following:
reaching_reg <- expr
old_reg <- reaching_reg
because this way copy propagation can discover additional PRE
- opportunuties. */
+ opportunuties. But if this fails, we try the old way. */
static void
pre_insert_copy_insn (struct expr *expr, rtx insn)
@@ -5368,27 +5368,53 @@ pre_insert_copy_insn (struct expr *expr, rtx insn)
rtx reg = expr->reaching_reg;
int regno = REGNO (reg);
int indx = expr->bitmap_index;
- rtx set = single_set (insn);
- rtx new_insn;
- rtx new_set;
+ rtx pat = PATTERN (insn);
+ rtx set, new_insn;
rtx old_reg;
+ int i;
- if (!set)
+ /* This block matches the logic in hash_scan_insn. */
+ if (GET_CODE (pat) == SET)
+ set = pat;
+ else if (GET_CODE (pat) == PARALLEL)
+ {
+ /* Search through the parallel looking for the set whose
+ source was the expression that we're interested in. */
+ set = NULL_RTX;
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx x = XVECEXP (pat, 0, i);
+ if (GET_CODE (x) == SET
+ && expr_equiv_p (SET_SRC (x), expr->expr))
+ {
+ set = x;
+ break;
+ }
+ }
+ }
+ else
abort ();
old_reg = SET_DEST (set);
- new_insn = emit_insn_after (gen_move_insn (old_reg,
- reg),
- insn);
- new_set = single_set (new_insn);
- if (!new_set)
- abort();
- SET_DEST (set) = reg;
+ /* Check if we can modify the set destination in the original insn. */
+ if (validate_change (insn, &SET_DEST (set), reg, 0))
+ {
+ new_insn = gen_move_insn (old_reg, reg);
+ new_insn = emit_insn_after (new_insn, insn);
+
+ /* Keep register set table up to date. */
+ replace_one_set (REGNO (old_reg), insn, new_insn);
+ record_one_set (regno, insn);
+ }
+ else
+ {
+ new_insn = gen_move_insn (reg, old_reg);
+ new_insn = emit_insn_after (new_insn, insn);
- /* Keep register set table up to date. */
- replace_one_set (REGNO (old_reg), insn, new_insn);
- record_one_set (regno, insn);
+ /* Keep register set table up to date. */
+ record_one_set (regno, new_insn);
+ }
gcse_create_count++;
@@ -5505,7 +5531,9 @@ pre_delete (void)
changed = 0;
for (i = 0; i < expr_hash_table.size; i++)
- for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
+ for (expr = expr_hash_table.table[i];
+ expr != NULL;
+ expr = expr->next_same_hash)
{
int indx = expr->bitmap_index;
@@ -5518,12 +5546,10 @@ pre_delete (void)
rtx set;
basic_block bb = BLOCK_FOR_INSN (insn);
- if (TEST_BIT (pre_delete_map[bb->index], indx))
+ /* We only delete insns that have a single_set. */
+ if (TEST_BIT (pre_delete_map[bb->index], indx)
+ && (set = single_set (insn)) != 0)
{
- set = single_set (insn);
- if (! set)
- abort ();
-
/* Create a pseudo-reg to store the result of reaching
expressions into. Get the mode for the new pseudo from
the mode of the original destination pseudo. */