diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-10-07 10:08:16 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-10-07 10:08:16 +0000 |
commit | 170e5c6cad6fc8d9ce6974d4d2a25dfff66ec0b1 (patch) | |
tree | a34a4f033edaaa12f4f9be06f703587f12853c6e /gcc/gcse.c | |
parent | d37e5c1ea20dc7e2f217718f4cc6991cc6f92d78 (diff) | |
download | ppe42-gcc-170e5c6cad6fc8d9ce6974d4d2a25dfff66ec0b1.tar.gz ppe42-gcc-170e5c6cad6fc8d9ce6974d4d2a25dfff66ec0b1.zip |
* gcse.c (pre_insert_insn): When a call ends a bb, insert
the new insns before the argument regs are loaded.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22891 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gcse.c')
-rw-r--r-- | gcc/gcse.c | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/gcc/gcse.c b/gcc/gcse.c index a992d111ea1..463959d520a 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -4373,22 +4373,72 @@ pre_insert_insn (expr, bb) add_label_notes (SET_SRC (pat), new_insn); if (BLOCK_HEAD (bb) == insn) BLOCK_HEAD (bb) = new_insn; - /* Keep block number table up to date. */ - set_block_num (new_insn, bb); - /* Keep register set table up to date. */ - record_one_set (regno, new_insn); + } + /* Likewise if the last insn is a call, as will happen in the presence + of exception handling. */ + else if (GET_CODE (insn) == CALL_INSN) + { + HARD_REG_SET parm_regs; + int nparm_regs; + rtx p; + + /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers, + we search backward and place the instructions before the first + parameter is loaded. Do this for everyone for consistency and a + presumtion that we'll get better code elsewhere as well. */ + + /* It should always be the case that we can put these instructions + anywhere in the basic block. Check this. */ + if (!TEST_BIT (pre_antloc[bb], expr->bitmap_index) + && !TEST_BIT (pre_transp[bb], expr->bitmap_index)) + abort (); + + /* Since different machines initialize their parameter registers + in different orders, assume nothing. Collect the set of all + parameter registers. */ + CLEAR_HARD_REG_SET (parm_regs); + nparm_regs = 0; + for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1)) + if (GET_CODE (XEXP (p, 0)) == USE + && GET_CODE (XEXP (XEXP (p, 0), 0)) == REG) + { + int regno = REGNO (XEXP (XEXP (p, 0), 0)); + if (regno >= FIRST_PSEUDO_REGISTER) + abort(); + SET_HARD_REG_BIT (parm_regs, regno); + nparm_regs++; + } + + /* Search backward for the first set of a register in this set. */ + while (nparm_regs && BLOCK_HEAD (bb) != insn) + { + insn = PREV_INSN (insn); + p = single_set (insn); + if (p && GET_CODE (SET_DEST (p)) == REG + && REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER + && TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)))) + { + CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))); + nparm_regs--; + } + } + + new_insn = emit_insn_before (pat, insn); + if (BLOCK_HEAD (bb) == insn) + BLOCK_HEAD (bb) = new_insn; } else { new_insn = emit_insn_after (pat, insn); add_label_notes (SET_SRC (pat), new_insn); BLOCK_END (bb) = new_insn; - /* Keep block number table up to date. */ - set_block_num (new_insn, bb); - /* Keep register set table up to date. */ - record_one_set (regno, new_insn); } + /* Keep block number table up to date. */ + set_block_num (new_insn, bb); + /* Keep register set table up to date. */ + record_one_set (regno, new_insn); + gcse_create_count++; if (gcse_file) |