"H.J. Lu" <[email protected]> writes:
> After
>
> commit 965564eafb721f8000013a3112f1bba8d8fae32b
> Author: Richard Sandiford <[email protected]>
> 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 <[email protected]>
> ---
> 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);