This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR36194
Adam Nemet <anemet@caviumnetworks.com> writes:
> Oh sorry, absolutely, I will fix that and retest. Thanks again.
I retested the patch below with a regtest and bootstrap on x86_64-linux, a
bootstrap on mips64-linux-gnu and a regtest on mipsisa64-elf. It's checked it
in as r135392 on trunk.
Adam
2008-05-15 Adam Nemet <anemet@caviumnetworks.com>
PR middle-end/36194
* combine.c (check_conversion): Rename back to check_promoted_subreg.
Don't call record_truncated_value from here.
(record_truncated_value): Turn it into a for_each_rtx callback.
(record_truncated_values): New function.
(combine_instructions): Call note_uses with
record_truncated_values. Change name of check_conversion to
check_promoted_subreg.
2008-05-15 Adam Nemet <anemet@caviumnetworks.com>
PR middle-end/36194
* gcc.dg/pr36194.c: New test.
Index: combine.c
===================================================================
*** combine.c (revision 135295)
--- combine.c (working copy)
*************** static rtx gen_lowpart_for_combine (enum
*** 425,431 ****
static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
static void update_table_tick (rtx);
static void record_value_for_reg (rtx, rtx, rtx);
! static void check_conversions (rtx, rtx);
static void record_dead_and_set_regs_1 (rtx, const_rtx, void *);
static void record_dead_and_set_regs (rtx);
static int get_last_value_validate (rtx *, rtx, int, int);
--- 425,431 ----
static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
static void update_table_tick (rtx);
static void record_value_for_reg (rtx, rtx, rtx);
! static void check_promoted_subreg (rtx, rtx);
static void record_dead_and_set_regs_1 (rtx, const_rtx, void *);
static void record_dead_and_set_regs (rtx);
static int get_last_value_validate (rtx *, rtx, int, int);
*************** static void mark_used_regs_combine (rtx)
*** 441,447 ****
static void record_promoted_value (rtx, rtx);
static int unmentioned_reg_p_1 (rtx *, void *);
static bool unmentioned_reg_p (rtx, rtx);
! static void record_truncated_value (rtx);
static bool reg_truncated_to_mode (enum machine_mode, const_rtx);
static rtx gen_lowpart_or_truncate (enum machine_mode, rtx);
--- 441,448 ----
static void record_promoted_value (rtx, rtx);
static int unmentioned_reg_p_1 (rtx *, void *);
static bool unmentioned_reg_p (rtx, rtx);
! static int record_truncated_value (rtx *, void *);
! static void record_truncated_values (rtx *, void *);
static bool reg_truncated_to_mode (enum machine_mode, const_rtx);
static rtx gen_lowpart_or_truncate (enum machine_mode, rtx);
*************** combine_instructions (rtx f, unsigned in
*** 1137,1143 ****
{
/* See if we know about function return values before this
insn based upon SUBREG flags. */
! check_conversions (insn, PATTERN (insn));
/* Try this insn with each insn it links back to. */
--- 1138,1149 ----
{
/* See if we know about function return values before this
insn based upon SUBREG flags. */
! check_promoted_subreg (insn, PATTERN (insn));
!
! /* See if we can find hardregs and subreg of pseudos in
! narrower modes. This could help turning TRUNCATEs
! into SUBREGs. */
! note_uses (&PATTERN (insn), record_truncated_values, NULL);
/* Try this insn with each insn it links back to. */
*************** reg_truncated_to_mode (enum machine_mode
*** 11610,11622 ****
return false;
}
! /* X is a REG or a SUBREG. If X is some sort of a truncation record
! it. For non-TRULY_NOOP_TRUNCATION targets we might be able to turn
! a truncate into a subreg using this information. */
! static void
! record_truncated_value (rtx x)
{
enum machine_mode truncated_mode;
reg_stat_type *rsp;
--- 11616,11630 ----
return false;
}
! /* Callback for for_each_rtx. If *P is a hard reg or a subreg record the mode
! that the register is accessed in. For non-TRULY_NOOP_TRUNCATION targets we
! might be able to turn a truncate into a subreg using this information.
! Return -1 if traversing *P is complete or 0 otherwise. */
! static int
! record_truncated_value (rtx *p, void *data ATTRIBUTE_UNUSED)
{
+ rtx x = *p;
enum machine_mode truncated_mode;
reg_stat_type *rsp;
*************** record_truncated_value (rtx x)
*** 11626,11636 ****
truncated_mode = GET_MODE (x);
if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
! return;
if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (truncated_mode),
GET_MODE_BITSIZE (original_mode)))
! return;
x = SUBREG_REG (x);
}
--- 11634,11644 ----
truncated_mode = GET_MODE (x);
if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
! return -1;
if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (truncated_mode),
GET_MODE_BITSIZE (original_mode)))
! return -1;
x = SUBREG_REG (x);
}
*************** record_truncated_value (rtx x)
*** 11639,11645 ****
else if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
truncated_mode = GET_MODE (x);
else
! return;
rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
if (rsp->truncated_to_mode == 0
--- 11647,11653 ----
else if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
truncated_mode = GET_MODE (x);
else
! return 0;
rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
if (rsp->truncated_to_mode == 0
*************** record_truncated_value (rtx x)
*** 11650,11672 ****
rsp->truncated_to_mode = truncated_mode;
rsp->truncation_label = label_tick;
}
}
! /* Scan X for promoted SUBREGs and truncated REGs. For each one
! found, note what it implies to the registers used in it. */
static void
! check_conversions (rtx insn, rtx x)
{
! if (GET_CODE (x) == SUBREG || REG_P (x))
! {
! if (GET_CODE (x) == SUBREG
! && SUBREG_PROMOTED_VAR_P (x)
! && REG_P (SUBREG_REG (x)))
! record_promoted_value (insn, x);
! record_truncated_value (x);
! }
else
{
const char *format = GET_RTX_FORMAT (GET_CODE (x));
--- 11658,11687 ----
rsp->truncated_to_mode = truncated_mode;
rsp->truncation_label = label_tick;
}
+
+ return -1;
}
! /* Callback for note_uses. Find hardregs and subregs of pseudos and
! the modes they are used in. This can help truning TRUNCATEs into
! SUBREGs. */
static void
! record_truncated_values (rtx *x, void *data ATTRIBUTE_UNUSED)
{
! for_each_rtx (x, record_truncated_value, NULL);
! }
! /* Scan X for promoted SUBREGs. For each one found,
! note what it implies to the registers used in it. */
!
! static void
! check_promoted_subreg (rtx insn, rtx x)
! {
! if (GET_CODE (x) == SUBREG
! && SUBREG_PROMOTED_VAR_P (x)
! && REG_P (SUBREG_REG (x)))
! record_promoted_value (insn, x);
else
{
const char *format = GET_RTX_FORMAT (GET_CODE (x));
*************** check_conversions (rtx insn, rtx x)
*** 11676,11688 ****
switch (format[i])
{
case 'e':
! check_conversions (insn, XEXP (x, i));
break;
case 'V':
case 'E':
if (XVEC (x, i) != 0)
for (j = 0; j < XVECLEN (x, i); j++)
! check_conversions (insn, XVECEXP (x, i, j));
break;
}
}
--- 11691,11703 ----
switch (format[i])
{
case 'e':
! check_promoted_subreg (insn, XEXP (x, i));
break;
case 'V':
case 'E':
if (XVEC (x, i) != 0)
for (j = 0; j < XVECLEN (x, i); j++)
! check_promoted_subreg (insn, XVECEXP (x, i, j));
break;
}
}
Index: testsuite/gcc.dg/pr36194.c
===================================================================
*** testsuite/gcc.dg/pr36194.c (revision 0)
--- testsuite/gcc.dg/pr36194.c (revision 0)
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do run } */
+ /* { dg-options "-O2" } */
+
+ void abort (void);
+
+ __attribute__ ((noinline)) void
+ f (int i)
+ {
+ if (i != 0x87654321)
+ abort ();
+ asm ("");
+ }
+
+ __attribute__ ((noinline)) void
+ g (long long a)
+ {
+ f (a);
+ asm ("");
+ }
+
+ main ()
+ {
+ g (0x1234567887654321ll);
+ return 0;
+ }