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:
John David Anglin 2003-10-08 17:55:41 +00:00 committed by John David Anglin
parent 85aa13b287
commit 9ab81df261
3 changed files with 48 additions and 36 deletions

View File

@ -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>

View File

@ -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)

View File

@ -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++;
}