On Sat, Sep 14, 2024 at 5:31 AM Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > In PTR + OFFSET cases, try harder to see if the target offset could > result in a constant. Specifically, if the offset is a PHI node with > all constant branches, return the minimum (or maximum for OST_MINIMUM) > of the possible values. > > gcc/ChangeLog: > > PR tree-optimization/116556 > * tree-object-size.cc (try_collapsing_offset): New function. > (plus_stmt_object_size): Use it. > * gcc/testsuite/gcc.dg/builtin-object-size-1.c (test12): New > function. > (main): Call it. > > Signed-off-by: Siddhesh Poyarekar <siddh...@gotplt.org> > --- > Tests underway for x86_64 and i686. OK if they pass? > > gcc/testsuite/gcc.dg/builtin-object-size-1.c | 25 ++++++++++++ > gcc/tree-object-size.cc | 41 ++++++++++++++++++++ > 2 files changed, 66 insertions(+) > > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c > b/gcc/testsuite/gcc.dg/builtin-object-size-1.c > index d6d13c5ef7a..eed1653505c 100644 > --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c > @@ -712,6 +712,30 @@ test11 (void) > } > #endif > > +void > +__attribute__ ((noinline)) > +test12 (unsigned cond) > +{ > + char *buf2 = malloc (10); > + char *p; > + size_t t; > + > + if (cond) > + t = 8; > + else > + t = 4; > + > + p = &buf2[t]; > + > +#ifdef __builtin_object_size > + if (__builtin_object_size (p, 0) != (cond ? 2 : 6)) > + FAIL (); > +#else > + if (__builtin_object_size (p, 0) != 6) > + FAIL (); > +#endif > +} > + > int > main (void) > { > @@ -729,6 +753,7 @@ main (void) > test10 (); > #ifndef SKIP_STRNDUP > test11 (); > + test12 (1); > #endif > DONE (); > } > diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc > index 4c1fa9b555f..d90cc43fa97 100644 > --- a/gcc/tree-object-size.cc > +++ b/gcc/tree-object-size.cc > @@ -1467,6 +1467,44 @@ merge_object_sizes (struct object_size_info *osi, tree > dest, tree orig) > return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig)); > } > > +/* For constant sizes, try collapsing a non-constant offset to a constant if > + possible. The case handled at the moment is when the offset is a PHI node > + with all of its targets are constants. */ > + > +static tree > +try_collapsing_offset (tree op, int object_size_type) > +{ > + gcc_assert (!(object_size_type & OST_DYNAMIC)); > + > + if (TREE_CODE (op) != SSA_NAME) > + return op; > + > + gimple *stmt = SSA_NAME_DEF_STMT (op); > + > + if (gimple_code (stmt) != GIMPLE_PHI) > + return op; > + > + tree off = size_unknown (object_size_type); > + > + for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++) > + { > + tree rhs = gimple_phi_arg (stmt, i)->def; > + > + if (TREE_CODE (rhs) != INTEGER_CST) > + return op; > + > + /* Note that this is the *opposite* of what we usually do with sizes, > + because the maximum offset estimate here will give us a minimum size > + estimate and vice versa. */ > + enum tree_code code = (object_size_type & OST_MINIMUM > + ? MAX_EXPR : MIN_EXPR); > + > + off = size_binop (code, off, rhs);
I suspect this won't work for integer constants which have the what would be the sign bit set. That is: ``` void __attribute__ ((noinline)) test9 (unsigned cond) { char *buf2 = __builtin_malloc (10); char *p; __SIZE_TYPE__ t; if (cond) t = -4; else t = 4; p = &buf2[4] + t; if (__builtin_object_size (&p[0], 0) != 10) __builtin_abort (); } ``` Since you do the MIN/MAX in unsigned. Thanks, Andrew Pinski > + } > + > + gcc_assert (TREE_CODE (off) == INTEGER_CST); > + return off; > +} > > /* Compute object_sizes for VAR, defined to the result of an assignment > with operator POINTER_PLUS_EXPR. Return true if the object size might > @@ -1499,6 +1537,9 @@ plus_stmt_object_size (struct object_size_info *osi, > tree var, gimple *stmt) > if (object_sizes_unknown_p (object_size_type, varno)) > return false; > > + if (!(object_size_type & OST_DYNAMIC) && TREE_CODE (op1) != INTEGER_CST) > + op1 = try_collapsing_offset (op1, object_size_type); > + > /* Handle PTR + OFFSET here. */ > if (size_valid_p (op1, object_size_type) > && (TREE_CODE (op0) == SSA_NAME || TREE_CODE (op0) == ADDR_EXPR)) > -- > 2.45.1 >