aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/passes.def1
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/builtin-object-size-15.c27
-rw-r--r--gcc/testsuite/gcc.dg/pr64715-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr64715-2.c19
-rw-r--r--gcc/tree-object-size.c63
7 files changed, 135 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 34a2048..6a1a43f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/passes.def b/gcc/passes.def
index 2bc5dcd..c839b79 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5f78043..a0fb763 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..9701857
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-15.c
@@ -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
index 0000000..fbb6353
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64715-1.c
@@ -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
index 0000000..4c7b581
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64715-2.c
@@ -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" } } */
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 4b2c267..828a3d0 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -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)