LGTM,
Claudiu

On Fri, Sep 11, 2026 at 2:57 PM Michiel Derhaeg <[email protected]> wrote:
>
> From: Michiel Derhaeg <[email protected]>
>
> This is a similar issue as PR120375.
>
> doloop_end, loop_end, dbnz, flag, and kflag all write the condition
> codes without declaring it.  Since r16-3301-g724d88900b7a moved
> aarch64-cc-fusion into late-combine, GCC exploits that and keeps
> condition codes live across these insns, producing wrong code.
>
> If a loop fails to resolve to a hardware loop, doloop_end and loop_end
> fall back to instructions that clobber CC.  This needs to be declared on
> the pattern itself or it will not be taken into account.  This fixes
> gcc.c-torture/execute/pr68185.c for ARC60x and ARC700.
>
> dbnz is wrong in the same way as (do)loop_end but I didn't succeed in
> creating a reproducer for it.
>
> flag and kflag write STATUS32, which holds the condition codes.  Since
> the cc-fusion move they can cause unintended clobbers too.
>
>         PR target/127191
>
> gcc/ChangeLog:
>
>         * config/arc/arc.md (doloop_end): Clobber CC.
>         (loop_end): Likewise.
>         (dbnz): Likewise.
>         (flag): Likewise.
>         (kflag): Likewise.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/arc/pr127191-1.c: New test.
>         * gcc.target/arc/pr127191-2.c: New test.
>
> Signed-off-by: Michiel Derhaeg <[email protected]>
> ---
>  gcc/config/arc/arc.md                     | 15 ++++---
>  gcc/testsuite/gcc.target/arc/pr127191-1.c | 30 ++++++++++++++
>  gcc/testsuite/gcc.target/arc/pr127191-2.c | 50 +++++++++++++++++++++++
>  3 files changed, 90 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/arc/pr127191-1.c
>  create mode 100644 gcc/testsuite/gcc.target/arc/pr127191-2.c
>
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index d080143c45d..a406f793090 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -4840,7 +4840,8 @@ archs4x, archs4xd"
>
>  (define_insn "flag"
>    [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
> -                  VUNSPEC_ARC_FLAG)]
> +                  VUNSPEC_ARC_FLAG)
> +   (clobber (reg:CC CC_REG))]
>    ""
>    "@
>      flag%?\\t%0
> @@ -5311,7 +5312,8 @@ archs4x, archs4xd"
>                     (pc)))
>               (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
>               (unspec:SI [(const_int 0)] UNSPEC_ARC_LP)
> -             (clobber (match_dup 2))])]
> +             (clobber (match_dup 2))
> +             (clobber (reg:CC CC_REG))])]
>    ""
>  {
>   if (GET_MODE (operands[0]) != SImode)
> @@ -5341,7 +5343,8 @@ archs4x, archs4xd"
>                       (pc)))
>     (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
>     (unspec:SI [(const_int 0)] UNSPEC_ARC_LP)
> -   (clobber (match_scratch:SI 2 "=X,&r"))]
> +   (clobber (match_scratch:SI 2 "=X,&r"))
> +   (clobber (reg:CC CC_REG))]
>    ""
>    "@
>     ; ZOL_END, begins @%l1
> @@ -5389,7 +5392,8 @@ archs4x, archs4xd"
>     (set (match_dup 0)
>         (plus:SI (match_dup 0)
>                  (const_int -1)))
> -   (clobber (match_scratch:SI 2 "=X,r"))]
> +   (clobber (match_scratch:SI 2 "=X,r"))
> +   (clobber (reg:CC CC_REG))]
>    "TARGET_DBNZ"
>    "@
>     dbnz%*\\t%0,%l1
> @@ -5812,7 +5816,8 @@ archs4x, archs4xd"
>
>  (define_insn "kflag"
>    [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
> -                  VUNSPEC_ARC_KFLAG)]
> +                  VUNSPEC_ARC_KFLAG)
> +   (clobber (reg:CC CC_REG))]
>    "TARGET_V2"
>    "@
>      kflag%?\\t%0
> diff --git a/gcc/testsuite/gcc.target/arc/pr127191-1.c 
> b/gcc/testsuite/gcc.target/arc/pr127191-1.c
> new file mode 100644
> index 00000000000..b79ad2ae3fb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pr127191-1.c
> @@ -0,0 +1,30 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +/* Verifies that the potential CC clobber is taken into account when 
> expanding
> +   doloop_end but this fails to resolve into a hardware loop.  */
> +
> +int d = 1, e, f, o, w = 1, q, t;
> +
> +int
> +main (void)
> +{
> +  int g = 0;
> +
> +  for (; d; d--)
> +    {
> +      while (o)
> +       while (e)
> +         ;
> +
> +      g = t ? g : w;
> +      f = g;
> +      if (g)
> +       q = 1;
> +    }
> +
> +  if (q != 1)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/arc/pr127191-2.c 
> b/gcc/testsuite/gcc.target/arc/pr127191-2.c
> new file mode 100644
> index 00000000000..d5137af1450
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arc/pr127191-2.c
> @@ -0,0 +1,50 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +int q, sink;
> +
> +int __attribute__ ((noipa))
> +flag_clobbers_cc (int a, int b, int *p)
> +{
> +  int s = a | b;
> +
> +  *p = s;
> +  __builtin_arc_flag (0);
> +  if (s == 0)
> +    q = 1;
> +
> +  return s;
> +}
> +
> +#if defined (__ARCEM__) || defined (__ARCHS__)
> +int r;
> +
> +int __attribute__ ((noipa))
> +kflag_clobbers_cc (int a, int b, int *p)
> +{
> +  int s = a | b;
> +
> +  *p = s;
> +  __builtin_arc_kflag (0);
> +  if (s == 0)
> +    r = 1;
> +
> +  return s;
> +}
> +#endif
> +
> +int
> +main (void)
> +{
> +  flag_clobbers_cc (0, 0, &sink);
> +  if (q != 1)
> +    __builtin_abort ();
> +
> +#if defined (__ARCEM__) || defined (__ARCHS__)
> +  kflag_clobbers_cc (0, 0, &sink);
> +  if (r != 1)
> +    __builtin_abort ();
> +#endif
> +
> +  return 0;
> +}
> --
> 2.54.0
>

Reply via email to