On Thu, May 7, 2020 at 6:27 PM Alexandre Oliva <ol...@adacore.com> wrote:
>
>
> gnat.dg/opt83.adb compiled with -O2+ would enter an infinite loop with
> memory allocation within fre.  I don't think there is anything
> Ada-specific in the bug, but the exact inlining and loop unrolling
> circumstances needed to trigger the bug are quite fragile, so I didn't
> try very hard to translate it to C.
>
> The problem comes about while attempting to eliminate the last of the
> following stmts, generated for 'R (0) := F;':
>
>   A78b_144 = MEM <struct opt83__e[/*...*/]> [(struct opt83__e &)_41][0]{lb: 
> _46 sz: 16}._tag;
>   MEM <struct opt83__e[/*...*/]> [(struct opt83__e &)_41][0]{lb: _46 sz: 16} 
> = f;
>   MEM <struct opt83__e[/*...*/]> [(struct opt83__e &)_41][0]{lb: _46 sz: 
> 16}._tag = A78b_144;
>
> valueize_refs_1 takes a sequence of vn_reference_op_s with _41 in it, and
> when it gets to that op, vn_valueize = rpo_vn_valueize replaces _41 with
> _47, defined in the previous block as:
>
>   _47 = &(*_41)[0]{lb: _46 sz: 16};
>
> _47 is the first argument passed to the function synthesized to copy F
> to the first element of array R, after checking that their addresses
> do not compare equal.
>
> There is another earlier def in the Value Numbering set associated with
> _41, namely:
>
>   _164 = &MEM[(struct ALLOC *)_163].ARRAY;
>
> _163 is the newly-allocated storage for the 0..4 array.  Unfortunately
> the logic in rpo_vn_valueize selects the former, and then we add the
> _47 definition in _41's place in the op sequence.  Problem is _41 is
> part of the expression, and thus of the expansion, so eventually we
> reach it and replace it again, and again, and at every cycle we add
> more ops than we remove, so the sequence grows unbounded.

So value-numbering value-numbered _41 and _47 the same which
looks sensible only if _46 is zero.  But at the _47 definition we should
not have recorded _47 as another available name for _41 so we should
not have valueized to _47.

I'll try to debug this myself, the proposed patch looks wrong to me.

Richard.

>
> Limiting the selection of alternate defs for the value to those that
> dominate the def we're replacing should be enough to avoid the
> problem, since we'd only perform replacements "up" the CFG.  Changing
> the BB context for the selection of the value equivalence to that of
> the name we're replacing, rather than that of the expression in which
> we're replacing it, seems to be close enough.  It does solve the
> problem without any codegen changes in a GCC bootstrap, despite a few
> differences in eliminate_avail.
>
> Regstrapped on x86_64-linux-gnu.  Ok to install?
>
> As I prepare to post this, it occurs to me that maybe, instead of using
> vn_context_bb for a default NAME like before, we should abandon the
> attempt to substitute it, lest we might run into the same kind of
> infinite loop in for e.g. _41(D).  WDYT?
>
>
> for  gcc/ChangeLog
>
>         * tree-ssa-sccvn.c (rpo_vn_valueize): Take the BB context from
>         NAME.
>
> for  gcc/testsuite/ChangeLog
>
>         * gnat.dg/opt83.adb: New.
> ---
>  gcc/testsuite/gnat.dg/opt83.adb |   33 +++++++++++++++++++++++++++++++++
>  gcc/tree-ssa-sccvn.c            |    7 ++++++-
>  2 files changed, 39 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gnat.dg/opt83.adb
>
> diff --git a/gcc/testsuite/gnat.dg/opt83.adb b/gcc/testsuite/gnat.dg/opt83.adb
> new file mode 100644
> index 00000000..7418520
> --- /dev/null
> +++ b/gcc/testsuite/gnat.dg/opt83.adb
> @@ -0,0 +1,33 @@
> +--  { dg-do compile }
> +--  { dg-options "-O2" }
> +
> +--  rpo fre3 used to loop indefinitely replacing _2 with _8 and back,
> +--  given MEM[(struct test__e &)_2][0]{lb: _7 sz: 16}._tag = A23s_29;
> +--  and an earlier _8 = &*_2[0]{lb: _7 sz: 16}.
> +
> +procedure Opt83 is
> +
> +   type E is tagged record
> +      I : Natural := 0;
> +   end record;
> +
> +   type A is array (Natural range <>) of aliased E;
> +
> +   F : E;
> +
> +   R : access A;
> +
> +   procedure N is
> +   begin
> +      if R = null then
> +        R := new A (0 .. 4);
> +      end if;
> +   end N;
> +
> +begin
> +
> +   N;
> +
> +   R (0) := F;
> +
> +end Opt83;
> diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
> index 8a4af91..9008724 100644
> --- a/gcc/tree-ssa-sccvn.c
> +++ b/gcc/tree-ssa-sccvn.c
> @@ -6790,9 +6790,14 @@ rpo_vn_valueize (tree name)
>             {
>               if (TREE_CODE (tem) != SSA_NAME)
>                 return tem;
> +             basic_block bb = vn_context_bb;
> +             /* Avoid replacing name with anything whose definition
> +                could refer back to name.  */
> +             if (! SSA_NAME_IS_DEFAULT_DEF (name))
> +               bb = gimple_bb (SSA_NAME_DEF_STMT (name));
>               /* For all values we only valueize to an available leader
>                  which means we can use SSA name info without restriction.  */
> -             tem = rpo_avail->eliminate_avail (vn_context_bb, tem);
> +             tem = rpo_avail->eliminate_avail (bb, tem);
>               if (tem)
>                 return tem;
>             }
>
> --
> Alexandre Oliva, freedom fighter    he/him    https://FSFLA.org/blogs/lxo/
> Free Software Evangelist              Stallman was right, but he's left :(
> GNU Toolchain Engineer           Live long and free, and prosper ethically

Reply via email to