"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);