On Tue, 21 Jul 2026, Richard Sandiford wrote:
> 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?
Ah, thanks for noticing.
> Yeah, agreed that this check looks redundant. Also, AFAIK, VEC_CONCAT
> requires both operands to have the same mode.
Not sure. As said I copied this from the vector-vector case.
> 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:
>
> > + if (i0 == l0 && mode == mode1 && !side_effects_p (subop0))
> > + return subop1;
>
> could be handled with known_eq.
Yes. I'm testing the following simplification and will post v2:
/* If we select one half of a vec_concat, return that. */
else if (GET_CODE (trueop0) == VEC_CONCAT)
{
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;
if (known_eq (i0, GET_MODE_NUNITS (mode0))
&& mode == mode1 && !side_effects_p (subop0))
return subop1;
}
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)