Regarding bug 22480, vectorisation of shifts

Paolo Bonzini paolo.bonzini@lu.unisi.ch
Thu Sep 1 07:25:00 GMT 2005


Uros Bizjak wrote (privately, but I forwarded to GCC in order to get help):

>Hello Paolo!
>
>I was looking at PR middle-end/22480 if there is something to fix at the i386 
>backend. However, there is no documentation at all regarding vec_shl_<mode> and 
>vec_shr_<mode> builtins.
>  
>
Heh, I'm quite at a loss regarding PR22480.  I don't know exactly what 
to do because i386 does not support, e.g. { 2, 4 } << { 1, 2 } (which 
would give {4, 16} as a result).  There is indeed a back-end problem, 
because ashl<mode>3 is supposed to have two operands of the same mode, 
not one vector and one SI!

On the other hand, I'm not keen on using vec_shl_<mode> because these 
shift the *whole* register, not each byte/word/dword. i.e. { 0x40000000, 
0x80000000 } << 2 = { 2, 0 } which is not really what is expected.

One simple way to fix the PR could be *not* to define ashl<mode>3 insns 
for i386.  These however would lose vectorization of a shift by     
constant.

Another way could be to

1) in the vectorizer, check in the optab if the predicate for each 
operand of an insn accepts a register.  If not, refuse vectorization if 
the corresponding gimple operand is not constant.

2) and add a new predicate to i386 that only accepts CONST_VECTORs whose 
items are all the same.  Make ashl<mode>3 use it, with a define_expand, 
and add a new insn which is the old ashl<mode>3:

(define_predicate "vec_shift_operand"
  (and (match_code "const_vector")
       (match_test "GET_MODE_CLASS (mode) == MODE_VECTOR_INT"))
{
  unsigned elt = GET_MODE_NUNITS (mode) - 1;
  HOST_WIDE_INT ref = INTVAL (CONST_VECTOR_ELT (op, elt));
  while (--elt >= 0)
    {
      if (INTVAL (CONST_VECTOR_ELT (op, elt)) != ref)
        return 0;
    }
  return 1;
})

(define_expand "ashl<mode>3"
  [(set (match_operand:SSEMODE248 0 "register_operand" "=x")
        (ashift:SSEMODE248
          (match_operand:SSEMODE248 1 "register_operand" "0")
          (match_operand:SSEMODE248 2 "vec_shift_operand" "xi")))]
  "TARGET_SSE2"
{
  operand[2] = CONST_VECTOR_ELT (operand[2], 0);
}

(define_insn "*sse_psll<mode>3"
  [(set (match_operand:SSEMODE248 0 "register_operand" "=x")
        (ashift:SSEMODE248
          (match_operand:SSEMODE248 1 "register_operand" "0")
          (match_operand:SI 2 "nonmemory_operand" "xi")))]
  "TARGET_SSE2"
  "psll<ssevecsize>\t{%2, %0|%0, %2}"
  [(set_attr "type" "sseishft")
   (set_attr "mode" "TI")])

And similarly for ashr<mode>3 and lshr<mode>3.

This however will not fix "a << b" shifts, which right now should (my 
guess) ICE with something similar to PR22480.

By the way, it is time to remove the mmx_ prefix from the MMX insns!

Paolo



More information about the Gcc mailing list