On Tue, 21 Jul 2026, Richard Sandiford wrote: > Richard Sandiford <[email protected]> writes: > > Jeffrey Law <[email protected]> writes: > >> On 7/20/2026 6:31 AM, Richard Biener wrote: > >>> The following adds simplification of a scalar mode vec_select wrapping > >>> a vec_concat. combine sees > >>> > >>> (insn 7 4 8 2 (set (reg:V2DF 106) > >>> (vec_concat:V2DF (plus:DF (vec_select:DF (reg/v:V2DF 101 [ p ]) > >>> (parallel [ > >>> (const_int 0 [0]) > >>> ])) > >>> (vec_select:DF (reg/v:V2DF 101 [ p ]) > >>> (parallel [ > >>> (const_int 1 [0x1]) > >>> ]))) > >>> (plus:DF (vec_select:DF (reg/v:V2DF 101 [ p ]) > >>> (parallel [ > >>> (const_int 0 [0]) > >>> ])) > >>> (vec_select:DF (reg/v:V2DF 101 [ p ]) > >>> (parallel [ > >>> (const_int 1 [0x1]) > >>> ]))))) "t.c":5:11 3234 {*sse3_haddv2df3} > >>> (expr_list:REG_DEAD (reg/v:V2DF 101 [ p ]) > >>> (nil))) > >>> (insn 8 7 9 2 (set (reg:DF 105) > >>> (vec_select:DF (reg:V2DF 106) > >>> (parallel [ > >>> (const_int 0 [0]) > >>> ]))) "t.c":5:11 7297 {sse2_storelpd} > >>> (expr_list:REG_DEAD (reg:V2DF 106) > >>> (nil))) > >>> > >>> and this should simplify and combine to > >>> > >>> (set (reg:DF 105) > >>> (plus:DF (vec_select:DF (reg:V2DF 109 [ p ]) > >>> (parallel [ > >>> (const_int 0 [0]) > >>> ])) > >>> (vec_select:DF (reg:V2DF 109 [ p ]) > >>> (parallel [ > >>> (const_int 1 [0x1]) > >>> ])))) > >>> > >>> which x86 can recognize (but rejects due to consting, see PR126328). > >>> There'll be test coverage in gcc.target/i386/pr54400.c > >>> > >>> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. > >>> > >>> The code snipped is stripped down from the vector vec_select case > >>> but with the side_effects_p arguments fixed(?) > >>> > >>> OK? > >>> > >>> Thanks, > >>> Richard. > >>> > >>> * simplify-rtx.cc (simplify_context::simplify_binary_operation_1): > >>> Simplify scalar vec_select of vec_concat. > >>> --- > >>> gcc/simplify-rtx.cc | 18 ++++++++++++++++++ > >>> 1 file changed, 18 insertions(+) > >>> > >>> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc > >>> index 882a11c5760..612413bf035 100644 > >>> --- a/gcc/simplify-rtx.cc > >>> +++ b/gcc/simplify-rtx.cc > >>> @@ -5148,6 +5148,7 @@ simplify_ashift: > >>> nested VEC_SELECT expressions. When input operand is a > >>> memory > >>> operand, this operation can be simplified to a simple > >>> scalar > >>> load from an offsetted memory address. */ > >>> + int l0, l1; > >>> int n_elts; > >>> if (GET_CODE (trueop0) == VEC_SELECT > >>> && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0))) > >>> @@ -5210,6 +5211,23 @@ simplify_ashift: > >>> tmp_op, gen_rtx_PARALLEL (VOIDmode, > >>> vec)); > >>> return tmp; > >>> } > >>> + /* If we select one half of a vec_concat, return that. */ > >>> + else if (GET_CODE (trueop0) == VEC_CONCAT > >>> + && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0))) > >>> + .is_constant (&l0)) > >>> + && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 1))) > >>> + .is_constant (&l1))) > >> You never use l1, though I guess what you're really testing is that it > >> is a constant, you don't need to know the precise constant? > > > > Yeah, agreed that this check looks redundant. Also, AFAIK, VEC_CONCAT > > requires both operands to have the same mode. > > > > But the is_constant seems unnecessary anyway. It isn't required for: > > > >> + { > >> + rtx subop0 = XEXP (trueop0, 0); > >> + rtx subop1 = XEXP (trueop0, 1); > >> + machine_mode mode0 = GET_MODE (subop0); > >> + machine_mode mode1 = GET_MODE (subop1); > >> + int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); > >> + if (i0 == 0 && mode == mode0 && !side_effects_p (subop1)) > >> + return subop0; > > > > this first simplification, which is valid and potentially useful for VLA > > as well. And the first check in: > > Sorry, scratch the bit about VLA. This will only trigger for 2-element > vectors.
Yes, of course (which is likely why the simplification was missing), but it's still simpler written with VLA in mind (aka known_eq). Richard.
