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)
{ hash_scan_set (pat, insn, set_p);
/* Ignore obvious no-ops. */
if (SET_SRC (pat) != SET_DEST (pat))
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;
/* Try this two ways: first just replace SET_SRC. If that doesn't
note = REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, work and this is a PARALLEL, try to replace the whole pattern
copy_rtx (SET_SRC (set)), with a new SET. */
REG_NOTES (insn)); 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))) /* We've failed to do replacement, have a single SET, and don't already
abort(); 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));
src = XEXP (note, 0); /* If there is already a NOTE, update the expression in it with our
replacement. */
else if (note != 0)
XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to);
/* Try to simplify resulting note. */ /* REG_EQUAL may get simplified into register.
simplified = simplify_rtx (src); We don't allow that. Remove that note. This code ought
if (simplified) not to hapen, because previous code ought to syntetize
{ reg-reg move, but be on the safe side. */
src = simplified; if (note && REG_P (XEXP (note, 0)))
XEXP (note, 0) = src; remove_note (insn, note);
}
/* REG_EQUAL may get simplified into register.
We don't allow that. Remove that note. This code ought
not to hapen, because previous code ought to syntetize
reg-reg move, but be on the safe side. */
else if (REG_P (src))
remove_note (insn, note);
}
return success; return success;
} }
...@@ -3734,82 +3732,57 @@ find_avail_set (regno, insn) ...@@ -3734,82 +3732,57 @@ 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. */
INSN_CODE (copy) = -1;
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 SET_SRC (set) = new;
or a nop-jump. We'd like to delete nop jumps
here, but doing so confuses gcse. So we just if (JUMP_LABEL (insn) != 0)
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));
}
/* If this has turned into an unconditional jump, /* Otherwise, this must be a valid instruction. */
then put a barrier after it so that the unreachable else if (! validate_change (insn, &SET_SRC (set), new, 0))
code will be deleted. */ return 0;
if (GET_CODE (SET_SRC (set)) == LABEL_REF)
emit_barrier_after (insn);
run_jump_opt_after_gcse = 1; /* If this has turned into an unconditional jump,
then put a barrier after it so that the unreachable
code will be deleted. */
if (GET_CODE (SET_SRC (set)) == LABEL_REF)
emit_barrier_after (insn);
const_prop_count++; run_jump_opt_after_gcse = 1;
if (gcse_file != NULL)
{
fprintf (gcse_file,
"CONST-PROP: Replacing reg %d in insn %d with constant ",
REGNO (reg_used->reg_rtx), INSN_UID (insn));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
return 1; const_prop_count++;
if (gcse_file != NULL)
{
fprintf (gcse_file,
"CONST-PROP: Replacing reg %d in insn %d with constant ",
REGNO (from), INSN_UID (insn));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
} }
return 0;
return 1;
} }
#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,13 +3917,11 @@ cprop_insn (insn, alter_jumps) ...@@ -3947,13 +3917,11 @@ 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
} }
...@@ -4006,17 +3974,15 @@ cprop (alter_jumps) ...@@ -4006,17 +3974,15 @@ 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);
/* Keep track of everything modified by this insn. */ /* Keep track of everything modified by this insn. */
/* ??? Need to be careful w.r.t. mods done to INSN. Don't /* ??? Need to be careful w.r.t. mods done to INSN. Don't
call mark_oprs_set if we turned the insn into a NOTE. */ call mark_oprs_set if we turned the insn into a NOTE. */
if (GET_CODE (insn) != NOTE) if (GET_CODE (insn) != NOTE)
mark_oprs_set (insn); mark_oprs_set (insn);
}
} }
} }
......
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