diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-26 18:23:33 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-26 18:23:33 +0000 |
commit | 53ee16e4a8273d7fd600c9004ff1a1a0cca47c2e (patch) | |
tree | 5040023f54434be9483c111c7a2cbc52d48270c4 /gcc/gcse.c | |
parent | a3cab1c2d25bf116f5931d5babbf9b554b168a6e (diff) | |
download | gcc-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.c | 70 |
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. */ |