From patchwork Sat Oct 6 02:52:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [lra] patch to fix a bug Date: Fri, 05 Oct 2012 16:52:25 -0000 From: Vladimir Makarov X-Patchwork-Id: 189661 Message-Id: <506F9CE9.4090108@redhat.com> To: GCC Patches The following patch fixes a bug found on x86-64 in a big program with some options combination. The patch was successfully bootstrapped on x86/x86-64. The patch changes the code for about 30% of SPEC2000 tests. But these changes are quite small (in code size and performance point of view). The patch is committed as rev. 192153. 2012-10-05 Vladimir Makarov * lra-constraints.c (multi_block_pseudo_p, dead_pseudo_p): New functions. (insn_rhs_dead_pseudo_p, init_insn_rhs_dead_pseudo_p): Ditto. (lra_constraints): Use them. Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 192048) +++ lra-constraints.c (working copy) @@ -3590,6 +3590,83 @@ int lra_constraint_iter_after_spill; pseudo. */ bool lra_risky_transformations_p; +/* Return true if REGNO is referenced in more than one block. */ +static bool +multi_block_pseudo_p (int regno) +{ + basic_block bb = NULL; + unsigned int uid; + bitmap_iterator bi; + + if (regno < FIRST_PSEUDO_REGISTER) + return false; + + EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi) + if (bb == NULL) + bb = BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn); + else if (BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn) != bb) + return true; + return false; +} + +/* Return true if X contains a pseudo dying in INSN. */ +static bool +dead_pseudo_p (rtx x, rtx insn) +{ + int i, j; + const char *fmt; + enum rtx_code code; + + if (REG_P (x)) + return (insn != NULL_RTX + && find_regno_note (insn, REG_DEAD, REGNO (x)) != NULL_RTX); + code = GET_CODE (x); + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + if (dead_pseudo_p (XEXP (x, i), insn)) + return true; + } + else if (fmt[i] == 'E') + { + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + if (dead_pseudo_p (XVECEXP (x, i, j), insn)) + return true; + } + } + return false; +} + +/* Return true if INSN contains a dying pseudo in INSN right hand + side. */ +static bool +insn_rhs_dead_pseudo_p (rtx insn) +{ + rtx set = single_set (insn); + + gcc_assert (set != NULL); + return dead_pseudo_p (SET_SRC (set), insn); +} + +/* Return true if any init insn of REGNO contains a dying pseudo in + insn right hand side. */ +static bool +init_insn_rhs_dead_pseudo_p (int regno) +{ + rtx insns = ira_reg_equiv[regno].init_insns; + + if (insns == NULL) + return false; + if (INSN_P (insns)) + return insn_rhs_dead_pseudo_p (insns); + for (; insns != NULL_RTX; insns = XEXP (insns, 1)) + if (insn_rhs_dead_pseudo_p (XEXP (insns, 0))) + return true; + return false; +} + /* Entry function of LRA constraint pass. Return true if the constraint pass did change the code. */ bool @@ -3628,7 +3705,22 @@ lra_constraints (bool first_p) } else if ((x = get_equiv_substitution (regno_reg_rtx[i])) != NULL_RTX) { - if (! first_p && contains_reg_p (x, false, false)) + bool pseudo_p = contains_reg_p (x, false, false); + + /* We don't use DF for compilation speed sake. So it is + problematic to update live info when we use an + equivalence containing pseudos in more than one BB. */ + if ((pseudo_p && multi_block_pseudo_p (i)) + /* We check that a pseudo in rhs of the init insn is + not dying in the insn. Otherwise, the live info + at the beginning of the corresponding BB might be + wrong after we removed the insn. When the equiv can + be a constant, the right hand side of the init insn + can be a pseudo. */ + || (ira_reg_equiv[i].memory == NULL_RTX + && init_insn_rhs_dead_pseudo_p (i))) + ira_reg_equiv[i].defined_p = false; + else if (! first_p && pseudo_p) /* After RTL transformation, we can not guarantee that pseudo in the substitution was not reloaded which might make equivalence invalid. For example, in