OSDN Git Service

2013-02-04 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Feb 2013 12:04:35 +0000 (12:04 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Feb 2013 12:04:35 +0000 (12:04 +0000)
Backport from mainline
2012-07-04  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/53844
* tree-ssa-dse.c (dse_possible_dead_store_p): Properly handle
the loop virtual PHI.

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

2012-12-13  Richard Biener  <rguenther@suse.de>

PR lto/55660
* tree-streamer.c (record_common_node): Check that we are not
recursively pre-loading nodes we want to skip.  Handle
char_type_node appearing as part of va_list_type_node.

* gcc.dg/lto/pr55660_0.c: New testcase.
* gcc.dg/lto/pr55660_1.c: Likewise.

2013-02-04  Richard Biener  <rguenther@suse.de>

PR middle-end/55890
* gimple.h (gimple_call_builtin_class_p): New function.
* gimple.c (validate_call): New function.
(gimple_call_builtin_class_p): Likewise.
* tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
Use gimple_call_builtin_class_p.
(find_func_clobbers): Likewise.
* tree-ssa-strlen.c (adjust_last_stmt): Likewise.
(strlen_optimize_stmt): Likewise.

* gcc.dg/torture/pr55890-1.c: New testcase.
* gcc.dg/torture/pr55890-2.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@195708 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr53844.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/pr55660_0.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/pr55660_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr55890-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr55890-2.c [new file with mode: 0644]
gcc/tree-ssa-dse.c
gcc/tree-ssa-strlen.c
gcc/tree-ssa-structalias.c
gcc/tree-streamer.c

index 9b194d2..7fbdd5a 100644 (file)
@@ -1,3 +1,31 @@
+2013-02-04  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2012-07-04  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53844
+       * tree-ssa-dse.c (dse_possible_dead_store_p): Properly handle
+       the loop virtual PHI.
+
+       2012-12-13  Richard Biener  <rguenther@suse.de>
+
+       PR lto/55660
+       * tree-streamer.c (record_common_node): Check that we are not
+       recursively pre-loading nodes we want to skip.  Handle
+       char_type_node appearing as part of va_list_type_node.
+
+2013-02-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/55890
+       * gimple.h (gimple_call_builtin_class_p): New function.
+       * gimple.c (validate_call): New function.
+       (gimple_call_builtin_class_p): Likewise.
+       * tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
+       Use gimple_call_builtin_class_p.
+       (find_func_clobbers): Likewise.
+       * tree-ssa-strlen.c (adjust_last_stmt): Likewise.
+       (strlen_optimize_stmt): Likewise.
+
 2013-02-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
index 79596a4..1be04ae 100644 (file)
@@ -5464,16 +5464,61 @@ gimple_decl_printable_name (tree decl, int verbosity)
   return IDENTIFIER_POINTER (DECL_NAME (decl));
 }
 
-/* Return true when STMT is builtins call to CODE.  */
+/* Return true when STMTs arguments match those of FNDECL.  */
+
+static bool
+validate_call (gimple stmt, tree fndecl)
+{
+  tree arg, targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+  unsigned nargs = gimple_call_num_args (stmt);
+  unsigned i;
+  for (i = 0; i < nargs; ++i)
+    {
+      /* Variadic args follow.  */
+      if (!targs)
+       return true;
+      arg = gimple_call_arg (stmt, i);
+      if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
+         && INTEGRAL_TYPE_P (TREE_VALUE (targs)))
+       ;
+      else if (POINTER_TYPE_P (TREE_TYPE (arg))
+              && POINTER_TYPE_P (TREE_VALUE (targs)))
+       ;
+      else if (TREE_CODE (TREE_TYPE (arg))
+              != TREE_CODE (TREE_VALUE (targs)))
+       return false;
+      targs = TREE_CHAIN (targs);
+    }
+  if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
+    return false;
+  return true;
+}
+
+/* Return true when STMT is builtins call to CLASS.  */
+
+bool
+gimple_call_builtin_class_p (gimple stmt, enum built_in_class klass)
+{
+  tree fndecl;
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) == klass)
+    return validate_call (stmt, fndecl);
+  return false;
+}
+
+/* Return true when STMT is builtins call to CODE of CLASS.  */
 
 bool
 gimple_call_builtin_p (gimple stmt, enum built_in_function code)
 {
   tree fndecl;
-  return (is_gimple_call (stmt)
-         && (fndecl = gimple_call_fndecl (stmt)) != NULL
-         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-         && DECL_FUNCTION_CODE (fndecl) == code);
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 
+      && DECL_FUNCTION_CODE (fndecl) == code)
+    return validate_call (stmt, fndecl);
+  return false;
 }
 
 /* Return true if STMT clobbers memory.  STMT is required to be a
index 47e46b7..97eec59 100644 (file)
@@ -1023,6 +1023,7 @@ extern bool walk_stmt_load_store_ops (gimple, void *,
                                      bool (*)(gimple, tree, void *),
                                      bool (*)(gimple, tree, void *));
 extern bool gimple_ior_addresses_taken (bitmap, gimple);
+extern bool gimple_call_builtin_class_p (gimple, enum built_in_class);
 extern bool gimple_call_builtin_p (gimple, enum built_in_function);
 extern bool gimple_asm_clobbers_memory_p (const_gimple);
 
index 83a2243..762e61c 100644 (file)
@@ -1,3 +1,23 @@
+2013-02-04  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2012-07-04  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/53844
+       * g++.dg/tree-ssa/pr53844.C: New testcase.
+
+       2012-12-13  Richard Biener  <rguenther@suse.de>
+
+       PR lto/55660
+       * gcc.dg/lto/pr55660_0.c: New testcase.
+       * gcc.dg/lto/pr55660_1.c: Likewise.
+
+2013-02-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/55890
+       * gcc.dg/torture/pr55890-1.c: New testcase.
+       * gcc.dg/torture/pr55890-2.c: Likewise.
+
 2013-02-02  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        Backport from trunk
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr53844.C b/gcc/testsuite/g++.dg/tree-ssa/pr53844.C
new file mode 100644 (file)
index 0000000..0be29d8
--- /dev/null
@@ -0,0 +1,78 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized-vops" }
+
+struct VBase;
+
+//Very minimal numeric vector class where Base provides the policy
+template<typename Base=VBase>
+struct Vector : public Base{
+       
+       inline Vector(const Base& b)
+       :Base(b)
+       {
+       }
+
+       //Assignment from any other sort of Vector
+       template<typename Base2>
+       void operator= (const Vector<Base2>& from)
+       {
+               for(int i=0; i<100; i++){
+                       (*this)[i]=from[i];
+               }
+       }
+};
+
+
+//Base class to represent pointer as a Vector
+struct VBase{
+       double * const my_data;
+
+       double& operator[](int i) {
+               return my_data[i];
+       }
+
+       const double& operator[](int i) const {
+               return my_data[i];
+       }
+};
+
+//Base class providing very minimalistic expression template
+template<class B2> struct ScalarMulExpr
+{
+       const int& mul;
+       const Vector<B2>& vec;
+
+       int size() const
+       {
+               return vec.size();
+       }
+
+       double operator[](int i) const
+       {
+               return vec[i]*mul;
+       }
+
+       ScalarMulExpr(const Vector<B2>& vec_, const int& m)
+       :mul(m),vec(vec_)
+       {
+       }
+};
+
+//Allow vector to be multiplied by a scalar
+template<class B2>
+Vector<ScalarMulExpr<B2> > operator*(const Vector<B2>& lhs, const int& rhs)
+{
+       return ScalarMulExpr<B2>(lhs, rhs);
+}
+
+//Test function producing suboptimal asm code
+void test(const Vector<>& in, Vector<>& out, int i)
+{
+       out=in*1*1*1*1*1*1*1*1*1*1*1;
+}
+
+// There should be a single store remaining, inside the loops.  All
+// dead stores to unused temporaries should have been removed.
+
+// { dg-final { scan-tree-dump-times "VDEF" 1 "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/lto/pr55660_0.c b/gcc/testsuite/gcc.dg/lto/pr55660_0.c
new file mode 100644 (file)
index 0000000..7e7bb2f
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-lto-do run } */
+/* { dg-extra-ld-options { -funsigned-char } } */
+
+char n[3] = {'a','b','c'};
+int foo(char *x)
+{
+  if (*x == 'b')
+    return (int)*x;
+  *x = 'y';
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr55660_1.c b/gcc/testsuite/gcc.dg/lto/pr55660_1.c
new file mode 100644 (file)
index 0000000..a8c368b
--- /dev/null
@@ -0,0 +1,15 @@
+extern int foo (char*);
+extern void abort (void);
+
+extern char n[3];
+
+int main ()
+{
+  int i, m = 0;
+  for (i = 0; i < 3; i++)
+    m += foo(&n[i]);
+
+  if (m != 'b')
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr55890-1.c b/gcc/testsuite/gcc.dg/torture/pr55890-1.c
new file mode 100644 (file)
index 0000000..9fd558e
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+extern void *memmove(void *, void *, __SIZE_TYPE__);
+typedef int (*_TEST_fun_) ();
+static _TEST_fun_ i = (_TEST_fun_) memmove;
+main() { i(); }
diff --git a/gcc/testsuite/gcc.dg/torture/pr55890-2.c b/gcc/testsuite/gcc.dg/torture/pr55890-2.c
new file mode 100644 (file)
index 0000000..a753e57
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-do compile } */\r
+\r
+extern void *memcpy();\r
+main() { memcpy(); }\r
index 285d08c..c80d9c9 100644 (file)
@@ -94,7 +94,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
   temp = stmt;
   do
     {
-      gimple use_stmt;
+      gimple use_stmt, defvar_def;
       imm_use_iterator ui;
       bool fail = false;
       tree defvar;
@@ -108,6 +108,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
        defvar = PHI_RESULT (temp);
       else
        defvar = gimple_vdef (temp);
+      defvar_def = temp;
       temp = NULL;
       FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
        {
@@ -139,7 +140,14 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
                  fail = true;
                  BREAK_FROM_IMM_USE_STMT (ui);
                }
-             temp = use_stmt;
+             /* Do not consider the PHI as use if it dominates the 
+                stmt defining the virtual operand we are processing,
+                we have processed it already in this case.  */
+             if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
+                 && !dominated_by_p (CDI_DOMINATORS,
+                                     gimple_bb (defvar_def),
+                                     gimple_bb (use_stmt)))
+               temp = use_stmt;
            }
          /* If the statement is a use the store is not dead.  */
          else if (ref_maybe_used_by_stmt_p (use_stmt,
index a37633a..304c294 100644 (file)
@@ -812,10 +812,10 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat)
 
   if (!is_gimple_call (last.stmt))
     return;
-  callee = gimple_call_fndecl (last.stmt);
-  if (callee == NULL_TREE || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
+  if (!gimple_call_builtin_class_p (last.stmt, BUILT_IN_NORMAL))
     return;
 
+  callee = gimple_call_fndecl (last.stmt);
   switch (DECL_FUNCTION_CODE (callee))
     {
     case BUILT_IN_MEMCPY:
@@ -1753,7 +1753,7 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi)
   if (is_gimple_call (stmt))
     {
       tree callee = gimple_call_fndecl (stmt);
-      if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+      if (gimple_call_builtin_class_p (stmt, BUILT_IN_NORMAL))
        switch (DECL_FUNCTION_CODE (callee))
          {
          case BUILT_IN_STRLEN:
index 9c58349..0d4258d 100644 (file)
@@ -4029,8 +4029,7 @@ find_func_aliases_for_builtin_call (gimple t)
   VEC(ce_s, heap) *rhsc = NULL;
   varinfo_t fi;
 
-  if (fndecl != NULL_TREE
-      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+  if (gimple_call_builtin_class_p (t, BUILT_IN_NORMAL))
     /* ???  All builtins that are handled here need to be handled
        in the alias-oracle query functions explicitly!  */
     switch (DECL_FUNCTION_CODE (fndecl))
@@ -4771,8 +4770,7 @@ find_func_clobbers (gimple origt)
 
       /* For builtins we do not have separate function info.  For those
         we do not generate escapes for we have to generate clobbers/uses.  */
-      if (decl
-         && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+      if (gimple_call_builtin_class_p (t, BUILT_IN_NORMAL))
        switch (DECL_FUNCTION_CODE (decl))
          {
          /* The following functions use and clobber memory pointed to
index 94d540b..8e0a917 100644 (file)
@@ -251,6 +251,16 @@ streamer_tree_cache_get (struct streamer_tree_cache_d *cache, unsigned ix)
 static void
 record_common_node (struct streamer_tree_cache_d *cache, tree node)
 {
+  /* If we recursively end up at nodes we do not want to preload simply don't.
+     ???  We'd want to verify that this doesn't happen, or alternatively
+     do not recurse at all.  */
+  if (node == char_type_node)
+    return;
+
+  gcc_checking_assert (node != boolean_type_node
+                      && node != boolean_true_node
+                      && node != boolean_false_node);
+
   /* We have to make sure to fill exactly the same number of
      elements for all frontends.  That can include NULL trees.
      As our hash table can't deal with zero entries we'll simply stream