On Thu, Aug 20, 2020 at 11:09 AM Petro Karashchenko via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hello Ricard!
>
> Thank you very much for your reply.
> The case is that currently the "uncached" attribute is used to generate
> special "cache bypass" instructions instead of regular one by ARC backend.
> That decision is made based on the result of "lookup_attribute()" call for
> a specified MEM_REF. For example
>   if (TREE_CODE (addr) == MEM_REF)
>     {
>       attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 0)));

Just a note - this looks very unsafe since the type of the address operand to
the MEM_REF is quite arbitrary.

>       if (lookup_attribute ("uncached", attrs))
>         return true;
>       attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 1)));
>       if (lookup_attribute ("uncached", attrs))
>         return true;
>     }
>
> That works pretty well for aligned types, but for unaligned/packed types
> (also for example for array -X access) the expression is dropped. In my
> test example with current code the "a1" will still inherit "uncached"
> attribute because "adjust_object" will not be done, but "a2", "a3" and "a4"
> will drop expression, hence "uncached" attribute can't be accessed.
>
> Does that make sense?

Hmm, the MEM_EXPR is used for optimization only and may _not_ be
the only way to carry information required for correctness.  That said,
dropping mem_attrs must be always correct.

This means you have to maintain the 'uncached' effect elsewhere.

Richard.

> Maybe we can clone/copy expression instead of dropping to preserve
> "uncached" attribute?
>
> Best Regards,
> Petro Karashchenko
>
> чт, 20 серп. 2020 о 11:01 Richard Sandiford <richard.sandif...@arm.com>
> пише:
>
> > Petro Karashchenko via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> > > for bitfield MEMREFs
> > >
> > > [FIX] Propagate uncached type attributes to unaligned/packed types
> >
> > This doesn't look safe in general.  The current code was added
> > to avoid wrong-code problems for accesses that step outside the
> > bounds of the original MEM_EXPR.
> >
> > Could you explain in more detail what's going wrong in the testcase?
> > It wasn't obvious why the code you're removing would trigger for that test.
> >
> > Thanks,
> > Richard
> >
> > >
> > > [ARC] Update tests
> > >
> > > gcc/
> > > xxxx-xx-xx  Petro Karashchenko  <petro.karashche...@gmail.com>
> > >
> > >         * emit-rtl.c (adjust_address_1): Do not drop the object
> > >         if the new memory reference is outside the underlying
> > >         object to preserve object attributes that are needed
> > >         by some backend implementations. Remove adjust_object
> > >         parameter as it is not used anymore.
> > >         (adjust_automodify_address_1): Adjust according to
> > >         new adjust_address_1 prototype.
> > >         (replace_equiv_address_nv): Likewise.
> > >         * gcc/emit-rtl.h (adjust_address): Adjust according to
> > >         new adjust_address_1 prototype.
> > >         (adjust_address_nv): Likewise.
> > >         (adjust_bitfield_address): Likewise.
> > >         (adjust_bitfield_address_size): Likewise.
> > >         (adjust_bitfield_address_nv): Likewise.
> > >
> > > testsuite/
> > > xxxx-xx-xx  Petro Karashchenko  <petro.karashche...@gmail.com>
> > >
> > >         * gcc.target/arc/uncached-9.c: New file.
> > >
> > > Problem description:
> > > __attribute__((uncached)) is dropped for other than the first member of
> > > "packed" or "unaligned" types.
> > >
> > > Tests:
> > > Tested with ARC600 bases ASIC. The correct code is generated.
> > >
> > > From 1f8a824f8ed8c1452f2bdfc513716c63d5d12545 Mon Sep 17 00:00:00 2001
> > > From: Petro Karashchenko <petro.karashche...@gmail.com>
> > > Date: Sun, 16 Aug 2020 01:10:11 +0300
> > > Subject: [PATCH] [FIX] Remove object adjustment to preserve object
> > attributes
> > >  for bitfield MEMREFs
> > >
> > > [FIX] Propagate uncached type attributes to unaligned/packed types
> > >
> > > [ARC] Update tests
> > >
> > > gcc/
> > > xxxx-xx-xx  Petro Karashchenko  <petro.karashche...@gmail.com>
> > >
> > >         * emit-rtl.c (adjust_address_1): Do not drop the object
> > >         if the new memory reference is outside the underlying
> > >         object to preserve object attributes that are needed
> > >         by some backend implementations. Remove adjust_object
> > >         parameter as it is not used anymore.
> > >         (adjust_automodify_address_1): Adjust according to
> > >         new adjust_address_1 prototype.
> > >         (replace_equiv_address_nv): Likewise.
> > >         * gcc/emit-rtl.h (adjust_address): Adjust according to
> > >         new adjust_address_1 prototype.
> > >         (adjust_address_nv): Likewise.
> > >         (adjust_bitfield_address): Likewise.
> > >         (adjust_bitfield_address_size): Likewise.
> > >         (adjust_bitfield_address_nv): Likewise.
> > >
> > > testsuite/
> > > xxxx-xx-xx  Petro Karashchenko  <petro.karashche...@gmail.com>
> > >
> > >         * gcc.target/arc/uncached-9.c: New file.
> > >
> > > Signed-off-by: Petro Karashchenko <petro.karashche...@gmail.com>
> > > ---
> > >  gcc/emit-rtl.c                            | 28 +++--------------------
> > >  gcc/emit-rtl.h                            | 12 +++++-----
> > >  gcc/testsuite/gcc.target/arc/uncached-9.c | 19 +++++++++++++++
> > >  3 files changed, 28 insertions(+), 31 deletions(-)
> > >  create mode 100644 gcc/testsuite/gcc.target/arc/uncached-9.c
> > >
> > > diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> > > index f9b0e9714d9..c0e2ead907b 100644
> > > --- a/gcc/emit-rtl.c
> > > +++ b/gcc/emit-rtl.c
> > > @@ -2337,8 +2337,7 @@ change_address (rtx memref, machine_mode mode, rtx
> > addr)
> > >
> > >  rtx
> > >  adjust_address_1 (rtx memref, machine_mode mode, poly_int64 offset,
> > > -               int validate, int adjust_address, int adjust_object,
> > > -               poly_int64 size)
> > > +               int validate, int adjust_address, poly_int64 size)
> > >  {
> > >    rtx addr = XEXP (memref, 0);
> > >    rtx new_rtx;
> > > @@ -2413,25 +2412,11 @@ adjust_address_1 (rtx memref, machine_mode mode,
> > poly_int64 offset,
> > >    if (new_rtx == memref && maybe_ne (offset, 0))
> > >      new_rtx = copy_rtx (new_rtx);
> > >
> > > -  /* Conservatively drop the object if we don't know where we start
> > from.  */
> > > -  if (adjust_object && (!attrs.offset_known_p || !attrs.size_known_p))
> > > -    {
> > > -      attrs.expr = NULL_TREE;
> > > -      attrs.alias = 0;
> > > -    }
> > > -
> > >    /* Compute the new values of the memory attributes due to this
> > adjustment.
> > >       We add the offsets and update the alignment.  */
> > >    if (attrs.offset_known_p)
> > >      {
> > >        attrs.offset += offset;
> > > -
> > > -      /* Drop the object if the new left end is not within its bounds.
> > */
> > > -      if (adjust_object && maybe_lt (attrs.offset, 0))
> > > -     {
> > > -       attrs.expr = NULL_TREE;
> > > -       attrs.alias = 0;
> > > -     }
> > >      }
> > >
> > >    /* Compute the new alignment by taking the MIN of the alignment and
> > the
> > > @@ -2445,18 +2430,11 @@ adjust_address_1 (rtx memref, machine_mode mode,
> > poly_int64 offset,
> > >
> > >    if (maybe_ne (size, 0))
> > >      {
> > > -      /* Drop the object if the new right end is not within its
> > bounds.  */
> > > -      if (adjust_object && maybe_gt (offset + size, attrs.size))
> > > -     {
> > > -       attrs.expr = NULL_TREE;
> > > -       attrs.alias = 0;
> > > -     }
> > >        attrs.size_known_p = true;
> > >        attrs.size = size;
> > >      }
> > >    else if (attrs.size_known_p)
> > >      {
> > > -      gcc_assert (!adjust_object);
> > >        attrs.size -= offset;
> > >        /* ??? The store_by_pieces machinery generates negative sizes,
> > >        so don't assert for that here.  */
> > > @@ -2477,7 +2455,7 @@ adjust_automodify_address_1 (rtx memref,
> > machine_mode mode, rtx addr,
> > >                            poly_int64 offset, int validate)
> > >  {
> > >    memref = change_address_1 (memref, VOIDmode, addr, validate, false);
> > > -  return adjust_address_1 (memref, mode, offset, validate, 0, 0, 0);
> > > +  return adjust_address_1 (memref, mode, offset, validate, 0, 0);
> > >  }
> > >
> > >  /* Return a memory reference like MEMREF, but whose address is changed
> > by
> > > @@ -2561,7 +2539,7 @@ replace_equiv_address_nv (rtx memref, rtx addr,
> > bool inplace)
> > >  rtx
> > >  widen_memory_access (rtx memref, machine_mode mode, poly_int64 offset)
> > >  {
> > > -  rtx new_rtx = adjust_address_1 (memref, mode, offset, 1, 1, 0, 0);
> > > +  rtx new_rtx = adjust_address_1 (memref, mode, offset, 1, 1, 0);
> > >    poly_uint64 size = GET_MODE_SIZE (mode);
> > >
> > >    /* If there are no changes, just return the original memory
> > reference.  */
> > > diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
> > > index 3d6565c8a30..108669f51a1 100644
> > > --- a/gcc/emit-rtl.h
> > > +++ b/gcc/emit-rtl.h
> > > @@ -473,27 +473,27 @@ extern rtx change_address (rtx, machine_mode, rtx);
> > >  /* Return a memory reference like MEMREF, but with its mode changed
> > >     to MODE and its address offset by OFFSET bytes.  */
> > >  #define adjust_address(MEMREF, MODE, OFFSET) \
> > > -  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 0, 0)
> > > +  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 0)
> > >
> > >  /* Likewise, but the reference is not required to be valid.  */
> > >  #define adjust_address_nv(MEMREF, MODE, OFFSET) \
> > > -  adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 0, 0)
> > > +  adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 0)
> > >
> > >  /* Return a memory reference like MEMREF, but with its mode changed
> > >     to MODE and its address offset by OFFSET bytes.  Assume that it's
> > >     for a bitfield and conservatively drop the underlying object if we
> > >     cannot be sure to stay within its bounds.  */
> > >  #define adjust_bitfield_address(MEMREF, MODE, OFFSET) \
> > > -  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 1, 0)
> > > +  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 0)
> > >
> > >  /* As for adjust_bitfield_address, but specify that the width of
> > >     BLKmode accesses is SIZE bytes.  */
> > >  #define adjust_bitfield_address_size(MEMREF, MODE, OFFSET, SIZE) \
> > > -  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 1, SIZE)
> > > +  adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, SIZE)
> > >
> > >  /* Likewise, but the reference is not required to be valid.  */
> > >  #define adjust_bitfield_address_nv(MEMREF, MODE, OFFSET) \
> > > -  adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 1, 0)
> > > +  adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 0)
> > >
> > >  /* Return a memory reference like MEMREF, but with its mode changed
> > >     to MODE and its address changed to ADDR, which is assumed to be
> > > @@ -506,7 +506,7 @@ extern rtx change_address (rtx, machine_mode, rtx);
> > >    adjust_automodify_address_1 (MEMREF, MODE, ADDR, OFFSET, 0)
> > >
> > >  extern rtx adjust_address_1 (rtx, machine_mode, poly_int64, int, int,
> > > -                          int, poly_int64);
> > > +                          poly_int64);
> > >  extern rtx adjust_automodify_address_1 (rtx, machine_mode, rtx,
> > >                                       poly_int64, int);
> > >
> > > diff --git a/gcc/testsuite/gcc.target/arc/uncached-9.c
> > b/gcc/testsuite/gcc.target/arc/uncached-9.c
> > > new file mode 100644
> > > index 00000000000..44b8a0ed7f3
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/arc/uncached-9.c
> > > @@ -0,0 +1,19 @@
> > > +/* { dg-do compile } */
> > > +
> > > +#include <stddef.h>
> > > +
> > > +typedef volatile struct {
> > > +  uint32_t a1;
> > > +  uint32_t a2;
> > > +  uint32_t a3;
> > > +  uint32_t a4;
> > > +} __attribute__((packed,uncached)) my_type_t;
> > > +
> > > +uint32_t foo (my_type_t *p)
> > > +{
> > > +  p->a3 = p->a2;
> > > +  return p->a4;
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler-times "stb\.di" 4 } } */
> > > +/* { dg-final { scan-assembler-times "ldb\.di" 12 } } */
> >

Reply via email to