]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/61034 (Optimizing takes too many passes)
authorRichard Biener <rguenther@suse.de>
Wed, 7 May 2014 14:19:14 +0000 (14:19 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 7 May 2014 14:19:14 +0000 (14:19 +0000)
2014-05-07  Richard Biener  <rguenther@suse.de>

PR tree-optimization/61034
* tree-ssa-alias.c (call_may_clobber_ref_p_1): Export.
(maybe_skip_until): Use translate to take into account
lattices when trying to do disambiguations.
(get_continuation_for_phi_1): Likewise.
(get_continuation_for_phi): Adjust for added translate
arguments.
(walk_non_aliased_vuses): Likewise.
* tree-ssa-alias.h (get_continuation_for_phi): Adjust
prototype.
(walk_non_aliased_vuses): Likewise.
(call_may_clobber_ref_p_1): Declare.
* tree-ssa-sccvn.c (vn_reference_lookup_3): Also
disambiguate against calls.  Stop early if we are
only supposed to disambiguate.
* tree-ssa-pre.c (translate_vuse_through_block): Adjust.

* g++.dg/tree-ssa/pr61034.C: New testcase.

From-SVN: r210160

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr61034.C [new file with mode: 0644]
gcc/tree-ssa-alias.c
gcc/tree-ssa-alias.h
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c

index 4532bd52262a251adac3579b09568bf1a0b3881b..afac89bf1d73af0cc8247e52f07939566d8d4ce1 100644 (file)
@@ -1,3 +1,22 @@
+2014-05-07  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/61034
+       * tree-ssa-alias.c (call_may_clobber_ref_p_1): Export.
+       (maybe_skip_until): Use translate to take into account
+       lattices when trying to do disambiguations.
+       (get_continuation_for_phi_1): Likewise.
+       (get_continuation_for_phi): Adjust for added translate
+       arguments.
+       (walk_non_aliased_vuses): Likewise.
+       * tree-ssa-alias.h (get_continuation_for_phi): Adjust
+       prototype.
+       (walk_non_aliased_vuses): Likewise.
+       (call_may_clobber_ref_p_1): Declare.
+       * tree-ssa-sccvn.c (vn_reference_lookup_3): Also
+       disambiguate against calls.  Stop early if we are
+       only supposed to disambiguate.
+       * tree-ssa-pre.c (translate_vuse_through_block): Adjust.
+
 2014-05-07  Joern Rennecke  <joern.rennecke@embecosm.com>
 
        * config/epiphany/epiphany.c (epiphany_handle_interrupt_attribute):
index 2925e328728e84e9e59fa8bb953349917d86218b..723967fa3bbf63e762aabd0a65a1b4dad2c34979 100644 (file)
@@ -1,3 +1,8 @@
+2014-05-07  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/61034
+       * g++.dg/tree-ssa/pr61034.C: New testcase.
+
 2014-05-07  Joern Rennecke  <joern.rennecke@embecosm.com>
 
        * gcc.target/epiphany/isr-arg.c: New file.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
new file mode 100644 (file)
index 0000000..fe09df3
--- /dev/null
@@ -0,0 +1,45 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-fre2" }
+
+#define assume(x) if(!(x))__builtin_unreachable()
+
+inline void* operator new(__SIZE_TYPE__ n){ return __builtin_malloc(n); }
+inline void operator delete(void *p) { __builtin_free(p); }
+struct O {
+    double num;
+    int count;
+};
+struct I {
+    O *o;
+    I(double d = 0) : o (new O) { o->num = d; o->count = 1; }
+    I(I const&i) { assume(i.o->count >= 1); o = i.o; ++o->count; }
+    I& operator=(I const&i) { I(i).swap(*this); return *this; }
+    ~I() { if (--o->count == 0) delete o; }
+    void swap(I& i) { O *tmp = o; o = i.o; i.o = tmp; }
+    I& operator*= (I const&i) {
+       if (o->count > 1) *this = I(o->num);
+       o->num *= i.o->num;
+       return *this;
+    }
+    I& operator-= (I const&i) {
+       if (o->count > 1) *this = I(o->num);
+       o->num -= i.o->num;
+       return *this;
+    }
+};
+inline I operator* (I a, I const&b) { return a *= b; }
+inline I operator- (I a, I const&b) { return a -= b; }
+inline bool operator< (I const&a, I const&b) { return a.o->num < b.o->num; }
+
+bool f(I a, I b, I c, I d) {
+    return (a * d - b * c) * (a * b - c * d) < 42;
+}
+
+// We should be able to CSE most references to count and thus remove
+// a bunch of conditional free()s and unreachable()s.
+// This works only if everything is inlined into 'f'.
+
+// { dg-final { scan-tree-dump-times ";; Function" 1 "fre2" } }
+// { dg-final { scan-tree-dump-times "free" 19 "fre2" } }
+// { dg-final { scan-tree-dump-times "unreachable" 11 "fre2" } }
+// { dg-final { cleanup-tree-dump "fre2" } }
index 7781d63226657d2d43ed79f6a09fdc7df9e6b45e..479fa9ce0f012108971836fae6e331b817a95dcd 100644 (file)
@@ -1835,7 +1835,7 @@ ref_maybe_used_by_stmt_p (gimple stmt, tree ref)
 /* If the call in statement CALL may clobber the memory reference REF
    return true, otherwise return false.  */
 
-static bool
+bool
 call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
 {
   tree base;
@@ -2318,7 +2318,9 @@ stmt_kills_ref_p (gimple stmt, tree ref)
 static bool
 maybe_skip_until (gimple phi, tree target, ao_ref *ref,
                  tree vuse, unsigned int *cnt, bitmap *visited,
-                 bool abort_on_visited)
+                 bool abort_on_visited,
+                 void *(*translate)(ao_ref *, tree, void *, bool),
+                 void *data)
 {
   basic_block bb = gimple_bb (phi);
 
@@ -2338,7 +2340,8 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
          if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
            return !abort_on_visited;
          vuse = get_continuation_for_phi (def_stmt, ref, cnt,
-                                          visited, abort_on_visited);
+                                          visited, abort_on_visited,
+                                          translate, data);
          if (!vuse)
            return false;
          continue;
@@ -2350,7 +2353,13 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
          /* A clobbering statement or the end of the IL ends it failing.  */
          ++*cnt;
          if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
-           return false;
+           {
+             if (translate
+                 && (*translate) (ref, vuse, data, true) == NULL)
+               ;
+             else
+               return false;
+           }
        }
       /* If we reach a new basic-block see if we already skipped it
          in a previous walk that ended successfully.  */
@@ -2372,7 +2381,9 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
 static tree
 get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
                            ao_ref *ref, unsigned int *cnt,
-                           bitmap *visited, bool abort_on_visited)
+                           bitmap *visited, bool abort_on_visited,
+                           void *(*translate)(ao_ref *, tree, void *, bool),
+                           void *data)
 {
   gimple def0 = SSA_NAME_DEF_STMT (arg0);
   gimple def1 = SSA_NAME_DEF_STMT (arg1);
@@ -2386,7 +2397,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
                                  gimple_bb (def1), gimple_bb (def0))))
     {
       if (maybe_skip_until (phi, arg0, ref, arg1, cnt,
-                           visited, abort_on_visited))
+                           visited, abort_on_visited, translate, data))
        return arg0;
     }
   else if (gimple_nop_p (def1)
@@ -2394,7 +2405,7 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
                              gimple_bb (def0), gimple_bb (def1)))
     {
       if (maybe_skip_until (phi, arg1, ref, arg0, cnt,
-                           visited, abort_on_visited))
+                           visited, abort_on_visited, translate, data))
        return arg1;
     }
   /* Special case of a diamond:
@@ -2414,8 +2425,12 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
           && common_vuse == gimple_vuse (def1))
     {
       *cnt += 2;
-      if (!stmt_may_clobber_ref_p_1 (def0, ref)
-         && !stmt_may_clobber_ref_p_1 (def1, ref))
+      if ((!stmt_may_clobber_ref_p_1 (def0, ref)
+          || (translate
+              && (*translate) (ref, arg0, data, true) == NULL))
+         && (!stmt_may_clobber_ref_p_1 (def1, ref)
+             || (translate
+                 && (*translate) (ref, arg1, data, true) == NULL)))
        return common_vuse;
     }
 
@@ -2432,7 +2447,9 @@ get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
 tree
 get_continuation_for_phi (gimple phi, ao_ref *ref,
                          unsigned int *cnt, bitmap *visited,
-                         bool abort_on_visited)
+                         bool abort_on_visited,
+                         void *(*translate)(ao_ref *, tree, void *, bool),
+                         void *data)
 {
   unsigned nargs = gimple_phi_num_args (phi);
 
@@ -2470,7 +2487,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref,
        {
          arg1 = PHI_ARG_DEF (phi, i);
          arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
-                                            cnt, visited, abort_on_visited);
+                                            cnt, visited, abort_on_visited,
+                                            translate, data);
          if (!arg0)
            return NULL_TREE;
        }
@@ -2502,7 +2520,8 @@ get_continuation_for_phi (gimple phi, ao_ref *ref,
 void *
 walk_non_aliased_vuses (ao_ref *ref, tree vuse,
                        void *(*walker)(ao_ref *, tree, unsigned int, void *),
-                       void *(*translate)(ao_ref *, tree, void *), void *data)
+                       void *(*translate)(ao_ref *, tree, void *, bool),
+                       void *data)
 {
   bitmap visited = NULL;
   void *res;
@@ -2532,7 +2551,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
        break;
       else if (gimple_code (def_stmt) == GIMPLE_PHI)
        vuse = get_continuation_for_phi (def_stmt, ref, &cnt,
-                                        &visited, translated);
+                                        &visited, translated, translate, data);
       else
        {
          cnt++;
@@ -2540,7 +2559,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
            {
              if (!translate)
                break;
-             res = (*translate) (ref, vuse, data);
+             res = (*translate) (ref, vuse, data, false);
              /* Failed lookup and translation.  */
              if (res == (void *)-1)
                {
index 3544aafca838d03f80bb511ff1c944bc09707ed1..c0b472bd3bef9d6dbda99e3920b6cb8edf68f182 100644 (file)
@@ -110,13 +110,17 @@ extern bool stmt_may_clobber_global_p (gimple);
 extern bool stmt_may_clobber_ref_p (gimple, tree);
 extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
 extern bool call_may_clobber_ref_p (gimple, tree);
+extern bool call_may_clobber_ref_p_1 (gimple, ao_ref *);
 extern bool stmt_kills_ref_p (gimple, tree);
 extern tree get_continuation_for_phi (gimple, ao_ref *,
-                                     unsigned int *, bitmap *, bool);
+                                     unsigned int *, bitmap *, bool,
+                                     void *(*)(ao_ref *, tree, void *, bool),
+                                     void *);
 extern void *walk_non_aliased_vuses (ao_ref *, tree,
                                     void *(*)(ao_ref *, tree,
                                               unsigned int, void *),
-                                    void *(*)(ao_ref *, tree, void *), void *);
+                                    void *(*)(ao_ref *, tree, void *, bool),
+                                    void *);
 extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
                                        bool (*)(ao_ref *, tree, void *),
                                        void *, bitmap *);
index 95e3af98238ac3b3ac660ff2938198d37b49d04e..f634f5efd29e076a18829673407eb683b62ae6de 100644 (file)
@@ -1308,7 +1308,8 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands,
          unsigned int cnt;
          /* Try to find a vuse that dominates this phi node by skipping
             non-clobbering statements.  */
-         vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false);
+         vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false,
+                                          NULL, NULL);
          if (visited)
            BITMAP_FREE (visited);
        }
index 585fd85049c78fa7817a05533226e53e7c984a4b..05a5fe8e73f6c7770693200f1e2073ac65959241 100644 (file)
@@ -1542,7 +1542,8 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse,
    of VUSE.  */
 
 static void *
-vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
+vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
+                      bool disambiguate_only)
 {
   vn_reference_t vr = (vn_reference_t)vr_;
   gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
@@ -1580,6 +1581,39 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
          lhs_ref_ok = true;
        }
     }
+  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL)
+          && gimple_call_num_args (def_stmt) <= 4)
+    {
+      /* For builtin calls valueize its arguments and call the
+         alias oracle again.  Valueization may improve points-to
+        info of pointers and constify size and position arguments.
+        Originally this was motivated by PR61034 which has
+        conditional calls to free falsely clobbering ref because
+        of imprecise points-to info of the argument.  */
+      tree oldargs[4];
+      bool valueized_anything;
+      for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
+       {
+         oldargs[i] = gimple_call_arg (def_stmt, i);
+         if (TREE_CODE (oldargs[i]) == SSA_NAME
+             && VN_INFO (oldargs[i])->valnum != oldargs[i])
+           {
+             gimple_call_set_arg (def_stmt, i, VN_INFO (oldargs[i])->valnum);
+             valueized_anything = true;
+           }
+       }
+      if (valueized_anything)
+       {
+         bool res = call_may_clobber_ref_p_1 (def_stmt, ref);
+         for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
+           gimple_call_set_arg (def_stmt, i, oldargs[i]);
+         if (!res)
+           return NULL;
+       }
+    }
+
+  if (disambiguate_only)
+    return (void *)-1;
 
   base = ao_ref_base (ref);
   offset = ref->offset;