On 2024-09-27 06:31, Jakub Jelinek wrote:
On Fri, Sep 20, 2024 at 12:40:26PM -0400, Siddhesh Poyarekar wrote:
When wholesize != size, there is a reasonable opportunity for static
object sizes also to be computed using size_for_offset, so use that.

gcc/ChangeLog:

        * tree-object-size.cc (plus_stmt_object_size): Call
        SIZE_FOR_OFFSET for some negative offset cases.
        * testsuite/gcc.dg/builtin-object-size-3.c (test9): Adjust test.
        * testsuite/gcc.dg/builtin-object-size-4.c (test8): Likewise.
---
  gcc/testsuite/gcc.dg/builtin-object-size-3.c | 6 +++---
  gcc/testsuite/gcc.dg/builtin-object-size-4.c | 6 +++---
  gcc/tree-object-size.cc                      | 2 +-
  3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c 
b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
index 3f58da3d500..ec2c62c9640 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
@@ -574,7 +574,7 @@ test9 (unsigned cond)
    if (__builtin_object_size (&p[-4], 2) != (cond ? 6 : 10))
      FAIL ();
  #else
-  if (__builtin_object_size (&p[-4], 2) != 0)
+  if (__builtin_object_size (&p[-4], 2) != 6)
      FAIL ();
  #endif
@@ -585,7 +585,7 @@ test9 (unsigned cond)
    if (__builtin_object_size (p, 2) != ((cond ? 2 : 6) + cond))
      FAIL ();
  #else
-  if (__builtin_object_size (p, 2) != 0)
+  if (__builtin_object_size (p, 2) != 2)
      FAIL ();
  #endif
@@ -598,7 +598,7 @@ test9 (unsigned cond)
        != sizeof (y) - __builtin_offsetof (struct A, c) - 8 + cond)
      FAIL ();
  #else
-  if (__builtin_object_size (p, 2) != 0)
+  if (__builtin_object_size (p, 2) != sizeof (y) - __builtin_offsetof (struct 
A, c) - 8)
      FAIL ();
  #endif
  }
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c 
b/gcc/testsuite/gcc.dg/builtin-object-size-4.c
index b3eb36efb74..7bcd24c4150 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c
@@ -482,7 +482,7 @@ test8 (unsigned cond)
    if (__builtin_object_size (&p[-4], 3) != (cond ? 6 : 10))
      FAIL ();
  #else
-  if (__builtin_object_size (&p[-4], 3) != 0)
+  if (__builtin_object_size (&p[-4], 3) != 6)
      FAIL ();
  #endif
@@ -493,7 +493,7 @@ test8 (unsigned cond)
    if (__builtin_object_size (p, 3) != ((cond ? 2 : 6) + cond))
      FAIL ();
  #else
-  if (__builtin_object_size (p, 3) != 0)
+  if (__builtin_object_size (p, 3) != 2)
      FAIL ();
  #endif
@@ -505,7 +505,7 @@ test8 (unsigned cond)
    if (__builtin_object_size (p, 3) != sizeof (y.c) - 8 + cond)
      FAIL ();
  #else
-  if (__builtin_object_size (p, 3) != 0)
+  if (__builtin_object_size (p, 3) != sizeof (y.c) - 8)
      FAIL ();
  #endif
  }

The testcase changes look reasonable to me.

diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index 6544730e153..f8fae0cbc82 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -1527,7 +1527,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree 
var, gimple *stmt)
        if (size_unknown_p (bytes, 0))
        ;
        else if ((object_size_type & OST_DYNAMIC)
-              || compare_tree_int (op1, offset_limit) <= 0)
+              || bytes != wholesize || compare_tree_int (op1, offset_limit) <= 
0)
        bytes = size_for_offset (bytes, op1, wholesize);
        /* In the static case, with a negative offset, the best estimate for
         minimum size is size_unknown but for maximum size, the wholesize is a

The coding conventions say that in cases like this where the whole condition
doesn't fit on a single line, each ||/&& operand should be on a separate
line.
So, the patch should be adding || bytes != wholesize on a separate line.

That said, there is a pre-existing problem, the tree direct comparisons
(bytes != wholesize here, && wholesize != sz in size_for_offset (note,
again, it should be on a separate line), maybe others).

We do INTEGER_CST caching, either using small array for small values or
hash table for larger ones, so INTEGER_CSTs with the same value of the
same type should be pointer equal unless they are TREE_OVERFLOW or similar,
but for anything else, unless you guarantee that in the "same" case
you assign the same tree to size/wholesize rather than say
perform size_binop twice, I'd expect instead comparisons with
operand_equal_p or something similar.

Though, because this patch is solely for the __builtin_object_size case
and the sizes in that case should be solely INTEGER_CSTs, I guess this patch
is ok with the formatting nit fix (and ideally the one in size_for_offset
too).

Thanks, we basically pass the same object to sz and wholesize when there's no separate subobject, so the pointer equivalence should be sufficient. However I reckon could be a theoretical situation where a subobject size expression folds into being the same as a whole size, but I'm not sure if that'll actually happen in practice. I could take a closer look at that and fix it separately. It doesn't affect this patch though, as you said.

I've fixed the style nit and pushed this.

Thanks,
Sid

Reply via email to