Hi!

On Wed, Sep 03, 2025 at 07:50:32PM +0530, Avinash Jayakar wrote:
> On Fri, 2025-08-29 at 13:14 -0500, Segher Boessenkool wrote:
> > Please don't do this.  Just do a define_insn that recognises a shift
> > by
> > const int 1, and emits an vaddudm machine insn for that.  The RTL as
> > we
> > currently create is just fine, and if we would want a canonical
> > representation for this the shift is probably the best idea!
> > 
> I did try this approach, and encountered several issues. 
> 1. The pattern 
> [(set (match_operand:VEC_I 0 "vint_operand")
>       (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
>                     (match_operand:VEC_I 2 "vint_operand")))]
> makes sure that operand #2 must be vint_operand, thus if it is a
> constant, then the function 'maybe_legitimize_operands' which is called
> under 'maybe_gen_insn', materialized the constant into a register after
> which the pattern matches successfully. 
> 2. Due to the above problem, I could not create a define insn, that can
> look at the operand 2 as a constant and generate vaddudm. I try
> something like following:
> (define_insn 
>   [(set (match_operand:VEC_I 0 "vint_operand")
>       (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
>                     (const_vector:V2DI [(const_int 1) (const_int
> 1)])))]
>   "<VI_unit>"
>   {
>     return "vaddu<VI_char>m %0,%1,%1";
>   }
> )
> 
> But the problem is again, operand 2 is always materialized into a
> register.

At least combine will merge that together with the move from the
const_int.  What happened there?  The dump file will tell you.

> If possible, could you please suggest how I can recognize
> operand #2 as a constant when it is already in a register. 

Just as the const_int thing.

> Just adding this comment, in case the above mentioned approach does not
> work. Would this be ok? Make the operand #2 constraint as
> general_operand (so that it is not materialized into a register). Then
> if operand #2 is a constant int 1, pass through, else copy it to mode
> reg and generate emit ASHIFT insn. 
> 
> diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
> index f5797387ca7..cba57a7319e 100644
> --- a/gcc/config/rs6000/vector.md
> +++ b/gcc/config/rs6000/vector.md
> @@ -1387,13 +1387,24 @@
>    DONE;
>  })
>  
> +
>  ;; Expanders for arithmetic shift left on each vector element
>  (define_expand "vashl<mode>3"
>    [(set (match_operand:VEC_I 0 "vint_operand")
>       (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand")
> -                   (match_operand:VEC_I 2 "vint_operand")))]
> +                   (match_operand:VEC_I 2 "general_operand")))]
>    "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
> -  "")
> +{
> +  rtx op2 = operands[2];
> +  if (CONSTANT_P(op2) && INTVAL(const_vector_elt (op2, 0)) != 1) {
> +    operands[2] = copy_to_mode_reg (<MODE>mode, op2);
> +    emit_insn (gen_rtx_SET (operands[0],
> +                        gen_rtx_ASHIFT (<MODE>mode,
> +                                        operands[1],
> +                                        operands[2])));
> +    DONE;
> +  }
> +})

CONSTANT_P is much more general than what you want here.  Just check for
const_int more directly?

But, don't do that at all!  Tou do not want to use INTVAL, you want to
check if the node is equal to const1_rtx directly!  That is the
canonical representation for (const_int 1), it is a unique RTX, wherever
(const_int 1) is used it always will use const1_rtx.  As it says in
emit-rtl.cc:

> /* We make one copy of (const_int C) where C is in
>    [- MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT]
>    to save space during the compilation and simplify comparisons of
>    integers.  */
> 
> rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];

(and rtl.h has

> #define const1_rtx      (const_int_rtx[MAX_SAVED_CONST_INT+1])

which ties it all neatly together).  So comparing something against
const1_rtx makes sure it is a const_int, and that its value is 1, all in
one fell swoop.  RTL can be very convenient to use :-)

> As you mentioned I will have to add patterns for various sizes as well.

Some judicious use of mode_iterator's should help :-)  It probably is
easiest to write one first, the vaddudm perhaps, but the more general
thing is easier to test, etc. :-)


Segher

Reply via email to