From: Alan Modra Date: Thu, 16 Feb 2017 22:56:51 +0000 (+1030) Subject: re PR rtl-optimization/79286 (ira and lra wrong code at -O2 and -Os on i686-linux) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a72b242eacf3bc43375daff829e04bcce634ad22;p=gcc.git re PR rtl-optimization/79286 (ira and lra wrong code at -O2 and -Os on i686-linux) 2017-02-16 Alan Modra PR rtl-optimization/79286 * ira.c (def_dominates_uses): New function. (update_equiv_regs): Don't create an equivalence for insns that may trap where the register def does not dominate the use. * gcc.c-torture/execute/pr79286.c: New. From-SVN: r245521 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2a4562ef9e..5a96b4ac8c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-02-16 Alan Modra + + PR rtl-optimization/79286 + * ira.c (def_dominates_uses): New function. + (update_equiv_regs): Don't create an equivalence for insns that + may trap where the register def does not dominate the use. + 2017-02-16 Vladimir Makarov PR rtl-optimization/78127 diff --git a/gcc/ira.c b/gcc/ira.c index 96b4b6206a5..6fb8aaffdcc 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3300,6 +3300,49 @@ adjust_cleared_regs (rtx loc, const_rtx old_rtx ATTRIBUTE_UNUSED, void *data) return NULL_RTX; } +/* Given register REGNO is set only once, return true if the defining + insn dominates all uses. */ + +static bool +def_dominates_uses (int regno) +{ + df_ref def = DF_REG_DEF_CHAIN (regno); + + struct df_insn_info *def_info = DF_REF_INSN_INFO (def); + /* If this is an artificial def (eh handler regs, hard frame pointer + for non-local goto, regs defined on function entry) then def_info + is NULL and the reg is always live before any use. We might + reasonably return true in that case, but since the only call + of this function is currently here in ira.c when we are looking + at a defining insn we can't have an artificial def as that would + bump DF_REG_DEF_COUNT. */ + gcc_assert (DF_REG_DEF_COUNT (regno) == 1 && def_info != NULL); + + rtx_insn *def_insn = DF_REF_INSN (def); + basic_block def_bb = BLOCK_FOR_INSN (def_insn); + + for (df_ref use = DF_REG_USE_CHAIN (regno); + use; + use = DF_REF_NEXT_REG (use)) + { + struct df_insn_info *use_info = DF_REF_INSN_INFO (use); + /* Only check real uses, not artificial ones. */ + if (use_info) + { + rtx_insn *use_insn = DF_REF_INSN (use); + if (!DEBUG_INSN_P (use_insn)) + { + basic_block use_bb = BLOCK_FOR_INSN (use_insn); + if (use_bb != def_bb + ? !dominated_by_p (CDI_DOMINATORS, use_bb, def_bb) + : DF_INSN_INFO_LUID (use_info) < DF_INSN_INFO_LUID (def_info)) + return false; + } + } + } + return true; +} + /* Find registers that are equivalent to a single value throughout the compilation (either because they can be referenced in memory or are set once from a single constant). Lower their priority for a @@ -3498,9 +3541,18 @@ update_equiv_regs (void) = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv[regno].init_insns); /* If this register is known to be equal to a constant, record that - it is always equivalent to the constant. */ + it is always equivalent to the constant. + Note that it is possible to have a register use before + the def in loops (see gcc.c-torture/execute/pr79286.c) + where the reg is undefined on first use. If the def insn + won't trap we can use it as an equivalence, effectively + choosing the "undefined" value for the reg to be the + same as the value set by the def. */ if (DF_REG_DEF_COUNT (regno) == 1 - && note && ! rtx_varies_p (XEXP (note, 0), 0)) + && note + && !rtx_varies_p (XEXP (note, 0), 0) + && (!may_trap_p (XEXP (note, 0)) + || def_dominates_uses (regno))) { rtx note_value = XEXP (note, 0); remove_note (insn, note); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 380457732e2..f7b64e30c2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-02-16 Alan Modra + + * gcc.c-torture/execute/pr79286.c: New. + 2017-02-16 Jakub Jelinek PR c++/79512 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79286.c b/gcc/testsuite/gcc.c-torture/execute/pr79286.c new file mode 100644 index 00000000000..e6d0e935a87 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr79286.c @@ -0,0 +1,15 @@ +int a = 0, c = 0; +static int d[][8] = {}; + +int main () +{ + int e; + for (int b = 0; b < 4; b++) + { + __builtin_printf ("%d\n", b, e); + while (a && c++) + e = d[300000000000000000][0]; + } + + return 0; +}