From 2f08c02a55d38823e2a186da437c48807aa56553 Mon Sep 17 00:00:00 2001 From: meissner Date: Mon, 15 Jun 1998 14:28:02 +0000 Subject: [PATCH] Do not do src->dest copy if register would not be allocated a normal register git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20512 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 ++-- gcc/regmove.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 165 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index adf9960e6a8..784542853b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,10 +1,12 @@ -Mon Jun 15 13:20:33 1998 Jim Wilson +Mon Jun 15 17:06:43 1998 Michael Meissner + Jim Wilson - * c-decl.c (shadow_tag_warned): Use specs not declspecs in for loop. + * regmove.c (copy_src_to_dest): Do not copy src to dest if either + the source or destination is special. -Mon Jun 15 15:33:45 1998 Michael Meissner +Mon Jun 15 13:20:33 1998 Jim Wilson - * regmove.c: Undo June 11th change for now. + * c-decl.c (shadow_tag_warned): Use specs not declspecs in for loop. Mon Jun 15 07:16:29 PDT 1998 Jeff Law (law@cygnus.com) diff --git a/gcc/regmove.c b/gcc/regmove.c index ee56db596c7..f932da8417d 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -43,11 +43,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "flags.h" #include "expr.h" #include "insn-flags.h" +#include "basic-block.h" static int optimize_reg_copy_1 PROTO((rtx, rtx, rtx)); static void optimize_reg_copy_2 PROTO((rtx, rtx, rtx)); static void optimize_reg_copy_3 PROTO((rtx, rtx, rtx)); static rtx gen_add3_insn PROTO((rtx, rtx, rtx)); +static void copy_src_to_dest PROTO((rtx, rtx, rtx, int)); +static int *regmove_bb_head; struct match { int with[MAX_RECOG_OPERANDS]; @@ -528,6 +531,105 @@ optimize_reg_copy_3 (insn, dest, src) validate_replace_rtx (src, src_reg, insn); } + +/* If we were not able to update the users of src to use dest directly, try + instead moving the value to dest directly before the operation. */ + +void +copy_src_to_dest (insn, src, dest, loop_depth) + rtx insn; + rtx src; + rtx dest; +{ + rtx seq; + rtx link; + rtx next; + rtx set; + rtx move_insn; + rtx *p_insn_notes; + rtx *p_move_notes; + int i; + int src_regno; + int dest_regno; + int bb; + int insn_uid; + int move_uid; + + /* A REG_LIVE_LENGTH of -1 indicates the register is equivalent to a constant + or memory location and is used infrequently; a REG_LIVE_LENGTH of -2 is + parameter when there is no frame pointer that is not allocated a register. + For now, we just reject them, rather than incrementing the live length. */ + + if (GET_CODE (src) == REG && GET_CODE (dest) == REG + && (set = single_set (insn)) != NULL_RTX + && !reg_mentioned_p (dest, SET_SRC (set)) + && REG_LIVE_LENGTH (REGNO (dest)) > 0 + && REG_LIVE_LENGTH (REGNO (src)) > 0 + && validate_replace_rtx (src, dest, insn)) + { + /* Generate the src->dest move. */ + start_sequence (); + emit_move_insn (dest, src); + seq = gen_sequence (); + end_sequence (); + emit_insn_before (seq, insn); + move_insn = PREV_INSN (insn); + p_move_notes = ®_NOTES (move_insn); + p_insn_notes = ®_NOTES (insn); + + /* Move any notes mentioning src to the move instruction */ + for (link = REG_NOTES (insn); link != NULL_RTX; link = next) + { + next = XEXP (link, 1); + if (XEXP (link, 0) == src) + { + *p_move_notes = link; + p_move_notes = &XEXP (link, 1); + } + else + { + *p_insn_notes = link; + p_insn_notes = &XEXP (link, 1); + } + } + + *p_move_notes = NULL_RTX; + *p_insn_notes = NULL_RTX; + + /* Is the insn the head of a basic block? If so extend it */ + insn_uid = INSN_UID (insn); + move_uid = INSN_UID (move_insn); + bb = regmove_bb_head[insn_uid]; + if (bb >= 0) + { + basic_block_head[bb] = move_insn; + regmove_bb_head[insn_uid] = -1; + } + + /* Update the various register tables. */ + dest_regno = REGNO (dest); + REG_N_SETS (dest_regno) += loop_depth; + REG_N_REFS (dest_regno) += loop_depth; + REG_LIVE_LENGTH (dest_regno)++; + if (REGNO_FIRST_UID (dest_regno) == insn_uid) + REGNO_FIRST_UID (dest_regno) = move_uid; + + src_regno = REGNO (src); + if (! find_reg_note (move_insn, REG_DEAD, src)) + REG_LIVE_LENGTH (src_regno)++; + + if (REGNO_FIRST_UID (src_regno) == insn_uid) + REGNO_FIRST_UID (src_regno) = move_uid; + + if (REGNO_LAST_UID (src_regno) == insn_uid) + REGNO_LAST_UID (src_regno) = move_uid; + + if (REGNO_LAST_NOTE_UID (src_regno) == insn_uid) + REGNO_LAST_NOTE_UID (src_regno) = move_uid; + } +} + + /* Return whether REG is set in only one location, and is set to a constant, but is set in a different basic block from INSN (an instructions which uses REG). In this case REG is equivalent to a @@ -750,10 +852,16 @@ regmove_optimize (f, nregs, regmove_dump_file) struct match match; int pass; int maxregnum = max_reg_num (), i; + rtx copy_src, copy_dst; regno_src_regno = (int *)alloca (sizeof *regno_src_regno * maxregnum); for (i = maxregnum; --i >= 0; ) regno_src_regno[i] = -1; + regmove_bb_head = (int *)alloca (sizeof (int) * (get_max_uid () + 1)); + for (i = get_max_uid (); --i >= 0; ) regmove_bb_head[i] = -1; + for (i = 0; i < n_basic_blocks; i++) + regmove_bb_head[INSN_UID (basic_block_head[i])] = i; + /* A forward/backward pass. Replace output operands with input operands. */ loop_depth = 1; @@ -936,6 +1044,7 @@ regmove_optimize (f, nregs, regmove_dump_file) { int insn_code_number = find_matches (insn, &match); int operand_number, match_number; + int success = 0; if (insn_code_number < 0) continue; @@ -946,13 +1055,14 @@ regmove_optimize (f, nregs, regmove_dump_file) operand. If safe, then replace the source operand with the dest operand in both instructions. */ + copy_src = NULL_RTX; + copy_dst = NULL_RTX; for (operand_number = 0; operand_number < insn_n_operands[insn_code_number]; operand_number++) { rtx set, p, src, dst; rtx src_note, dst_note; - int success = 0; int num_calls = 0; enum reg_class src_class, dst_class; int length; @@ -1016,27 +1126,58 @@ regmove_optimize (f, nregs, regmove_dump_file) || CLASS_LIKELY_SPILLED_P (src_class)) && (! reg_class_subset_p (dst_class, src_class) || CLASS_LIKELY_SPILLED_P (dst_class))) - continue; - - if (! (src_note = find_reg_note (insn, REG_DEAD, src))) - continue; + { + if (!copy_src) + { + copy_src = src; + copy_dst = dst; + } + continue; + } /* Can not modify an earlier insn to set dst if this insn uses an old value in the source. */ if (reg_overlap_mentioned_p (dst, SET_SRC (set))) - continue; + { + if (!copy_src) + { + copy_src = src; + copy_dst = dst; + } + continue; + } + + if (! (src_note = find_reg_note (insn, REG_DEAD, src))) + { + if (!copy_src) + { + copy_src = src; + copy_dst = dst; + } + continue; + } - if (regmove_dump_file) - fprintf (regmove_dump_file, - "Could fix operand %d of insn %d matching operand %d.\n", - operand_number, INSN_UID (insn), match_number); /* If src is set once in a different basic block, and is set equal to a constant, then do not use it for this optimization, as this would make it no longer equivalent to a constant. */ - if (reg_is_remote_constant_p (src, insn, f)) - continue; + + if (reg_is_remote_constant_p (src, insn, f)) + { + if (!copy_src) + { + copy_src = src; + copy_dst = dst; + } + continue; + } + + + if (regmove_dump_file) + fprintf (regmove_dump_file, + "Could fix operand %d of insn %d matching operand %d.\n", + operand_number, INSN_UID (insn), match_number); /* Scan backward to find the first instruction that uses the input operand. If the operand is set here, then @@ -1173,6 +1314,12 @@ regmove_optimize (f, nregs, regmove_dump_file) break; } } + + /* If we weren't able to replace any of the alternatives, try an + alternative appoach of copying the source to the destination. */ + if (!success && copy_src != NULL_RTX) + copy_src_to_dest (insn, copy_src, copy_dst, loop_depth); + } } #endif /* REGISTER_CONSTRAINTS */ -- 2.11.4.GIT