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,