On Wed, 30 Oct 2019, Jakub Jelinek wrote:

> Hi!
> 
> As mentioned in the PR, while get_computation_at calls unshare_aff_combination
> and through that unshares the individual expressions, we then call
> aff_combination_to_tree which uses the fold-const.c APIs, and those do not
> guarantee the same non-shareable tree isn't used multiple times in the
> result, e.g. (a ? b : c) + d can be folded into a ? b + d : c + d and when
> say d is (cast) &whatever that will appear multiple times in the result.
> For debug stmts we are putting these expressions directly into the IL and so
> need to make sure there is no invalid tree sharing.  As since my patch we
> can try to compute the expressions even in cases where it won't be then used
> in the end, the following patch does the unsharing only immediately before
> putting it into the IL, and removes unsharing in get_debug_computation_at
> because it will be unshared anyway later.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2019-10-30  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/92262
>       * tree-ssa-loop-ivopts.c (get_debug_computation_at): Don't unshare
>       ubase or cbase here.
>       (remove_unused_ivs): Unshare comp before using it.
> 
>       * g++.dg/opt/pr92262.C: New test.
> 
> --- gcc/tree-ssa-loop-ivopts.c.jj     2019-10-23 14:35:42.994753407 +0200
> +++ gcc/tree-ssa-loop-ivopts.c        2019-10-29 09:45:47.418217336 +0100
> @@ -4152,8 +4152,6 @@ get_debug_computation_at (class loop *lo
>        var = fold_convert (ctype, var);
>      }
>  
> -  ubase = unshare_expr (ubase);
> -  cbase = unshare_expr (cbase);
>    if (stmt_after_increment (loop, cand, at))
>      var = fold_build2 (MINUS_EXPR, TREE_TYPE (var), var,
>                      unshare_expr (cstep));
> @@ -7648,6 +7646,7 @@ remove_unused_ivs (struct ivopts_data *d
>             if (!best_cand)
>               continue;
>  
> +           comp = unshare_expr (comp);
>             if (count > 1)
>               {
>                 tree vexpr = make_node (DEBUG_EXPR_DECL);
> --- gcc/testsuite/g++.dg/opt/pr92262.C.jj     2019-10-29 11:20:46.822901945 
> +0100
> +++ gcc/testsuite/g++.dg/opt/pr92262.C        2019-10-29 11:20:13.956410318 
> +0100
> @@ -0,0 +1,85 @@
> +// PR tree-optimization/92262
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-O2 -ftree-loop-distribution -g" }
> +
> +struct A;
> +struct B { template <typename T> using b = T *; };
> +template <typename, typename T> using c = B::b<T>;
> +void *operator new (__SIZE_TYPE__, void *p) { return p; }
> +struct C {
> +  template <typename T, typename... U> void
> +  foo (T *x, U... y) { new (x) T(y...); }
> +};
> +template <typename> class D : public C {};
> +template <typename> struct E;
> +template <typename T> struct E<D<T>> {
> +  using e = D<T>;
> +  template <typename U> using f = D<U>;
> +  template <typename U, typename... V>
> +  static void
> +  bar (e x, U y, V... z) { x.foo (y, z...); }
> +};
> +template <typename T> struct F : E<T> {
> +  template <typename U> struct G { typedef typename E<T>::template f<U> O; };
> +};
> +template <typename T, typename U, typename V> void
> +baz (T x, U y, V z)
> +{
> +  F<V>::bar (z, y, *x);
> +}
> +struct H {
> +  typedef c<int, A> I;
> +  typedef c<int, I> J;
> +  I i;
> +  J j;
> +  void qux (J x) { j = x; }
> +};
> +template <typename>
> +struct K {
> +  K(D<A> x) : k (x) {}
> +  typedef H::J L;
> +  struct M { L m; H n, o; };
> +  struct N : F<D<int>>::G<A>::O, M { N (F<D>::G<A>::O); };
> +  void quux ();
> +  N k;
> +};
> +template <typename T>
> +void
> +K<T>::quux ()
> +{
> +  L K (k.m - 1);
> +  k.n.qux (K);
> +}
> +template <typename, typename = int>
> +struct P : K<int> {
> +  template <typename T>
> +  P (T x, T, D<A> y = D<A> ()) : K (y) { corge (x); }
> +  template <typename T> void corge (T);
> +  typedef L L;
> +};
> +template <typename T, typename U>
> +template <typename V>
> +void P<T, U>::corge (V y)
> +{
> +  quux ();
> +  for (L x = k.n.j; x < k.o.j; ++x)
> +  {
> +    ++y;
> +    D<int> pv;
> +    baz (y, *x, pv);
> +  }
> +  D<int> z;
> +  baz (y, k.o.i, z);
> +}
> +struct A {
> +  A (int x) : a (x) {}
> +  int a;
> +};
> +int a[2]{};
> +
> +int
> +main ()
> +{
> +  P<int> (a, a);
> +  return 0;
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to