From 9318b36873d2cb12dc5b90dcf84369b2adb27d1b Mon Sep 17 00:00:00 2001 From: rsandifo Date: Tue, 4 May 2004 17:57:39 +0000 Subject: [PATCH] * reload1.c (inherit_piecemeal_p): New function. (emit_reload_insns): When reloading a group of hard registers, use inherit_piecemeal_p to decide whether the values of individual hard registers can be inherited. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@81480 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++++++ gcc/reload1.c | 40 +++++++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/torture/mips-hilo-2.c | 24 ++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/mips-hilo-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9585261..95a70e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-05-04 Richard Sandiford + + * reload1.c (inherit_piecemeal_p): New function. + (emit_reload_insns): When reloading a group of hard registers, use + inherit_piecemeal_p to decide whether the values of individual hard + registers can be inherited. + 2004-05-04 H.J. Lu * config/ia64/t-ia64 (LIB2ADDEH): Remove gthr-gnat.c. diff --git a/gcc/reload1.c b/gcc/reload1.c index 56f02c9..8c17a61 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -417,6 +417,7 @@ static void emit_output_reload_insns (struct insn_chain *, struct reload *, int); static void do_input_reload (struct insn_chain *, struct reload *, int); static void do_output_reload (struct insn_chain *, struct reload *, int); +static bool inherit_piecemeal_p (int, int); static void emit_reload_insns (struct insn_chain *); static void delete_output_reload (rtx, int, int); static void delete_address_reloads (rtx, rtx); @@ -6956,6 +6957,27 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j) emit_output_reload_insns (chain, rld + j, j); } +/* Reload number R reloads from or to a group of hard registers starting at + register REGNO. Return true if it can be treated for inheritance purposes + like a group of reloads, each one reloading a single hard register. + The caller has already checked that the spill register and REGNO use + the same number of registers to store the reload value. */ + +static bool +inherit_piecemeal_p (int r, int regno) +{ +#ifdef CANNOT_CHANGE_MODE_CLASS + return (!REG_CANNOT_CHANGE_MODE_P (reload_spill_index[r], + GET_MODE (rld[r].reg_rtx), + reg_raw_mode[reload_spill_index[r]]) + && !REG_CANNOT_CHANGE_MODE_P (regno, + GET_MODE (rld[r].reg_rtx), + reg_raw_mode[regno])); +#else + return true; +#endif +} + /* Output insns to reload values in and out of the chosen reload regs. */ static void @@ -7137,11 +7159,16 @@ emit_reload_insns (struct insn_chain *chain) int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1 : hard_regno_nregs[nregno] [GET_MODE (rld[r].reg_rtx)]); + bool piecemeal; spill_reg_store[i] = new_spill_reg_store[i]; spill_reg_stored_to[i] = out; reg_last_reload_reg[nregno] = rld[r].reg_rtx; + piecemeal = (nregno < FIRST_PSEUDO_REGISTER + && nr == nnr + && inherit_piecemeal_p (r, nregno)); + /* If NREGNO is a hard register, it may occupy more than one register. If it does, say what is in the rest of the registers assuming that both registers @@ -7151,7 +7178,7 @@ emit_reload_insns (struct insn_chain *chain) if (nregno < FIRST_PSEUDO_REGISTER) for (k = 1; k < nnr; k++) reg_last_reload_reg[nregno + k] - = (nr == nnr + = (piecemeal ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k] : 0); @@ -7160,7 +7187,7 @@ emit_reload_insns (struct insn_chain *chain) { CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k); reg_reloaded_contents[i + k] - = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr + = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal ? nregno : nregno + k); reg_reloaded_insn[i + k] = insn; @@ -7185,6 +7212,7 @@ emit_reload_insns (struct insn_chain *chain) int nregno; int nnr; rtx in; + bool piecemeal; if (GET_CODE (rld[r].in) == REG && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER) @@ -7201,10 +7229,14 @@ emit_reload_insns (struct insn_chain *chain) reg_last_reload_reg[nregno] = rld[r].reg_rtx; + piecemeal = (nregno < FIRST_PSEUDO_REGISTER + && nr == nnr + && inherit_piecemeal_p (r, nregno)); + if (nregno < FIRST_PSEUDO_REGISTER) for (k = 1; k < nnr; k++) reg_last_reload_reg[nregno + k] - = (nr == nnr + = (piecemeal ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k] : 0); @@ -7220,7 +7252,7 @@ emit_reload_insns (struct insn_chain *chain) { CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k); reg_reloaded_contents[i + k] - = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr + = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal ? nregno : nregno + k); reg_reloaded_insn[i + k] = insn; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df01d26..f2d454b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-05-04 Richard Sandiford + + * gcc.dg/torture/mips-hilo-2.c: New test. + 2004-05-03 Giovanni Bajo PR c++/14389 diff --git a/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c b/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c new file mode 100644 index 0000000..a8db617 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c @@ -0,0 +1,24 @@ +/* Due to a reload inheritance bug, the asm statement in f() would be passed + the low part of u.ll on little-endian 32-bit targets. */ +/* { dg-do run { target mips*-*-* } } */ + +unsigned int g; + +unsigned long long f (unsigned int x) +{ + union { unsigned long long ll; unsigned int parts[2]; } u; + + u.ll = ((unsigned long long) x * x); + asm ("mflo\t%0" : "=r" (g) : "l" (u.parts[1])); + return u.ll; +} + +int main () +{ + union { unsigned long long ll; unsigned int parts[2]; } u; + + u.ll = f (0x12345678); + if (g != u.parts[1]) + abort (); + exit (0); +} -- 2.7.4