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.

Reply via email to