diff options
author | Roger Sayle <sayle@gcc.gnu.org> | 2003-09-26 18:23:33 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-09-26 18:23:33 +0000 |
commit | 073089a7e016eaee614755fc4d54e74007de779b (patch) | |
tree | 5040023f54434be9483c111c7a2cbc52d48270c4 /gcc/gcse.c | |
parent | 43ab026f2a019405f7e5af2a35ac41467dc35111 (diff) | |
download | gcc-073089a7e016eaee614755fc4d54e74007de779b.zip gcc-073089a7e016eaee614755fc4d54e74007de779b.tar.gz gcc-073089a7e016eaee614755fc4d54e74007de779b.tar.bz2 |
re PR rtl-optimization/11741 (internal compiler error at gcse.c:5318)
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.
From-SVN: r71827
Diffstat (limited to 'gcc/gcse.c')
-rw-r--r-- | gcc/gcse.c | 70 |
1 files changed, 48 insertions, 22 deletions
@@ -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. */ |