"H.J. Lu" <hjl.to...@gmail.com> writes:
> After
>
> commit 965564eafb721f8000013a3112f1bba8d8fae32b
> Author: Richard Sandiford <richard.sandif...@arm.com>
> Date:   Tue Jul 29 15:58:34 2025 +0100
>
>     simplify-rtx: Simplify subregs of logic ops
>
> make_compound_operation_int gets
>
> (lshiftrt:DI (and:DI (reg:DI 110 [ b ])
>                    (reg/v:DI 103 [ a ]))
>            (const_int 8 [0x8])))
>
> instead of
>
> (and:DI (lshiftrt:DI (and:DI (reg:DI 110 [ b ])
>                            (reg/v:DI 103 [ a ]))
>          (const_int 8 [0x8]))
>       (const_int 255 [0xff]))
>
> If this is for SET of ZERO_EXTRACT destination:
>
> (zero_extract:DI (reg/v:DI 103 [ a ])
>     (const_int 8 [0x8])
>     (const_int 8 [0x8]))
>
> make an extraction out of the logical right shift
>
> (zero_extract:DI (and:DI (reg:DI 110 [ b ])
>                        (reg/v:DI 103 [ a ]))
>     (const_int 8 [0x8])
>     (const_int 8 [0x8]))
>
> to convert
>
> (set (zero_extract:DI (reg/v:DI 103 [ a ])
>         (const_int 8 [0x8])
>         (const_int 8 [0x8]))
>      (lshiftrt:DI (and:DI (reg:DI 110 [ b ])
>                         (reg/v:DI 103 [ a ]))
>                 (const_int 8 [0x8])))
>
> to
>
> (set (zero_extract:DI (reg/v:DI 103 [ a ])
>         (const_int 8 [0x8])
>         (const_int 8 [0x8]))
>      (zero_extract:DI (and:DI (reg:DI 110 [ b ])
>                             (reg/v:DI 103 [ a ]))
>       (const_int 8 [0x8])
>       (const_int 8 [0x8])))

Thanks for tackling the regression.  I don't think this is the
right fix though.  It doesn't seem conceptually correct for
make_compound_operation to depend on the destination.

In:

struct s {
  long a:8;
  long b:8;
  long c:48;
};

struct s f(struct s x, long y, long z) {
  x.b = (y & z) >> 8;
  return x;
}

struct s f2(struct s x, struct s y) {
  x.b &= y.b;
  return x;
}

we used the shift form even before my patch, and I think the shift form
is to be preferred over zero/sign_extract when no masking is needed.

Another possiblity would be to replace i386 uses of extract_operator with
a new extract_high_operator that matches both shifts and extracts.
I've got a patch for that that I'll test overnight.

Richard

>
>       PR target/121306
>       * combine.cc (simplify_set): Pass dest to make_compound_operation.
>       (make_compound_operation_int): Add an rtx argument for
>       destination and pass it to make_compound_operation.  For a logical
>       right shift if the destination is ZERO_EXTRACT with constant start
>       and width, make an extraction.
>       (make_compound_operation): Add an rtx argument for destination
>       and pass it to make_compound_operation_int.
>       * rtl.h (make_compound_operation): Add an rtx argument, default
>       to nullptr.
>
> Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
> ---
>  gcc/combine.cc | 34 ++++++++++++++++++++++++++++++----
>  gcc/rtl.h      |  2 +-
>  2 files changed, 31 insertions(+), 5 deletions(-)
>
> diff --git a/gcc/combine.cc b/gcc/combine.cc
> index 4dbc1f6a4a4..42dff7db153 100644
> --- a/gcc/combine.cc
> +++ b/gcc/combine.cc
> @@ -7027,7 +7027,7 @@ simplify_set (rtx x)
>      {
>        /* Get SET_SRC in a form where we have placed back any
>        compound expressions.  Then do the checks below.  */
> -      src = make_compound_operation (src, SET);
> +      src = make_compound_operation (src, SET, dest);
>        SUBST (SET_SRC (x), src);
>      }
>  
> @@ -8070,7 +8070,8 @@ extract_left_shift (scalar_int_mode mode, rtx x, int 
> count)
>  static rtx
>  make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
>                            enum rtx_code in_code,
> -                          enum rtx_code *next_code_ptr)
> +                          enum rtx_code *next_code_ptr,
> +                          rtx dest)
>  {
>    rtx x = *x_ptr;
>    enum rtx_code next_code = *next_code_ptr;
> @@ -8343,6 +8344,31 @@ make_compound_operation_int (scalar_int_mode mode, rtx 
> *x_ptr,
>                                     XEXP (x, 1));
>         break;
>       }
> +      else if (in_code == SET
> +            && dest
> +            && GET_CODE (dest) == ZERO_EXTRACT
> +            && CONST_INT_P (XEXP (dest, 1))
> +            && CONST_INT_P (XEXP (dest, 2)))
> +     {
> +       /* If this is used for SET of ZERO_EXTRACT destination with
> +          constant start and width:
> +
> +          (set (zero_extract:DI (reg/v:DI 103 [ a ])
> +                  (const_int 8 [0x8])
> +                  (const_int 8 [0x8]))
> +               (lshiftrt:DI (and:DI (reg:DI 110 [ b ])
> +                                    (reg/v:DI 103 [ a ]))
> +                            (const_int 8 [0x8])))
> +
> +          make an extraction.  */
> +       new_rtx = make_compound_operation (XEXP (x, 0), next_code);
> +       new_rtx = make_extraction (mode, new_rtx,
> +                                  INTVAL (XEXP (dest, 2)),
> +                                  XEXP (x, 1),
> +                                  INTVAL (XEXP (dest, 1)), true,
> +                                  false, in_code == COMPARE);
> +       break;
> +     }
>  
>        /* fall through */
>  
> @@ -8503,7 +8529,7 @@ make_compound_operation_int (scalar_int_mode mode, rtx 
> *x_ptr,
>     precisely it is an equality comparison against zero.  */
>  
>  rtx
> -make_compound_operation (rtx x, enum rtx_code in_code)
> +make_compound_operation (rtx x, enum rtx_code in_code, rtx dest)
>  {
>    enum rtx_code code = GET_CODE (x);
>    const char *fmt;
> @@ -8524,7 +8550,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
>    if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
>      {
>        rtx new_rtx = make_compound_operation_int (mode, &x, in_code,
> -                                              &next_code);
> +                                              &next_code, dest);
>        if (new_rtx)
>       return new_rtx;
>        code = GET_CODE (x);
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index 5bd0bd4d168..e4f197157b0 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -4287,7 +4287,7 @@ extern bool validate_subreg (machine_mode, machine_mode,
>  /* In combine.cc  */
>  extern unsigned int extended_count (const_rtx, machine_mode, bool);
>  extern rtx remove_death (unsigned int, rtx_insn *);
> -extern rtx make_compound_operation (rtx, enum rtx_code);
> +extern rtx make_compound_operation (rtx, enum rtx_code, rtx = nullptr);
>  
>  /* In sched-rgn.cc.  */
>  extern void schedule_insns (void);

Reply via email to