re PR rtl-optimization/12142 (-fnon-call-exceptions generates incorrect code)
PR optimization/12142 * cse.c (count_reg_usage): In a SET with a REG SET_DEST, count the uses of the register in the SET_SRC. Remove unnecessary argument. * pa.c (legitimize_pic_address): Before reload, use a scratch register for the intermediate result in loading the address of a SYMBOL_REF. Set the MEM_NOTRAP_P flag for the MEM. Add a REG_EQUAL to the insn which loads the SYMBOL_REF address. From-SVN: r72234
This commit is contained in:
parent
85aa13b287
commit
9ab81df261
@ -1,3 +1,13 @@
|
||||
2003-10-08 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
PR optimization/12142
|
||||
* cse.c (count_reg_usage): In a SET with a REG SET_DEST, count the
|
||||
uses of the register in the SET_SRC. Remove unnecessary argument.
|
||||
* pa.c (legitimize_pic_address): Before reload, use a scratch register
|
||||
for the intermediate result in loading the address of a SYMBOL_REF.
|
||||
Set the MEM_NOTRAP_P flag for the MEM. Add a REG_EQUAL to the insn
|
||||
which loads the SYMBOL_REF address.
|
||||
|
||||
2003-10-08 Timo Kokkonen <tjko@iki.fi>
|
||||
Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
|
@ -836,22 +836,35 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
||||
}
|
||||
if (GET_CODE (orig) == SYMBOL_REF)
|
||||
{
|
||||
rtx insn, tmp_reg;
|
||||
|
||||
if (reg == 0)
|
||||
abort ();
|
||||
|
||||
emit_move_insn (reg,
|
||||
/* Before reload, allocate a temporary register for the intermediate
|
||||
result. This allows the sequence to be deleted when the final
|
||||
result is unused and the insns are trivially dead. */
|
||||
tmp_reg = ((reload_in_progress || reload_completed)
|
||||
? reg : gen_reg_rtx (Pmode));
|
||||
|
||||
emit_move_insn (tmp_reg,
|
||||
gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
|
||||
gen_rtx_HIGH (word_mode, orig)));
|
||||
pic_ref
|
||||
= gen_rtx_MEM (Pmode,
|
||||
gen_rtx_LO_SUM (Pmode, reg,
|
||||
gen_rtx_LO_SUM (Pmode, tmp_reg,
|
||||
gen_rtx_UNSPEC (Pmode,
|
||||
gen_rtvec (1, orig),
|
||||
0)));
|
||||
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
MEM_NOTRAP_P (pic_ref) = 1;
|
||||
RTX_UNCHANGING_P (pic_ref) = 1;
|
||||
emit_move_insn (reg, pic_ref);
|
||||
insn = emit_move_insn (reg, pic_ref);
|
||||
|
||||
/* Put a REG_EQUAL note on this insn, so that it can be optimized. */
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn));
|
||||
|
||||
return reg;
|
||||
}
|
||||
else if (GET_CODE (orig) == CONST)
|
||||
|
55
gcc/cse.c
55
gcc/cse.c
@ -647,7 +647,7 @@ static void invalidate_skipped_block (rtx);
|
||||
static void cse_check_loop_start (rtx, rtx, void *);
|
||||
static void cse_set_around_loop (rtx, rtx, rtx);
|
||||
static rtx cse_basic_block (rtx, rtx, struct branch_path *, int);
|
||||
static void count_reg_usage (rtx, int *, rtx, int);
|
||||
static void count_reg_usage (rtx, int *, int);
|
||||
static int check_for_label_ref (rtx *, void *);
|
||||
extern void dump_class (struct table_elt*);
|
||||
static struct cse_reg_info * get_cse_reg_info (unsigned int);
|
||||
@ -7301,14 +7301,10 @@ check_for_label_ref (rtx *rtl, void *data)
|
||||
|
||||
/* Count the number of times registers are used (not set) in X.
|
||||
COUNTS is an array in which we accumulate the count, INCR is how much
|
||||
we count each register usage.
|
||||
|
||||
Don't count a usage of DEST, which is the SET_DEST of a SET which
|
||||
contains X in its SET_SRC. This is because such a SET does not
|
||||
modify the liveness of DEST. */
|
||||
we count each register usage. */
|
||||
|
||||
static void
|
||||
count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
count_reg_usage (rtx x, int *counts, int incr)
|
||||
{
|
||||
enum rtx_code code;
|
||||
rtx note;
|
||||
@ -7321,8 +7317,7 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
switch (code = GET_CODE (x))
|
||||
{
|
||||
case REG:
|
||||
if (x != dest)
|
||||
counts[REGNO (x)] += incr;
|
||||
counts[REGNO (x)] += incr;
|
||||
return;
|
||||
|
||||
case PC:
|
||||
@ -7339,25 +7334,23 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
/* If we are clobbering a MEM, mark any registers inside the address
|
||||
as being used. */
|
||||
if (GET_CODE (XEXP (x, 0)) == MEM)
|
||||
count_reg_usage (XEXP (XEXP (x, 0), 0), counts, NULL_RTX, incr);
|
||||
count_reg_usage (XEXP (XEXP (x, 0), 0), counts, incr);
|
||||
return;
|
||||
|
||||
case SET:
|
||||
/* Unless we are setting a REG, count everything in SET_DEST. */
|
||||
if (GET_CODE (SET_DEST (x)) != REG)
|
||||
count_reg_usage (SET_DEST (x), counts, NULL_RTX, incr);
|
||||
count_reg_usage (SET_SRC (x), counts,
|
||||
SET_DEST (x),
|
||||
incr);
|
||||
count_reg_usage (SET_DEST (x), counts, incr);
|
||||
count_reg_usage (SET_SRC (x), counts, incr);
|
||||
return;
|
||||
|
||||
case CALL_INSN:
|
||||
count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, NULL_RTX, incr);
|
||||
count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, incr);
|
||||
/* Fall through. */
|
||||
|
||||
case INSN:
|
||||
case JUMP_INSN:
|
||||
count_reg_usage (PATTERN (x), counts, NULL_RTX, incr);
|
||||
count_reg_usage (PATTERN (x), counts, incr);
|
||||
|
||||
/* Things used in a REG_EQUAL note aren't dead since loop may try to
|
||||
use them. */
|
||||
@ -7372,12 +7365,12 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
Process all the arguments. */
|
||||
do
|
||||
{
|
||||
count_reg_usage (XEXP (eqv, 0), counts, NULL_RTX, incr);
|
||||
count_reg_usage (XEXP (eqv, 0), counts, incr);
|
||||
eqv = XEXP (eqv, 1);
|
||||
}
|
||||
while (eqv && GET_CODE (eqv) == EXPR_LIST);
|
||||
else
|
||||
count_reg_usage (eqv, counts, NULL_RTX, incr);
|
||||
count_reg_usage (eqv, counts, incr);
|
||||
}
|
||||
return;
|
||||
|
||||
@ -7387,19 +7380,15 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
/* FUNCTION_USAGE expression lists may include (CLOBBER (mem /u)),
|
||||
involving registers in the address. */
|
||||
|| GET_CODE (XEXP (x, 0)) == CLOBBER)
|
||||
count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
|
||||
count_reg_usage (XEXP (x, 0), counts, incr);
|
||||
|
||||
count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
|
||||
count_reg_usage (XEXP (x, 1), counts, incr);
|
||||
return;
|
||||
|
||||
case ASM_OPERANDS:
|
||||
/* If the asm is volatile, then this insn cannot be deleted,
|
||||
and so the inputs *must* be live. */
|
||||
if (MEM_VOLATILE_P (x))
|
||||
dest = NULL_RTX;
|
||||
/* Iterate over just the inputs, not the constraints as well. */
|
||||
for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
|
||||
count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, dest, incr);
|
||||
count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, incr);
|
||||
return;
|
||||
|
||||
case INSN_LIST:
|
||||
@ -7413,10 +7402,10 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
count_reg_usage (XEXP (x, i), counts, dest, incr);
|
||||
count_reg_usage (XEXP (x, i), counts, incr);
|
||||
else if (fmt[i] == 'E')
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
count_reg_usage (XVECEXP (x, i, j), counts, dest, incr);
|
||||
count_reg_usage (XVECEXP (x, i, j), counts, incr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7508,11 +7497,11 @@ dead_libcall_p (rtx insn, int *counts)
|
||||
new = XEXP (note, 0);
|
||||
|
||||
/* While changing insn, we must update the counts accordingly. */
|
||||
count_reg_usage (insn, counts, NULL_RTX, -1);
|
||||
count_reg_usage (insn, counts, -1);
|
||||
|
||||
if (validate_change (insn, &SET_SRC (set), new, 0))
|
||||
{
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
count_reg_usage (insn, counts, 1);
|
||||
remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
|
||||
remove_note (insn, note);
|
||||
return true;
|
||||
@ -7523,14 +7512,14 @@ dead_libcall_p (rtx insn, int *counts)
|
||||
new = force_const_mem (GET_MODE (SET_DEST (set)), new);
|
||||
if (new && validate_change (insn, &SET_SRC (set), new, 0))
|
||||
{
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
count_reg_usage (insn, counts, 1);
|
||||
remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
|
||||
remove_note (insn, note);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
count_reg_usage (insn, counts, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -7554,7 +7543,7 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
||||
/* First count the number of times each register is used. */
|
||||
counts = xcalloc (nreg, sizeof (int));
|
||||
for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
count_reg_usage (insn, counts, 1);
|
||||
|
||||
do
|
||||
{
|
||||
@ -7598,7 +7587,7 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
||||
|
||||
if (! live_insn)
|
||||
{
|
||||
count_reg_usage (insn, counts, NULL_RTX, -1);
|
||||
count_reg_usage (insn, counts, -1);
|
||||
delete_insn_and_edges (insn);
|
||||
ndead++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user