On Sat, 7 Dec 2024, Siddhesh Poyarekar wrote:

> On 2024-12-05 05:37, Richard Biener wrote:
> > VN again is the culprit for exploiting address equivalences before
> > __builtin_object_size got the chance to do its job.  This time
> > it isn't about union members but adjacent structure fields where
> > an address to one after the last element of an array field can
> > spill over to the next field.
> > 
> > The following protects all out-of-bound accesses on the upper bound
> > side (singling out TYPE_MAX_VALUE + 1 is more expensive).  It
> > ignores other out-of-bound addresses that would invoke UB.
> > 
> > Zero-sized arrays are a bit awkward because the C++ represents them
> > with a -1U upper bound.
> > 
> > There's a similar issue for zero-sized components whose address can
> > be the same as the adjacent field in C.
> > 
> > Bootstrap and regtest running on x86_64-unknown-linux-gnu.
> > 
> > Does this look OK?
> 
> I can't approve of course, but the fix looks correct to me module a comment
> typo nit below.

Sure - fixed the comments.  I'm still waiting on Jakubs OK though.

Thanks,
Richard.

> Thanks,
> Sid
> 
> > We possbly want to have a zero_size_domain_p () function, or clean up
> > the zero-size mess - I refrained from dealing with this in this patch.
> > 
> > Richard.
> > 
> >  PR tree-optimization/117912
> >  * tree-ssa-sccvn.cc (copy_reference_ops_from_ref): For addresses
> >  of zero-sized components do not set ->off if the object size pass
> >  didn't run.
> >  For OOB ARRAY_REF accesses in address expressions avoid setting
> >  ->off if the object size pass didn't run.
> >  (valueize_refs_1): Likewise.
> > 
> >  * c-c++-common/torture/pr117912-1.c: New testcase.
> >  * c-c++-common/torture/pr117912-2.c: Likewise.
> >  * gcc.dg/torture/pr117912-3.c: Likewise.
> > ---
> >   .../c-c++-common/torture/pr117912-1.c         | 28 +++++++++++
> >   .../c-c++-common/torture/pr117912-2.c         | 28 +++++++++++
> >   gcc/testsuite/gcc.dg/torture/pr117912-3.c     | 18 +++++++
> >   gcc/tree-ssa-sccvn.cc                         | 47 +++++++++++++++++--
> >   4 files changed, 118 insertions(+), 3 deletions(-)
> >   create mode 100644 gcc/testsuite/c-c++-common/torture/pr117912-1.c
> >   create mode 100644 gcc/testsuite/c-c++-common/torture/pr117912-2.c
> >   create mode 100644 gcc/testsuite/gcc.dg/torture/pr117912-3.c
> > 
> > diff --git a/gcc/testsuite/c-c++-common/torture/pr117912-1.c
> > b/gcc/testsuite/c-c++-common/torture/pr117912-1.c
> > new file mode 100644
> > index 00000000000..2750585c7f7
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/torture/pr117912-1.c
> > @@ -0,0 +1,28 @@
> > +/* { dg-do run } */
> > +
> > +struct S { int a; int b[24]; int c[24]; int d; };
> > +volatile int *p;
> > +
> > +void __attribute__((noipa))
> > +bar (int *q)
> > +{
> > + p = q;
> > +}
> > +
> > +__SIZE_TYPE__ __attribute__((noipa))
> > +foo (struct S *p)
> > +{
> > +  bar (&p->b[24]);
> > +  bar (&p->c[0]);
> > +  return __builtin_object_size (&p->c[0], 1);
> > +}
> > +
> > +int
> > +main()
> > +{
> > +  struct S s;
> > +  __SIZE_TYPE__ x = foo (&s);
> > +  if (x < sizeof (int) * 24)
> > +    __builtin_abort ();
> > +  return 0;
> > +}
> > diff --git a/gcc/testsuite/c-c++-common/torture/pr117912-2.c
> > b/gcc/testsuite/c-c++-common/torture/pr117912-2.c
> > new file mode 100644
> > index 00000000000..a3a62157563
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/torture/pr117912-2.c
> > @@ -0,0 +1,28 @@
> > +/* { dg-do run } */
> > +
> > +struct S { int a; int b[0]; int c[24]; int d; };
> > +volatile int *p;
> > +
> > +void __attribute__((noipa))
> > +bar (int *q)
> > +{
> > + p = q;
> > +}
> > +
> > +__SIZE_TYPE__ __attribute__((noipa))
> > +foo (struct S *p)
> > +{
> > +  bar (&p->b[0]);
> > +  bar (&p->c[0]);
> > +  return __builtin_object_size (&p->c[0], 1);
> > +}
> > +
> > +int
> > +main()
> > +{
> > +  struct S s;
> > +  __SIZE_TYPE__ x = foo (&s);
> > +  if (x < sizeof (int) * 24)
> > +    __builtin_abort ();
> > +  return 0;
> > +}
> > diff --git a/gcc/testsuite/gcc.dg/torture/pr117912-3.c
> > b/gcc/testsuite/gcc.dg/torture/pr117912-3.c
> > new file mode 100644
> > index 00000000000..b4a036439c3
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/torture/pr117912-3.c
> > @@ -0,0 +1,18 @@
> > +/* { dg-do link } */
> > +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
> > +
> > +long s;
> > +struct A * __attribute__((noipa)) foo (void) {}
> > +struct B {};
> > +struct B __attribute__((noipa)) bar (struct B *) {}
> > +void baz (void) __attribute__((__error__ ("baz")));
> > +struct A { int a; struct B b; char c[]; };
> > +int
> > +main ()
> > +{
> > +  struct A *p = foo ();
> > +  bar (&p->b);
> > +  unsigned long q = __builtin_object_size (p->c, 1);
> > +  if (q < s)
> > +    baz ();
> > +}
> > diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
> > index 8d74731a891..9b9fbddb1ab 100644
> > --- a/gcc/tree-ssa-sccvn.cc
> > +++ b/gcc/tree-ssa-sccvn.cc
> > @@ -987,9 +987,12 @@ copy_reference_ops_from_ref (tree ref,
> > vec<vn_reference_op_s> *result)
> >              + (wi::to_offset (bit_offset) >> LOG2_BITS_PER_UNIT));
> >         /* Probibit value-numbering zero offset components
> 
> Maybe also fix this typo while we're here?
> 
> >                    of addresses the same before the pass folding
> > -                  __builtin_object_size had a chance to run.  */
> > +                  __builtin_object_size had a chance to run.  Likewise
> > +                  for components of zero size at arbitrary offset.  */
> >                 if (TREE_CODE (orig) != ADDR_EXPR
> > -                   || maybe_ne (off, 0)
> > +                   || (TYPE_SIZE (temp.type)
> > +                       && !integer_zerop (TYPE_SIZE (temp.type))
> > +                       && maybe_ne (off, 0))
> >      || (cfun->curr_properties & PROP_objsz))
> >           off.to_shwi (&temp.off);
> >               }
> > @@ -1010,9 +1013,30 @@ copy_reference_ops_from_ref (tree ref,
> > vec<vn_reference_op_s> *result)
> >        if (! temp.op2)
> >          temp.op2 = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (eltype),
> >                                  size_int (TYPE_ALIGN_UNIT (eltype)));
> > +       /* Probibit value-numbering addresses of out-of-bound ARRAY_REFs
> 
> ... and then avoid propagating that typo here :)
> 
> > +          the same as addresses of other components before the pass
> > +          folding __builtin_object_size had a chance to run.  */
> > +       bool avoid_oob = true;
> > +       if (TREE_CODE (orig) != ADDR_EXPR
> > +           || cfun->curr_properties & PROP_objsz)
> > +         avoid_oob = false;
> > +       else if (poly_int_tree_p (temp.op0))
> > +         {
> > +           tree ub = array_ref_up_bound (ref);
> > +           if (ub
> > +               && poly_int_tree_p (ub)
> > +               /* ???  The C frontend for T[0] uses [0:] and the
> > +                  C++ frontend [0:-1U].  See layout_type for how
> > +                  awkward this is.  */
> > +               && !integer_minus_onep (ub)
> > +               && known_le (wi::to_poly_offset (temp.op0),
> > +                            wi::to_poly_offset (ub)))
> > +             avoid_oob = false;
> > +         }
> >        if (poly_int_tree_p (temp.op0)
> >             && poly_int_tree_p (temp.op1)
> > -           && TREE_CODE (temp.op2) == INTEGER_CST)
> > +           && TREE_CODE (temp.op2) == INTEGER_CST
> > +           && !avoid_oob)
> >          {
> >     poly_offset_int off = ((wi::to_poly_offset (temp.op0)
> >                                     - wi::to_poly_offset (temp.op1))
> > @@ -1754,6 +1778,23 @@ re_valueize:
> >           && poly_int_tree_p (vro->op1)
> >           && TREE_CODE (vro->op2) == INTEGER_CST)
> >     {
> > +     /* Probibit value-numbering addresses of out-of-bound ARRAY_REFs
> 
> Likewise.
> 
> > +        the same as addresses of other components before the pass
> > +        folding __builtin_object_size had a chance to run.  */
> > +     if (!(cfun->curr_properties & PROP_objsz)
> > +         && (*orig)[0].opcode == ADDR_EXPR)
> > +       {
> > +         tree dom = TYPE_DOMAIN ((*orig)[i + 1].type);
> > +         if (!dom
> > +             || !TYPE_MAX_VALUE (dom)
> > +             || !poly_int_tree_p (TYPE_MAX_VALUE (dom))
> > +             || integer_minus_onep (TYPE_MAX_VALUE (dom)))
> > +           continue;
> > +         if (!known_le (wi::to_poly_offset (vro->op0),
> > +                        wi::to_poly_offset (TYPE_MAX_VALUE (dom))))
> > +           continue;
> > +       }
> > +
> >      poly_offset_int off = ((wi::to_poly_offset (vro->op0)
> >        - wi::to_poly_offset (vro->op1))
> >        * wi::to_offset (vro->op2)
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to