Commit 172890a2 by Richard Kenner Committed by Richard Kenner

gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV.

	* gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV.
	Don't CSE a nop.
	(hash_scan_insn): Clean up calls to hash_scan_set.
	(compute_kill_rd): REGNO now unsigned.
	(try_replace_reg): Rework to use simplify_replace_rtx.
	(cprop_jump, cprop_cc0_jump): Likewise.
	(cprop_insn): Call find_reg_equal_equiv_note.
	Reflect changes to cprop_jump and cprop_cc0_jump.

From-SVN: r39774
parent b71e8e84
...@@ -8,6 +8,15 @@ ...@@ -8,6 +8,15 @@
Fri Feb 16 12:41:30 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> Fri Feb 16 12:41:30 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV.
Don't CSE a nop.
(hash_scan_insn): Clean up calls to hash_scan_set.
(compute_kill_rd): REGNO now unsigned.
(try_replace_reg): Rework to use simplify_replace_rtx.
(cprop_jump, cprop_cc0_jump): Likewise.
(cprop_insn): Call find_reg_equal_equiv_note.
Reflect changes to cprop_jump and cprop_cc0_jump.
* recog.c (validate_replace_rtx): Replace in operands of * recog.c (validate_replace_rtx): Replace in operands of
ZERO_EXTRACT in SET_DEST. ZERO_EXTRACT in SET_DEST.
......
...@@ -583,7 +583,7 @@ static void compute_cprop_data PARAMS ((void)); ...@@ -583,7 +583,7 @@ static void compute_cprop_data PARAMS ((void));
static void find_used_regs PARAMS ((rtx)); static void find_used_regs PARAMS ((rtx));
static int try_replace_reg PARAMS ((rtx, rtx, rtx)); static int try_replace_reg PARAMS ((rtx, rtx, rtx));
static struct expr *find_avail_set PARAMS ((int, rtx)); static struct expr *find_avail_set PARAMS ((int, rtx));
static int cprop_jump PARAMS ((rtx, rtx, struct reg_use *, rtx)); static int cprop_jump PARAMS ((rtx, rtx, rtx));
#ifdef HAVE_cc0 #ifdef HAVE_cc0
static int cprop_cc0_jump PARAMS ((rtx, struct reg_use *, rtx)); static int cprop_cc0_jump PARAMS ((rtx, struct reg_use *, rtx));
#endif #endif
...@@ -1114,7 +1114,7 @@ record_one_set (regno, insn) ...@@ -1114,7 +1114,7 @@ record_one_set (regno, insn)
int regno; int regno;
rtx insn; rtx insn;
{ {
/* allocate a new reg_set element and link it onto the list */ /* Allocate a new reg_set element and link it onto the list. */
struct reg_set *new_reg_info; struct reg_set *new_reg_info;
/* If the table isn't big enough, enlarge it. */ /* If the table isn't big enough, enlarge it. */
...@@ -1334,7 +1334,9 @@ hash_expr (x, mode, do_not_record_p, hash_table_size) ...@@ -1334,7 +1334,9 @@ hash_expr (x, mode, do_not_record_p, hash_table_size)
hash = hash_expr_1 (x, mode, do_not_record_p); hash = hash_expr_1 (x, mode, do_not_record_p);
return hash % hash_table_size; return hash % hash_table_size;
} }
/* Hash a string. Just add its bytes up. */ /* Hash a string. Just add its bytes up. */
static inline unsigned static inline unsigned
hash_string_1 (ps) hash_string_1 (ps)
const char *ps; const char *ps;
...@@ -1857,7 +1859,6 @@ insert_set_in_table (x, insn) ...@@ -1857,7 +1859,6 @@ insert_set_in_table (x, insn)
/* Set the fields of the expr element. /* Set the fields of the expr element.
We must copy X because it can be modified when copy propagation is We must copy X because it can be modified when copy propagation is
performed on its operands. */ performed on its operands. */
/* ??? Should this go in a different obstack? */
cur_expr->expr = copy_rtx (x); cur_expr->expr = copy_rtx (x);
cur_expr->bitmap_index = n_sets++; cur_expr->bitmap_index = n_sets++;
cur_expr->next_same_hash = NULL; cur_expr->next_same_hash = NULL;
...@@ -1910,22 +1911,31 @@ hash_scan_set (pat, insn, set_p) ...@@ -1910,22 +1911,31 @@ hash_scan_set (pat, insn, set_p)
{ {
rtx src = SET_SRC (pat); rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat); rtx dest = SET_DEST (pat);
rtx note;
if (GET_CODE (src) == CALL) if (GET_CODE (src) == CALL)
hash_scan_call (src, insn); hash_scan_call (src, insn);
if (GET_CODE (dest) == REG) else if (GET_CODE (dest) == REG)
{ {
int regno = REGNO (dest); unsigned int regno = REGNO (dest);
rtx tmp; rtx tmp;
/* If this is a single set and we are doing constant propagation,
see if a REG_NOTE shows this equivalent to a constant. */
if (set_p && (note = find_reg_equal_equiv_note (insn)) != 0
&& CONSTANT_P (XEXP (note, 0)))
src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
/* Only record sets of pseudo-regs in the hash table. */ /* Only record sets of pseudo-regs in the hash table. */
if (! set_p if (! set_p
&& regno >= FIRST_PSEUDO_REGISTER && regno >= FIRST_PSEUDO_REGISTER
/* Don't GCSE something if we can't do a reg/reg copy. */ /* Don't GCSE something if we can't do a reg/reg copy. */
&& can_copy_p [GET_MODE (dest)] && can_copy_p [GET_MODE (dest)]
/* Is SET_SRC something we want to gcse? */ /* Is SET_SRC something we want to gcse? */
&& want_to_gcse_p (src)) && want_to_gcse_p (src)
/* Don't CSE a nop. */
&& src != dest)
{ {
/* An expression is not anticipatable if its operands are /* An expression is not anticipatable if its operands are
modified before this insn. */ modified before this insn. */
...@@ -1942,7 +1952,8 @@ hash_scan_set (pat, insn, set_p) ...@@ -1942,7 +1952,8 @@ hash_scan_set (pat, insn, set_p)
&& regno >= FIRST_PSEUDO_REGISTER && regno >= FIRST_PSEUDO_REGISTER
&& ((GET_CODE (src) == REG && ((GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER && REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)]) && can_copy_p [GET_MODE (dest)]
&& REGNO (src) != regno)
|| GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_INT
|| GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == SYMBOL_REF
|| GET_CODE (src) == CONST_DOUBLE) || GET_CODE (src) == CONST_DOUBLE)
...@@ -1992,25 +2003,21 @@ hash_scan_insn (insn, set_p, in_libcall_block) ...@@ -1992,25 +2003,21 @@ hash_scan_insn (insn, set_p, in_libcall_block)
rtx pat = PATTERN (insn); rtx pat = PATTERN (insn);
int i; int i;
if (in_libcall_block)
return;
/* Pick out the sets of INSN and for other forms of instructions record /* Pick out the sets of INSN and for other forms of instructions record
what's been modified. */ what's been modified. */
if (GET_CODE (pat) == SET && ! in_libcall_block) if (GET_CODE (pat) == SET)
{
/* Ignore obvious no-ops. */
if (SET_SRC (pat) != SET_DEST (pat))
hash_scan_set (pat, insn, set_p); hash_scan_set (pat, insn, set_p);
}
else if (GET_CODE (pat) == PARALLEL) else if (GET_CODE (pat) == PARALLEL)
for (i = 0; i < XVECLEN (pat, 0); i++) for (i = 0; i < XVECLEN (pat, 0); i++)
{ {
rtx x = XVECEXP (pat, 0, i); rtx x = XVECEXP (pat, 0, i);
if (GET_CODE (x) == SET) if (GET_CODE (x) == SET)
{ hash_scan_set (x, insn, set_p);
if (GET_CODE (SET_SRC (x)) == CALL)
hash_scan_call (SET_SRC (x), insn);
}
else if (GET_CODE (x) == CLOBBER) else if (GET_CODE (x) == CLOBBER)
hash_scan_clobber (x, insn); hash_scan_clobber (x, insn);
else if (GET_CODE (x) == CALL) else if (GET_CODE (x) == CALL)
...@@ -2611,7 +2618,8 @@ static void ...@@ -2611,7 +2618,8 @@ static void
compute_kill_rd () compute_kill_rd ()
{ {
int bb, cuid; int bb, cuid;
int regno, i; unsigned int regno;
int i;
/* For each block /* For each block
For each set bit in `gen' of the block (i.e each insn which For each set bit in `gen' of the block (i.e each insn which
...@@ -3603,63 +3611,53 @@ static int ...@@ -3603,63 +3611,53 @@ static int
try_replace_reg (from, to, insn) try_replace_reg (from, to, insn)
rtx from, to, insn; rtx from, to, insn;
{ {
rtx note; rtx note = find_reg_equal_equiv_note (insn);
rtx src; rtx src;
int success; int success = 0;
rtx set; rtx set = single_set (insn);
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
if (!note)
note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
/* If this fails we could try to simplify the result of the
replacement and attempt to recognize the simplified insn.
But we need a general simplify_rtx that doesn't have pass
specific state variables. I'm not aware of one at the moment. */
success = validate_replace_src (from, to, insn);
set = single_set (insn);
/* We've failed to do replacement. Try to add REG_EQUAL note to not loose /* If this is a single set, try to simplify the source of the set given
information. */ our substitution. We could perhaps try this for multiple SETs, but
if (!success && !note) it probably won't buy us anything. */
if (set != 0)
{ {
if (!set) src = simplify_replace_rtx (SET_SRC (set), from, to);
return 0;
note = REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, /* Try this two ways: first just replace SET_SRC. If that doesn't
copy_rtx (SET_SRC (set)), work and this is a PARALLEL, try to replace the whole pattern
REG_NOTES (insn)); with a new SET. */
if (validate_change (insn, &SET_SRC (set), src, 0))
success = 1;
else if (GET_CODE (PATTERN (insn)) == PARALLEL
&& validate_change (insn, &PATTERN (insn),
gen_rtx_SET (VOIDmode, SET_DEST (set),
src),
0))
success = 1;
} }
/* Always do the replacement in REQ_EQUAL and REG_EQUIV notes. Also /* Otherwise, try to do a global replacement within the insn. */
try to simplify them. */ if (!success)
if (note) success = validate_replace_src (from, to, insn);
{
rtx simplified;
if (!validate_replace_rtx_subexp (from, to, insn, &XEXP (note, 0)))
abort();
src = XEXP (note, 0); /* We've failed to do replacement, have a single SET, and don't already
have a note, two to add a REG_EQUAL note to not lose information. */
if (!success && note == 0 && set != 0)
note= REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
/* Try to simplify resulting note. */ /* If there is already a NOTE, update the expression in it with our
simplified = simplify_rtx (src); replacement. */
if (simplified) else if (note != 0)
{ XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to);
src = simplified;
XEXP (note, 0) = src;
}
/* REG_EQUAL may get simplified into register. /* REG_EQUAL may get simplified into register.
We don't allow that. Remove that note. This code ought We don't allow that. Remove that note. This code ought
not to hapen, because previous code ought to syntetize not to hapen, because previous code ought to syntetize
reg-reg move, but be on the safe side. */ reg-reg move, but be on the safe side. */
else if (REG_P (src)) if (note && REG_P (XEXP (note, 0)))
remove_note (insn, note); remove_note (insn, note);
}
return success; return success;
} }
...@@ -3734,60 +3732,37 @@ find_avail_set (regno, insn) ...@@ -3734,60 +3732,37 @@ find_avail_set (regno, insn)
} }
/* Subroutine of cprop_insn that tries to propagate constants into /* Subroutine of cprop_insn that tries to propagate constants into
JUMP_INSNS. INSN must be a conditional jump; COPY is a copy of it JUMP_INSNS. INSN must be a conditional jump. FROM is what we will try to
that we can use for substitutions. replace, SRC is the constant we will try to substitute for it. Returns
REG_USED is the use we will try to replace, SRC is the constant we nonzero if a change was made. We know INSN has just a SET. */
will try to substitute for it.
Returns nonzero if a change was made. */
static int static int
cprop_jump (insn, copy, reg_used, src) cprop_jump (insn, from, src)
rtx insn, copy; rtx insn;
struct reg_use *reg_used; rtx from;
rtx src; rtx src;
{ {
rtx set = PATTERN (copy); rtx set = PATTERN (insn);
rtx temp; rtx new = simplify_replace_rtx (SET_SRC (set), from, src);
/* Replace the register with the appropriate constant. */
replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
GET_MODE (SET_SRC (set)),
GET_MODE (XEXP (SET_SRC (set), 0)),
XEXP (SET_SRC (set), 0),
XEXP (SET_SRC (set), 1),
XEXP (SET_SRC (set), 2));
/* If no simplification can be made, then try the next /* If no simplification can be made, then try the next
register. */ register. */
if (temp == 0) if (rtx_equal_p (new, SET_SRC (set)))
return 0; return 0;
SET_SRC (set) = temp; /* If this is now a no-op leave it that way, but update LABEL_NUSED if
necessary. */
/* That may have changed the structure of TEMP, so if (new == pc_rtx)
force it to be rerecognized if it has not turned {
into a nop or unconditional jump. */ SET_SRC (set) = new;
INSN_CODE (copy) = -1; if (JUMP_LABEL (insn) != 0)
if ((SET_DEST (set) == pc_rtx
&& (SET_SRC (set) == pc_rtx
|| GET_CODE (SET_SRC (set)) == LABEL_REF))
|| recog (PATTERN (copy), copy, NULL) >= 0)
{
/* This has either become an unconditional jump
or a nop-jump. We'd like to delete nop jumps
here, but doing so confuses gcse. So we just
make the replacement and let later passes
sort things out. */
PATTERN (insn) = set;
INSN_CODE (insn) = -1;
/* One less use of the label this insn used to jump to
if we turned this into a NOP jump. */
if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
--LABEL_NUSES (JUMP_LABEL (insn)); --LABEL_NUSES (JUMP_LABEL (insn));
}
/* Otherwise, this must be a valid instruction. */
else if (! validate_change (insn, &SET_SRC (set), new, 0))
return 0;
/* If this has turned into an unconditional jump, /* If this has turned into an unconditional jump,
then put a barrier after it so that the unreachable then put a barrier after it so that the unreachable
...@@ -3802,14 +3777,12 @@ cprop_jump (insn, copy, reg_used, src) ...@@ -3802,14 +3777,12 @@ cprop_jump (insn, copy, reg_used, src)
{ {
fprintf (gcse_file, fprintf (gcse_file,
"CONST-PROP: Replacing reg %d in insn %d with constant ", "CONST-PROP: Replacing reg %d in insn %d with constant ",
REGNO (reg_used->reg_rtx), INSN_UID (insn)); REGNO (from), INSN_UID (insn));
print_rtl (gcse_file, src); print_rtl (gcse_file, src);
fprintf (gcse_file, "\n"); fprintf (gcse_file, "\n");
} }
return 1; return 1;
}
return 0;
} }
#ifdef HAVE_cc0 #ifdef HAVE_cc0
...@@ -3826,20 +3799,20 @@ cprop_cc0_jump (insn, reg_used, src) ...@@ -3826,20 +3799,20 @@ cprop_cc0_jump (insn, reg_used, src)
struct reg_use *reg_used; struct reg_use *reg_used;
rtx src; rtx src;
{ {
/* First substitute in the SET_SRC of INSN, then substitute that for
CC0 in JUMP. */
rtx jump = NEXT_INSN (insn); rtx jump = NEXT_INSN (insn);
rtx copy = copy_rtx (jump); rtx new_src = simplify_replace_rtx (SET_SRC (PATTERN (insn)),
rtx set = PATTERN (copy); reg_used->reg_rtx, src);
/* We need to copy the source of the cc0 setter, as cprop_jump is going to if (! cprop_jump (jump, cc0_rtx, new_src))
substitute into it. */
replace_rtx (SET_SRC (set), cc0_rtx, copy_rtx (SET_SRC (PATTERN (insn))));
if (! cprop_jump (jump, copy, reg_used, src))
return 0; return 0;
/* If we succeeded, delete the cc0 setter. */ /* If we succeeded, delete the cc0 setter. */
PUT_CODE (insn, NOTE); PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0; NOTE_SOURCE_FILE (insn) = 0;
return 1; return 1;
} }
#endif #endif
...@@ -3858,17 +3831,13 @@ cprop_insn (insn, alter_jumps) ...@@ -3858,17 +3831,13 @@ cprop_insn (insn, alter_jumps)
/* Only propagate into SETs. Note that a conditional jump is a /* Only propagate into SETs. Note that a conditional jump is a
SET with pc_rtx as the destination. */ SET with pc_rtx as the destination. */
if ((GET_CODE (insn) != INSN if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
&& GET_CODE (insn) != JUMP_INSN)
|| GET_CODE (PATTERN (insn)) != SET)
return 0; return 0;
reg_use_count = 0; reg_use_count = 0;
find_used_regs (PATTERN (insn)); find_used_regs (PATTERN (insn));
note = find_reg_note (insn, REG_EQUIV, NULL_RTX); note = find_reg_equal_equiv_note (insn);
if (!note)
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
/* We may win even when propagating constants into notes. */ /* We may win even when propagating constants into notes. */
if (note) if (note)
...@@ -3938,7 +3907,8 @@ cprop_insn (insn, alter_jumps) ...@@ -3938,7 +3907,8 @@ cprop_insn (insn, alter_jumps)
&& GET_CODE (insn) == JUMP_INSN && GET_CODE (insn) == JUMP_INSN
&& condjump_p (insn) && condjump_p (insn)
&& ! simplejump_p (insn)) && ! simplejump_p (insn))
changed |= cprop_jump (insn, copy_rtx (insn), reg_used, src); changed |= cprop_jump (insn, reg_used->reg_rtx, src);
#ifdef HAVE_cc0 #ifdef HAVE_cc0
/* Similar code for machines that use a pair of CC0 setter and /* Similar code for machines that use a pair of CC0 setter and
conditional jump insn. */ conditional jump insn. */
...@@ -3947,14 +3917,12 @@ cprop_insn (insn, alter_jumps) ...@@ -3947,14 +3917,12 @@ cprop_insn (insn, alter_jumps)
&& SET_DEST (PATTERN (insn)) == cc0_rtx && SET_DEST (PATTERN (insn)) == cc0_rtx
&& GET_CODE (NEXT_INSN (insn)) == JUMP_INSN && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
&& condjump_p (NEXT_INSN (insn)) && condjump_p (NEXT_INSN (insn))
&& ! simplejump_p (NEXT_INSN (insn))) && ! simplejump_p (NEXT_INSN (insn))
{ && cprop_cc0_jump (insn, reg_used, src))
if (cprop_cc0_jump (insn, reg_used, src))
{ {
changed = 1; changed = 1;
break; break;
} }
}
#endif #endif
} }
else if (GET_CODE (src) == REG else if (GET_CODE (src) == REG
...@@ -4006,7 +3974,6 @@ cprop (alter_jumps) ...@@ -4006,7 +3974,6 @@ cprop (alter_jumps)
for (insn = BLOCK_HEAD (bb); for (insn = BLOCK_HEAD (bb);
insn != NULL && insn != NEXT_INSN (BLOCK_END (bb)); insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
{
if (INSN_P (insn)) if (INSN_P (insn))
{ {
changed |= cprop_insn (insn, alter_jumps); changed |= cprop_insn (insn, alter_jumps);
...@@ -4018,7 +3985,6 @@ cprop (alter_jumps) ...@@ -4018,7 +3985,6 @@ cprop (alter_jumps)
mark_oprs_set (insn); mark_oprs_set (insn);
} }
} }
}
if (gcse_file != NULL) if (gcse_file != NULL)
fprintf (gcse_file, "\n"); fprintf (gcse_file, "\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment