reload fix
Jan Hubicka
jh@suse.cz
Tue May 14 03:13:00 GMT 2002
Hi
the following testcase:
extern double cos (double __x) ; extern double __cos (double __x) ;
extern double sin (double __x) ; extern double __sin (double __x) ;
void
axis_to_quat(float a[3], float phi, float q[4])
{
vcopy(a,q);
vscale(q,sin(phi/2.0));
q[3] = cos(phi/2.0);
}
Crashes on x86_64 (and probably i386 with SSE2/ssemath) as well by producing
zero extend from st(0) to xmm1 in reload. This happends in emit_inoyt_reload_insns
that attempts to optimize and replace source originally properly reloaded by
xmm1, since it veirfies the transformation of constraint_accepts_reg_p that
implicitly assumes each alternative is matching.
I am not quite sure if the attached patch is the proper fix. I think idea of
constraint_accepts_reg_p is simply broken, so I replace it by extract_insn
and constrain operands. This can have two problems, eigther that the insns
are not completely reload or that otehr instruction must be extracted, but
I am not able to reproduce any of such scenarios.
Honza
Tue May 14 11:51:21 CEST 2002 Jan Hubicka <jh@suse.cz>
* reload1.c (emit_input_reload_insns): Use constrain_operands
instead of constraint_accepts_reg_p to verify optimization.
(constraint_accepts_reg_p): Kill
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.335
diff -c -3 -p -r1.335 reload1.c
*** reload1.c 9 May 2002 01:42:26 -0000 1.335
--- reload1.c 14 May 2002 09:51:17 -0000
*************** static void delete_output_reload PARAMS
*** 440,446 ****
static void delete_address_reloads PARAMS ((rtx, rtx));
static void delete_address_reloads_1 PARAMS ((rtx, rtx, rtx));
static rtx inc_for_reload PARAMS ((rtx, rtx, rtx, int));
- static int constraint_accepts_reg_p PARAMS ((const char *, rtx));
static void reload_cse_regs_1 PARAMS ((rtx));
static int reload_cse_noop_set_p PARAMS ((rtx));
static int reload_cse_simplify_set PARAMS ((rtx, rtx));
--- 440,445 ----
*************** emit_input_reload_insns (chain, rl, old,
*** 6384,6421 ****
&& SET_DEST (PATTERN (temp)) == old
/* Make sure we can access insn_operand_constraint. */
&& asm_noperands (PATTERN (temp)) < 0
- /* This is unsafe if prev insn rejects our reload reg. */
- && constraint_accepts_reg_p (insn_data[recog_memoized (temp)].operand[0].constraint,
- reloadreg)
/* This is unsafe if operand occurs more than once in current
insn. Perhaps some occurrences aren't reloaded. */
! && count_occurrences (PATTERN (insn), old, 0) == 1
! /* Don't risk splitting a matching pair of operands. */
! && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp))))
{
/* Store into the reload register instead of the pseudo. */
SET_DEST (PATTERN (temp)) = reloadreg;
! /* If the previous insn is an output reload, the source is
! a reload register, and its spill_reg_store entry will
! contain the previous destination. This is now
! invalid. */
! if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
! && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
! {
! spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! }
!
! /* If these are the only uses of the pseudo reg,
! pretend for GDB it lives in the reload reg we used. */
! if (REG_N_DEATHS (REGNO (old)) == 1
! && REG_N_SETS (REGNO (old)) == 1)
{
! reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
! alter_reg (REGNO (old), -1);
}
- special = 1;
}
}
--- 6383,6425 ----
&& SET_DEST (PATTERN (temp)) == old
/* Make sure we can access insn_operand_constraint. */
&& asm_noperands (PATTERN (temp)) < 0
/* This is unsafe if operand occurs more than once in current
insn. Perhaps some occurrences aren't reloaded. */
! && count_occurrences (PATTERN (insn), old, 0) == 1)
{
+ rtx old = SET_DEST (PATTERN (temp));
/* Store into the reload register instead of the pseudo. */
SET_DEST (PATTERN (temp)) = reloadreg;
! /* Verify that resulting insn is valid. */
! extract_insn (temp);
! if (constrain_operands (1))
{
! /* If the previous insn is an output reload, the source is
! a reload register, and its spill_reg_store entry will
! contain the previous destination. This is now
! invalid. */
! if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
! && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
! {
! spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! }
!
! /* If these are the only uses of the pseudo reg,
! pretend for GDB it lives in the reload reg we used. */
! if (REG_N_DEATHS (REGNO (old)) == 1
! && REG_N_SETS (REGNO (old)) == 1)
! {
! reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
! alter_reg (REGNO (old), -1);
! }
! special = 1;
! }
! else
! {
! SET_DEST (PATTERN (temp)) = old;
}
}
}
*************** inc_for_reload (reloadreg, in, value, in
*** 7978,8028 ****
}
return store;
- }
-
- /* Return 1 if we are certain that the constraint-string STRING allows
- the hard register REG. Return 0 if we can't be sure of this. */
-
- static int
- constraint_accepts_reg_p (string, reg)
- const char *string;
- rtx reg;
- {
- int value = 0;
- int regno = true_regnum (reg);
- int c;
-
- /* Initialize for first alternative. */
- value = 0;
- /* Check that each alternative contains `g' or `r'. */
- while (1)
- switch (c = *string++)
- {
- case 0:
- /* If an alternative lacks `g' or `r', we lose. */
- return value;
- case ',':
- /* If an alternative lacks `g' or `r', we lose. */
- if (value == 0)
- return 0;
- /* Initialize for next alternative. */
- value = 0;
- break;
- case 'g':
- case 'r':
- /* Any general reg wins for this alternative. */
- if (TEST_HARD_REG_BIT (reg_class_contents[(int) GENERAL_REGS], regno))
- value = 1;
- break;
- default:
- /* Any reg in specified class wins for this alternative. */
- {
- enum reg_class class = REG_CLASS_FROM_LETTER (c);
-
- if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))
- value = 1;
- }
- }
}
/* INSN is a no-op; delete it.
--- 7982,7987 ----
More information about the Gcc-patches
mailing list