r16-1905-g7165ca43caf470 incorrectly returned the size of *_1 for a
GIMPLE_ASSIGN of type:

  ptr = *_1;

This is only OK when _1 is set to .ACCESS_WITH_SIZE, since that builtin
expresses the size of *_1 in the form of _1.

gcc/ChangeLog:

        * tree-object-size.cc (is_access_with_size): New function.
        (collect_object_sizes_for): Use it.

gcc/testsuite/ChangeLog:

        * gcc.dg/pr120929.c: New test case.

Signed-off-by: Siddhesh Poyarekar <siddh...@gotplt.org>
---

Bootstraps in progress.

 gcc/testsuite/gcc.dg/pr120929.c | 57 +++++++++++++++++++++++++++++++++
 gcc/tree-object-size.cc         | 40 ++++++++++++++++-------
 2 files changed, 86 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr120929.c

diff --git a/gcc/testsuite/gcc.dg/pr120929.c b/gcc/testsuite/gcc.dg/pr120929.c
new file mode 100644
index 00000000000..2730ca79062
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120929.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+#include "builtin-object-size-common.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+void
+__attribute__ ((noinline))
+pin_pointer(void *)
+{
+}
+
+struct magic_ {
+        char unused[9]; // at least 9
+};
+
+struct magic_map {
+        struct magic_ *magic;
+};
+
+static int
+coalesce_entries(struct magic_ **ma)
+{
+  size_t slen;
+
+  slen = sizeof (**ma);
+  *ma = __builtin_malloc (slen);
+
+  for (unsigned i = 0; i < 1; i++)
+    {
+      char b[1024] = {};
+      struct magic_ *ptr = *ma;
+      /* It should either give the correct size or fail graciously.  */
+      if (__builtin_dynamic_object_size (ptr, 0) != sizeof (**ma)
+         && __builtin_dynamic_object_size (ptr, 0) != (size_t) -1)
+       FAIL ();
+    }
+  return 0;
+}
+
+int
+main (void)
+{
+  char buf[128]; // did not shrink, but needs to be more than 100
+  struct magic_map *map2;
+
+  map2 = __builtin_malloc (sizeof (*map2));
+
+  pin_pointer(&buf);
+  coalesce_entries(&map2->magic);
+  pin_pointer(map2);
+
+  DONE ();
+
+  return 0;
+}
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index a551f2b4068..bfb0379430e 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -1858,6 +1858,20 @@ phi_dynamic_object_size (struct object_size_info *osi, 
tree var)
   object_sizes_set (osi, varno, sizes, wholesizes);
 }
 
+/* Return true if PTR is defined with .ACCESS_WITH_SIZE.  */
+
+static bool
+is_access_with_size (tree ptr)
+{
+  gcc_assert (TREE_CODE (ptr) == SSA_NAME);
+
+  gimple *stmt = SSA_NAME_DEF_STMT (ptr);
+  if (gimple_code (stmt) != GIMPLE_CALL)
+    return false;
+
+  return gimple_call_internal_p (as_a <gcall *> (stmt), IFN_ACCESS_WITH_SIZE);
+}
+
 /* Compute object sizes for VAR.
    For ADDR_EXPR an object size is the number of remaining bytes
    to the end of the object (where what is considered an object depends on
@@ -1941,20 +1955,24 @@ collect_object_sizes_for (struct object_size_info *osi, 
tree var)
         else if (gimple_assign_single_p (stmt)
                  || gimple_assign_unary_nop_p (stmt))
           {
+           /* If RHS is a MEM_REF of PTR with zero offset, the size may be
+              expressed with the .ACCESS_WITH_SIZE builtin in the form of
+              &PTR, so look for that if available.  This is the sample IR of
+              this situation:
+              1  _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B);
+              2  _5 = *_1;
+              3  _6 = __builtin_dynamic_object_size (_5, 1);
+              */
+           if (TREE_CODE (rhs) == MEM_REF
+               && POINTER_TYPE_P (TREE_TYPE (rhs))
+               && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
+               && integer_zerop (TREE_OPERAND (rhs, 1))
+               && is_access_with_size (TREE_OPERAND (rhs, 0)))
+             rhs = TREE_OPERAND (rhs, 0);
+
             if (TREE_CODE (rhs) == SSA_NAME
                 && POINTER_TYPE_P (TREE_TYPE (rhs)))
              reexamine = merge_object_sizes (osi, var, rhs);
-           /* Handle the following stmt #2 to propagate the size from the
-              stmt #1 to #3:
-               1  _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B);
-               2  _5 = *_1;
-               3  _6 = __builtin_dynamic_object_size (_5, 1);
-            */
-           else if (TREE_CODE (rhs) == MEM_REF
-                    && POINTER_TYPE_P (TREE_TYPE (rhs))
-                    && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
-                    && integer_zerop (TREE_OPERAND (rhs, 1)))
-             reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0));
             else
               expr_object_size (osi, var, rhs);
           }
-- 
2.50.0

Reply via email to