The following patch was committed to gcc5 branch as rev. 226442.
The patch was bootstrapped and tested on x86/x86-64. 2015-07-31 Vladimir Makarov <vmaka...@redhat.com> PR debug/66691 * lra-int.h (lra_substitute_pseudo): Add a parameter. (lra_substitute_pseudo_within_insn): Ditto. * lra.c (lra_substitute_pseudo): Add a parameter. Simplify subreg of constant. (lra_substitute_pseudo_within_insn): Add a parameter. Transfer it to lra_substitute_pseudo. * lra-lives.c (process_bb_lives): Add an argument to lra_substitute_pseudo_within_insn call. * lra-constraints.c (inherit_reload_reg, split_reg): Add an argument to lra_substitute_pseudo and lra_substitute_pseudo_within_insn calls. (remove_inheritance_pseudos, undo_optional_reloads): Ditto. 2015-07-31 Vladimir Makarov <vmaka...@redhat.com> PR debug/66691 * gcc.target/i386/pr66691.c: New.
Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 226441) +++ lra-constraints.c (working copy) @@ -4729,7 +4729,7 @@ inherit_reload_reg (bool def_p, int orig } return false; } - lra_substitute_pseudo_within_insn (insn, original_regno, new_reg); + lra_substitute_pseudo_within_insn (insn, original_regno, new_reg, false); lra_update_insn_regno_info (insn); if (! def_p) /* We now have a new usage insn for original regno. */ @@ -4761,7 +4761,7 @@ inherit_reload_reg (bool def_p, int orig lra_assert (DEBUG_INSN_P (usage_insn)); next_usage_insns = XEXP (next_usage_insns, 1); } - lra_substitute_pseudo (&usage_insn, original_regno, new_reg); + lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false); lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); if (lra_dump_file != NULL) { @@ -5023,7 +5023,7 @@ split_reg (bool before_p, int original_r usage_insn = XEXP (next_usage_insns, 0); lra_assert (DEBUG_INSN_P (usage_insn)); next_usage_insns = XEXP (next_usage_insns, 1); - lra_substitute_pseudo (&usage_insn, original_regno, new_reg); + lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false); lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); if (lra_dump_file != NULL) { @@ -5955,8 +5955,9 @@ remove_inheritance_pseudos (bitmap remov { if (change_p && bitmap_bit_p (remove_pseudos, regno)) { - lra_substitute_pseudo_within_insn ( - curr_insn, regno, regno_reg_rtx[restore_regno]); + lra_substitute_pseudo_within_insn + (curr_insn, regno, regno_reg_rtx[restore_regno], + false); restored_regs_p = true; } else @@ -6079,9 +6080,9 @@ undo_optional_reloads (void) we remove the inheritance pseudo and the optional reload. */ } - lra_substitute_pseudo_within_insn ( - insn, regno, - regno_reg_rtx[lra_reg_info[regno].restore_regno]); + lra_substitute_pseudo_within_insn + (insn, regno, regno_reg_rtx[lra_reg_info[regno].restore_regno], + false); lra_update_insn_regno_info (insn); if (lra_dump_file != NULL) { Index: lra-int.h =================================================================== --- lra-int.h (revision 226441) +++ lra-int.h (working copy) @@ -314,8 +314,8 @@ extern void lra_update_dups (lra_insn_re extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *, const char *); -extern bool lra_substitute_pseudo (rtx *, int, rtx); -extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx); +extern bool lra_substitute_pseudo (rtx *, int, rtx, bool); +extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx, bool); extern lra_insn_recog_data_t lra_set_insn_recog_data (rtx_insn *); extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx_insn *); Index: lra-lives.c =================================================================== --- lra-lives.c (revision 226441) +++ lra-lives.c (working copy) @@ -759,7 +759,7 @@ process_bb_lives (basic_block bb, int &c { insn = lra_insn_recog_data[uid]->insn; lra_substitute_pseudo_within_insn (insn, dst_regno, - SET_SRC (set)); + SET_SRC (set), true); lra_update_insn_regno_info (insn); } } Index: lra.c =================================================================== --- lra.c (revision 226441) +++ lra.c (working copy) @@ -1818,9 +1818,10 @@ lra_process_new_insns (rtx_insn *insn, r /* Replace all references to register OLD_REGNO in *LOC with pseudo - register NEW_REG. Return true if any change was made. */ + register NEW_REG. Try to simplify subreg of constant if SUBREG_P. + Return true if any change was made. */ bool -lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg) +lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p) { rtx x = *loc; bool result = false; @@ -1832,9 +1833,25 @@ lra_substitute_pseudo (rtx *loc, int old return false; code = GET_CODE (x); - if (code == REG && (int) REGNO (x) == old_regno) + if (code == SUBREG && subreg_p) { - machine_mode mode = GET_MODE (*loc); + rtx subst, inner = SUBREG_REG (x); + /* Transform subreg of constant while we still have inner mode + of the subreg. The subreg internal should not be an insn + operand. */ + if (REG_P (inner) && (int) REGNO (inner) == old_regno + && CONSTANT_P (new_reg) + && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner), + SUBREG_BYTE (x))) != NULL_RTX) + { + *loc = subst; + return true; + } + + } + else if (code == REG && (int) REGNO (x) == old_regno) + { + machine_mode mode = GET_MODE (x); machine_mode inner_mode = GET_MODE (new_reg); if (mode != inner_mode @@ -1856,26 +1873,30 @@ lra_substitute_pseudo (rtx *loc, int old { if (fmt[i] == 'e') { - if (lra_substitute_pseudo (&XEXP (x, i), old_regno, new_reg)) + if (lra_substitute_pseudo (&XEXP (x, i), old_regno, + new_reg, subreg_p)) result = true; } else if (fmt[i] == 'E') { for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno, new_reg)) + if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno, + new_reg, subreg_p)) result = true; } } return result; } -/* Call lra_substitute_pseudo within an insn. This won't update the insn ptr, - just the contents of the insn. */ +/* Call lra_substitute_pseudo within an insn. Try to simplify subreg + of constant if SUBREG_P. This won't update the insn ptr, just the + contents of the insn. */ bool -lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, rtx new_reg) +lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, + rtx new_reg, bool subreg_p) { rtx loc = insn; - return lra_substitute_pseudo (&loc, old_regno, new_reg); + return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p); } Index: testsuite/gcc.target/i386/pr66691.c =================================================================== --- testsuite/gcc.target/i386/pr66691.c (revision 0) +++ testsuite/gcc.target/i386/pr66691.c (working copy) @@ -0,0 +1,64 @@ +/* PR debug/66691 */ +/* { dg-do compile } */ +/* { dg-require-effective-target ia32 } */ +/* { dg-options "-O3 -g -mtune=generic -march=i686" } */ + +unsigned int a; +int b[2], c, d, e, f, g, h, i, k[8], l, m, s, t, w; +static int j; + +void +fn1 (long long p) +{ + int t = p; + c = c ^ b[c ^ (t & 1)]; +} + +static void +fn2 (long long p) +{ + c = c ^ b[1 ^ (d & 1)]; + fn1 (p >> 1 & 1); + fn1 (p >> 2); +} + +static void +fn3 () +{ + unsigned char p; + f = g = 0; + for (h = 0; h < 6; h++) + { + for (s = 0; s < 7; s++) + if (k[s+1]) + g = 0; + else + for (j = 0; j < 2; j++) + ; + t = j > 2 ? 0 : 1 >> j; + } + if (l) + { + short q[2]; + q[0] = q[1] = 0; + if (m) + for (i = 0; i < 2; i++) + { + unsigned char r = q[i]; + p = f ? r % f : r; + e = ((p > 0) <= (q[i] ^ 1)) + a; + if (k[1]) + for (e = 0; e != 18; ++e) + k[0] = 0; + } + } +} + +int +main () +{ + fn3 (); + fn2 (w); + fn2 (j); + return 0; +}