summaryrefslogtreecommitdiff
path: root/gcc/regmove.c
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-11 11:51:52 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-11 11:51:52 +0000
commit403003d78ce688323cd90811366ae7d4621cdbb0 (patch)
tree614f48702fe3b1201670055c1fd940453de3416c /gcc/regmove.c
parentdf037ff5b0207f0f0e1365cc5867b822725cfb89 (diff)
downloadgcc-403003d78ce688323cd90811366ae7d4621cdbb0.tar.gz
For regmove if we could not improve code by changing the source to the destination, copy the source to the destination directly
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20427 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/regmove.c')
-rw-r--r--gcc/regmove.c164
1 files changed, 152 insertions, 12 deletions
diff --git a/gcc/regmove.c b/gcc/regmove.c
index ee56db596c7..43116268ccd 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,98 @@ 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;
+
+ if (GET_CODE (src) == REG && GET_CODE (dest) == REG
+ && (set = single_set (insn)) != NULL_RTX
+ && !reg_mentioned_p (dest, SET_SRC (set))
+ && 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 = &REG_NOTES (move_insn);
+ p_insn_notes = &REG_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 +845,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 +1037,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 +1048,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 +1119,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 +1307,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 */