re PR rtl-optimization/79286 (ira and lra wrong code at -O2 and -Os on i686-linux)

2017-02-16  Alan Modra  <amodra@gmail.com>

	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
This commit is contained in:
Alan Modra 2017-02-17 09:26:51 +10:30 committed by Jeff Law
parent 9b9ad3606d
commit a72b242eac
4 changed files with 80 additions and 2 deletions

View File

@ -1,3 +1,10 @@
2017-02-16 Alan Modra <amodra@gmail.com>
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 <vmakarov@redhat.com>
PR rtl-optimization/78127

View File

@ -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);

View File

@ -1,3 +1,7 @@
2017-02-16 Alan Modra <amodra@gmail.com>
* gcc.c-torture/execute/pr79286.c: New.
2017-02-16 Jakub Jelinek <jakub@redhat.com>
PR c++/79512

View File

@ -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;
}