This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[dataflow] partial register handling
- From: Roman Zippel <zippel at linux-m68k dot org>
- To: gcc at gcc dot gnu dot org
- Cc: zadeck at naturalbridge dot com, dberlin at dberlin dot org
- Date: Thu, 10 May 2007 19:43:19 +0200 (CEST)
- Subject: [dataflow] partial register handling
Hi,
I have a few problems with the m68k mulsidi3 pattern on the dataflow
branch.
Currently incorrect code is generated as the DF_REF_PARTIAL bit isn't
set for its destinations and dataflow thinks both set the register
completely, thus one destination is set to unused. I could change the
pattern to include a strict_low_part, but that still wouldn't help due
to a bug in df_def_record_1().
Looking closer at this I don't think strict_low_part should be required
as splitting DI registers produces a lot of (subreg:SI (reg:DI)) even as
destination, but they only set strictly part of the register. If I look
through i386/m68k I don't see a single (strict_low_part (subreg:SI)).
I also think that ZERO_EXTRACT should set DF_REF_PARTIAL as well, since
e.g. these two patterns are equivalent:
(set (strict_low_part (subreg:HI (reg:SI))) ...)
(set (zero_extract:SI (reg:SI) (const_int 16) (const_int 16)) ...)
Below is the first attempt at fixing this, the subreg handling might
need further improvement. df_ref_record sets the partial bit for hard
registers but not for virtual registers?
I also removed one check from df_read_modify_subreg_p, why should
(subreg:QI (reg:DI)) be treated differently than (subreg:QI (reg:SI))?
The df_read_modify_subreg_p might be taken out of the loop, as currently
df_ref_record sees only a fraction of all subregs and thus I'm not sure
the subreg check always works.
bye, Roman
---
gcc/df-scan.c | 28 ------------!!!!!!!!!!!!!!!!
1 file changed, 12 deletions(-), 16 modifications(!)
Index: gcc-dataflow/gcc/df-scan.c
===================================================================
*** gcc-dataflow.orig/gcc/df-scan.c
--- gcc-dataflow/gcc/df-scan.c
*************** df_read_modify_subreg_p (rtx x)
*** 2702,2708 ****
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
! return (isize > osize && isize > UNITS_PER_WORD);
}
--- 2702,2708 ----
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
! return isize > osize;
}
*************** df_def_record_1 (struct df_collection_re
*** 2717,2723 ****
{
rtx *loc;
rtx dst;
- bool dst_in_strict_lowpart = false;
/* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
construct. */
--- 2717,2722 ----
*************** df_def_record_1 (struct df_collection_re
*** 2751,2780 ****
|| GET_CODE (dst) == ZERO_EXTRACT
|| df_read_modify_subreg_p (dst))
{
! #if 0
! /* Strict low part always contains SUBREG, but we do not want to make
! it appear outside, as whole register is always considered. */
! if (GET_CODE (dst) == STRICT_LOW_PART)
! {
! loc = &XEXP (dst, 0);
! dst = *loc;
! }
! #endif
loc = &XEXP (dst, 0);
- if (GET_CODE (dst) == STRICT_LOW_PART)
- dst_in_strict_lowpart = true;
dst = *loc;
- flags |= DF_REF_READ_WRITE;
-
}
- /* Sets to a subreg of a single word register are partial sets if
- they are wrapped in a strict lowpart, and not partial otherwise.
- */
- if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))
- && dst_in_strict_lowpart)
- flags |= DF_REF_PARTIAL;
-
if (REG_P (dst)
|| (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))))
df_ref_record (collection_rec,
--- 2750,2764 ----
|| GET_CODE (dst) == ZERO_EXTRACT
|| df_read_modify_subreg_p (dst))
{
! flags |= DF_REF_READ_WRITE;
! if (GET_CODE (dst) != SUBREG
! || GET_MODE_SIZE (GET_MODE (dst))
! >= REGMODE_NATURAL_SIZE (GET_MODE (dst)))
! flags |= DF_REF_PARTIAL;
loc = &XEXP (dst, 0);
dst = *loc;
}
if (REG_P (dst)
|| (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))))
df_ref_record (collection_rec,