LGTM, please commit it.
Claudiu

On Fri, Sep 11, 2026 at 1:01 PM Michiel Derhaeg <[email protected]> wrote:
>
> From: Michiel Derhaeg <[email protected]>
>
> `stdi<mode>` incorrectly uses a too liberal predicate for the
> destination operand, producing something like this: stb.di r2,[r13,r1]
> These [reg,reg] operands are not valid.
>
> This bug appeared because the introduction of
> `-ffuse-ops-with-volatile-access` in r16-5947-ga6c50ec2c6ebcb.  Before
> its existence, recog/combine would've disallowed `(plus (reg) (reg))` as
> the destination operand.
>
> POST_INC (and friends) is now produced as well. Didn't try implementing
> that for *stdidi_split and simply disallowed it instead.
>
>         PR target/126157
>
> gcc/ChangeLog:
>
>         * config/arc/arc.cc (prepare_move_operands): Force the address of
>         an uncached store into a register when it is not a valid store
>         destination.
>         * config/arc/arc.md (stdi<mode>): Use move_dest_operand for the
>         destination operand.
>         (*stdidi_split): Use non_mod_move_dest_operand for the destination
>         operand.
>         * config/arc/predicates.md (non_mod_move_dest_operand): New
>         predicate that disallows PRE/POST_INC/DEC.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/arc/uncached-10.c: New test.
>         * gcc.target/arc/uncached-11.c: New test.
>
> Signed-off-by: Alexandru Turjan <[email protected]>
> Signed-off-by: Michiel Derhaeg <[email protected]>
> ---
>  gcc/config/arc/arc.cc                      |  9 ++++
>  gcc/config/arc/arc.md                      |  4 +-
>  gcc/config/arc/predicates.md               | 17 ++++++++
>  gcc/testsuite/gcc.target/arc/uncached-10.c | 50 ++++++++++++++++++++++
>  gcc/testsuite/gcc.target/arc/uncached-11.c | 50 ++++++++++++++++++++++
>  5 files changed, 128 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/arc/uncached-10.c
>  create mode 100644 gcc/testsuite/gcc.target/arc/uncached-11.c
>
> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
> index 32e358d2fd4..de6982f5c4c 100644
> --- a/gcc/config/arc/arc.cc
> +++ b/gcc/config/arc/arc.cc
> @@ -9286,6 +9286,15 @@ prepare_move_operands (rtx *operands, machine_mode 
> mode)
>         {
>           if (!REG_P (operands[1]))
>             operands[1] = force_reg (mode, operands[1]);
> +
> +         if (!move_dest_operand (operands[0], mode))
> +           {
> +             rtx tmp0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
> +             rtx tmp1 = change_address (operands[0], mode, tmp0);
> +             MEM_COPY_ATTRIBUTES (tmp1, operands[0]);
> +             operands[0] = tmp1;
> +           }
> +
>           emit_insn (gen_rtx_UNSPEC_VOLATILE
>                      (VOIDmode, gen_rtvec (2, operands[0], operands[1]),
>                       VUNSPEC_ARC_STDI));
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 54b65fefe6a..d080143c45d 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -4955,7 +4955,7 @@ archs4x, archs4xd"
>    [(set_attr "type" "load")])
>
>  (define_insn "stdi<mode>"
> -  [(unspec_volatile [(match_operand:ALLI 0 "memory_operand"    "m,m,Usc")
> +  [(unspec_volatile [(match_operand:ALLI 0 "move_dest_operand" "m,m,Usc")
>                      (match_operand:ALLI 1 "nonmemory_operand" "r,Cm3,i")]
>                     VUNSPEC_ARC_STDI)]
>    ""
> @@ -4964,7 +4964,7 @@ archs4x, archs4xd"
>     (set_attr "type" "store")])
>
>  (define_insn_and_split "*stdidi_split"
> -  [(unspec_volatile [(match_operand:DI 0 "memory_operand"   "m")
> +  [(unspec_volatile [(match_operand:DI 0 "non_mod_move_dest_operand" "m")
>                      (match_operand:DI 1 "register_operand" "r")]
>                     VUNSPEC_ARC_STDI)]
>    "!TARGET_LL64"
> diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
> index 1b7f53a70ff..382012dc68d 100644
> --- a/gcc/config/arc/predicates.md
> +++ b/gcc/config/arc/predicates.md
> @@ -775,3 +775,20 @@
>    (ior (match_test "register_operand (op, mode)")
>         (and (match_code "const_int, symbol_ref")
>             (match_test "!optimize_size"))))
> +
> +(define_predicate "non_mod_move_dest_operand"
> +  (match_operand 0 "move_dest_operand")
> +{
> +  rtx addr = XEXP (op, 0);
> +  enum rtx_code code = GET_CODE (addr);
> +
> +  if (code == POST_INC
> +      || code == PRE_INC
> +      || code == POST_DEC
> +      || code == PRE_DEC
> +      || code == POST_MODIFY
> +      || code == PRE_MODIFY)
> +    return false;
> +
> +  return true;
> +})
> diff --git a/gcc/testsuite/gcc.target/arc/uncached-10.c 
> b/gcc/testsuite/gcc.target/arc/uncached-10.c
> new file mode 100644
> index 00000000000..767cd484fb6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/uncached-10.c
> @@ -0,0 +1,50 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mno-ll64" } */
> +
> +#ifndef __uncached
> +#define __uncached __attribute__((uncached))
> +#endif
> +
> +volatile char *
> +pack_byte_ptr (volatile char *p, const void *s, int len)
> +{
> +    volatile __uncached char *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const char *)s)[i];
> +    return p;
> +}
> +
> +volatile short *
> +pack_halfword_ptr (volatile short *p, const void *s, int len)
> +{
> +    volatile __uncached short *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const short *)s)[i];
> +    return p;
> +}
> +
> +volatile int *
> +pack_word_ptr (volatile int *p, const void *s, int len)
> +{
> +    volatile __uncached int *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const int *)s)[i];
> +    return p;
> +}
> +
> +volatile long long *
> +pack_doubleword_ptr (volatile long long *p, const void *s, int len)
> +{
> +    volatile __uncached long long *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const long long *)s)[i];
> +    return p;
> +}
> +
> +/* { dg-final { scan-assembler "stb.*\\.di" } } */
> +/* { dg-final { scan-assembler "\\m(sth|stw).*\\.di" } } */
> +/* { dg-final { scan-assembler "st.*\\.di" } } */
> +
> +/* { dg-final { scan-assembler-not 
> {stb.*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> +/* { dg-final { scan-assembler-not 
> {\m(sth|stw).*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> +/* { dg-final { scan-assembler-not 
> {st.*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> diff --git a/gcc/testsuite/gcc.target/arc/uncached-11.c 
> b/gcc/testsuite/gcc.target/arc/uncached-11.c
> new file mode 100644
> index 00000000000..44efeb2cb05
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/uncached-11.c
> @@ -0,0 +1,50 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Os -mno-ll64" } */
> +
> +#ifndef __uncached
> +#define __uncached __attribute__((uncached))
> +#endif
> +
> +volatile char *
> +pack_byte_ptr (volatile char *p, const void *s, int len)
> +{
> +    volatile __uncached char *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const char *)s)[i];
> +    return p;
> +}
> +
> +volatile short *
> +pack_halfword_ptr (volatile short *p, const void *s, int len)
> +{
> +    volatile __uncached short *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const short *)s)[i];
> +    return p;
> +}
> +
> +volatile int *
> +pack_word_ptr (volatile int *p, const void *s, int len)
> +{
> +    volatile __uncached int *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const int *)s)[i];
> +    return p;
> +}
> +
> +volatile long long *
> +pack_doubleword_ptr (volatile long long *p, const void *s, int len)
> +{
> +    volatile __uncached long long *buf = p + 4;
> +    for (int i = 0; i < len; i++)
> +        buf[i] = ((const long long *)s)[i];
> +    return p;
> +}
> +
> +/* { dg-final { scan-assembler "stb.*\\.di" } } */
> +/* { dg-final { scan-assembler "\\m(sth|stw).*\\.di" } } */
> +/* { dg-final { scan-assembler "st.*\\.di" } } */
> +
> +/* { dg-final { scan-assembler-not 
> {stb.*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> +/* { dg-final { scan-assembler-not 
> {\m(sth|stw).*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> +/* { dg-final { scan-assembler-not 
> {st.*\.di\s+r[0-9]+,\s*\[r[0-9]+,\s*r[0-9]+\]} } } */
> --
> 2.54.0
>

Reply via email to