re PR tree-optimization/64715 (__builtin_object_size (..., 1) fails to locate subobject)
authorJakub Jelinek <jakub@redhat.com>
Thu, 26 Mar 2015 13:19:59 +0000 (14:19 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 26 Mar 2015 13:19:59 +0000 (14:19 +0100)
PR tree-optimization/64715
* passes.def: Add another instance of pass_object_sizes before
ccp1.
* tree-object-size.c (pass_object_sizes::execute): In
first_pass_instance, only handle __bos (, 1) and __bos (, 3)
calls, and keep the call in the IL, as {MIN,MAX}_EXPR of the
__bos result and the computed constant.  Remove redundant
checks, obsoleted by gimple_call_builtin_p test.

* gcc.dg/builtin-object-size-15.c: New test.
* gcc.dg/pr64715-1.c: New test.
* gcc.dg/pr64715-2.c: New test.

From-SVN: r221694

gcc/ChangeLog
gcc/passes.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtin-object-size-15.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr64715-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr64715-2.c [new file with mode: 0644]
gcc/tree-object-size.c

index 34a2048f900d7ef9df954bc8e3b189ea0a793a9b..6a1a43fa2858083f52b186020e659dab14730e94 100644 (file)
@@ -1,5 +1,14 @@
 2015-03-26  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/64715
+       * passes.def: Add another instance of pass_object_sizes before
+       ccp1.
+       * tree-object-size.c (pass_object_sizes::execute): In
+       first_pass_instance, only handle __bos (, 1) and __bos (, 3)
+       calls, and keep the call in the IL, as {MIN,MAX}_EXPR of the
+       __bos result and the computed constant.  Remove redundant
+       checks, obsoleted by gimple_call_builtin_p test.
+
        * var-tracking.c (variable_tracking_main_1): Don't track
        variables for targetm.no_register_allocation targets.
 
index 2bc5dcd781fe77591883527ddd0e9705a521c9a0..c839b7984ca79bf9234f0719c63d61bde1148fdb 100644 (file)
@@ -77,6 +77,7 @@ along with GCC; see the file COPYING3.  If not see
       PUSH_INSERT_PASSES_WITHIN (pass_all_early_optimizations)
          NEXT_PASS (pass_remove_cgraph_callee_edges);
          NEXT_PASS (pass_rename_ssa_copies);
+         NEXT_PASS (pass_object_sizes);
          NEXT_PASS (pass_ccp);
          /* After CCP we rewrite no longer addressed locals into SSA
             form if possible.  */
index 5f78043cb65f2ee029db1b49fd97f3708c3399bf..a0fb7634d51279a3f56c5525b86566e93979059d 100644 (file)
@@ -1,3 +1,10 @@
+2015-03-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/64715
+       * gcc.dg/builtin-object-size-15.c: New test.
+       * gcc.dg/pr64715-1.c: New test.
+       * gcc.dg/pr64715-2.c: New test.
+
 2015-03-26  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/65519
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-15.c b/gcc/testsuite/gcc.dg/builtin-object-size-15.c
new file mode 100644 (file)
index 0000000..9701857
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+int
+main ()
+{
+  struct A { char buf1[9]; char buf2[1]; } a;
+
+  if (__builtin_object_size (a.buf1 + (0 + 4), 1) != 5)
+    abort ();
+  char *p = a.buf1;
+  p += 1;
+  p += 3;
+  if (__builtin_object_size (p, 1) != 5)
+    abort ();
+  p = (char *) &a;
+  char *q = p + 1;
+  char *r = q + 3;
+  char *t = r;
+  if (r != (char *) &a + 4)
+    t = (char *) &a + 1;
+  if (__builtin_object_size (t, 1) != 6)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr64715-1.c b/gcc/testsuite/gcc.dg/pr64715-1.c
new file mode 100644 (file)
index 0000000..fbb6353
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR tree-optimization/64715 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+extern inline __attribute__ ((always_inline, gnu_inline, artificial, nothrow, leaf)) char *
+strcpy (char *__restrict dest, const char *__restrict src)
+{
+  return __builtin___strcpy_chk (dest, src, __builtin_object_size (dest, 2 > 1));
+}
+
+const char *str1 = "JIHGFEDCBA";
+void bar (char *);
+
+void
+foo ()
+{
+  struct A { char buf1[9]; char buf2[1]; } a;
+  strcpy (a.buf1 + (0 + 4), str1 + 5);
+  bar ((char *) &a);
+}
+
+/* { dg-final { scan-tree-dump "__builtin___strcpy_chk\[^;\n\r\]*, 5\\\);" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr64715-2.c b/gcc/testsuite/gcc.dg/pr64715-2.c
new file mode 100644 (file)
index 0000000..4c7b581
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR tree-optimization/64715 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void bar (char *, int);
+
+void
+foo (int x)
+{
+  char p[16], *q;
+  q = p;
+  if (x)
+    q = p + 3;
+  __builtin___strcpy_chk (q, "abcdefghijkl", __builtin_object_size (q, 1));
+  bar (p, x);
+}
+
+/* { dg-final { scan-tree-dump "__builtin_memcpy \\\(\[^;\n\r\]*, \"abcdefghijkl\", 13\\\);" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index 4b2c26716cd9832d0ca8318d1c2ec95241818088..828a3d02dbc8d1ce4d890122b431f4b1dba0667a 100644 (file)
@@ -1268,25 +1268,60 @@ pass_object_sizes::execute (function *fun)
            continue;
 
          init_object_sizes ();
+
+         /* In the first pass instance, only attempt to fold
+            __builtin_object_size (x, 1) and __builtin_object_size (x, 3),
+            and rather than folding the builtin to the constant if any,
+            create a MIN_EXPR or MAX_EXPR of the __builtin_object_size
+            call result and the computed constant.  */
+         if (first_pass_instance)
+           {
+             tree ost = gimple_call_arg (call, 1);
+             if (tree_fits_uhwi_p (ost))
+               {
+                 unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
+                 tree ptr = gimple_call_arg (call, 0);
+                 tree lhs = gimple_call_lhs (call);
+                 if ((object_size_type == 1 || object_size_type == 3)
+                     && (TREE_CODE (ptr) == ADDR_EXPR
+                         || TREE_CODE (ptr) == SSA_NAME)
+                     && lhs)
+                   {
+                     tree type = TREE_TYPE (lhs);
+                     unsigned HOST_WIDE_INT bytes
+                       = compute_builtin_object_size (ptr, object_size_type);
+                     if (bytes != (unsigned HOST_WIDE_INT) (object_size_type == 1
+                                                            ? -1 : 0)
+                         && wi::fits_to_tree_p (bytes, type))
+                       {
+                         tree tem = make_ssa_name (type);
+                         gimple_call_set_lhs (call, tem);
+                         enum tree_code code
+                           = object_size_type == 1 ? MIN_EXPR : MAX_EXPR;
+                         tree cst = build_int_cstu (type, bytes);
+                         gimple g = gimple_build_assign (lhs, code, tem, cst);
+                         gsi_insert_after (&i, g, GSI_NEW_STMT);
+                         update_stmt (call);
+                       }
+                   }
+               }
+             continue;
+           }
+
          result = fold_call_stmt (as_a <gcall *> (call), false);
          if (!result)
            {
-             if (gimple_call_num_args (call) == 2
-                 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
+             tree ost = gimple_call_arg (call, 1);
+
+             if (tree_fits_uhwi_p (ost))
                {
-                 tree ost = gimple_call_arg (call, 1);
+                 unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
 
-                 if (tree_fits_uhwi_p (ost))
-                   {
-                     unsigned HOST_WIDE_INT object_size_type
-                       = tree_to_uhwi (ost);
-
-                     if (object_size_type < 2)
-                       result = fold_convert (size_type_node,
-                                              integer_minus_one_node);
-                     else if (object_size_type < 4)
-                       result = build_zero_cst (size_type_node);
-                   }
+                 if (object_size_type < 2)
+                   result = fold_convert (size_type_node,
+                                          integer_minus_one_node);
+                 else if (object_size_type < 4)
+                   result = build_zero_cst (size_type_node);
                }
 
              if (!result)