https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127670

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
t.c:5:1: note: node 0x55b3790 (refcnt=1) vector(4) int @_12 = x[3];
t.c:5:1: note: op template: _3 = _1 << _22;
t.c:5:1: note:  stmt 0 _3 = _1 << _22;
t.c:5:1: note:  stmt 1 _5 = _4 << _2;
t.c:5:1: note:  stmt 2 _9 = _8 << _2;
t.c:5:1: note:  stmt 3 _13 = _12 << _2;
t.c:5:1: note:  children 0x55b38f0 0x55b39a0

so we disagree with the result analysis vs. transform which fails at

  vec_mode = TYPE_MODE (vectype);
  icode = (int) optab_handler (optab, vec_mode);
  if (icode == CODE_FOR_nothing)
    {               
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "shift op not supported by target.\n");
      return false;

with V4SImode for vashl_optab while during analysis we ue ashl_optab.
So scalar shift vs. non-scalar shift is mis-recognized.

During analysis:

(gdb) p debug (slp_node)
t.c:5:1: note: node 0x55b3790 (refcnt=1) vector(4) int
t.c:5:1: note: op template: _3 = _1 << _2;
t.c:5:1: note:  stmt 0 _3 = _1 << _2;
t.c:5:1: note:  stmt 1 _5 = _4 << _2;
t.c:5:1: note:  stmt 2 _9 = _8 << _2;
t.c:5:1: note:  stmt 3 _13 = _12 << _2;
t.c:5:1: note:  children 0x55b38f0 0x55b39a0

so somehow the scalar statements changed which happens via

#0  set_ssa_use_from_ptr (use=0x7ffff6600488, val=<ssa_name 0x7ffff6602cb8 22>)
    at /space/rguenther/src/gcc-clean/gcc/ssa-iterators.h:333
#1  0x0000000001f14393 in vectorizable_live_operation (vinfo=0x5621c20, 
    stmt_info=0x5621cf0, slp_node=0x55b36e0, slp_node_instance=0x55191e0, 
    slp_index=0, vec_stmt_p=true, cost_vec=0x0)
    at /space/rguenther/src/gcc-clean/gcc/tree-vect-loop.cc:10519
#2  0x0000000001ee3c22 in vect_transform_stmt (vinfo=0x5621c20, 
    stmt_info=0x5621cf0, gsi=0x7fffffffc8a0, slp_node=0x55b36e0, 
    slp_node_instance=0x55191e0)
    at /space/rguenther/src/gcc-clean/gcc/tree-vect-stmts.cc:13288
#3  0x0000000001f5f2bb in vect_schedule_slp_node (vinfo=0x5621c20,
node=0x55b36e0, 
    instance=0x55191e0, place_only=false)
    at /space/rguenther/src/gcc-clean/gcc/tree-vect-slp.cc:12548

so we have a "live" lane of the SLP graph feeding its own external def,
but we somehow oddly arrive at _2 being live.  The graph we vectorize is

t.c:7:8: note: node 0x2c43b5e0 (refcnt=1) vector(4) int @x[3] = _15;
t.c:7:8: note: op template: x[0] = _4;
t.c:7:8: note:  stmt 0 x[0] = _4;
t.c:7:8: note:  stmt 1 x[1] = _7;
t.c:7:8: note:  stmt 2 x[2] = _11;
t.c:7:8: note:  stmt 3 x[3] = _15;
t.c:7:8: note:  children 0x2c43b690
t.c:7:8: note: node 0x2c43b690 (refcnt=1) vector(4) int @_12 = x[3];
t.c:7:8: note: op template: _4 = _2 + _3;
t.c:7:8: note:  stmt 0 _4 = _2 + _3;
t.c:7:8: note:  stmt 1 _7 = _5 + _6;
t.c:7:8: note:  stmt 2 _11 = _9 + _10;
t.c:7:8: note:  stmt 3 _15 = _13 + _14;
t.c:7:8: note:  children 0x2c43b7f0 0x2c43b8a0
t.c:7:8: note: node 0x2c43b7f0 (refcnt=1) vector(4) int @_2 = j[0];
t.c:7:8: note: op template: _2 = j[0];
t.c:7:8: note:  [l*]stmt 0 _2 = j[0];
t.c:7:8: note:  stmt 1 _6 = j[1];
t.c:7:8: note:  stmt 2 _10 = j[2];
t.c:7:8: note:  stmt 3 _14 = j[3];
t.c:7:8: note: node 0x2c43b8a0 (refcnt=1) vector(4) int @_12 = x[3];
t.c:7:8: note: op template: _3 = _1 << _2;
t.c:7:8: note:  stmt 0 _3 = _1 << _2;
t.c:7:8: note:  stmt 1 _5 = _4 << _2;
t.c:7:8: note:  stmt 2 _9 = _8 << _2;
t.c:7:8: note:  stmt 3 _13 = _12 << _2;
t.c:7:8: note:  children 0x2c43ba00 0x2c43bab0
t.c:7:8: note: node (external) 0x2c43ba00 (refcnt=1) vector(4) int @_12 = x[3];
t.c:7:8: note:  { _1, _4, _8, _12 }
t.c:7:8: note: node 0x2c43bab0 (refcnt=1) vector(4) int @_2 = j[0];
t.c:7:8: note: op template: _2 = j[0];
t.c:7:8: note:  [l] stmt 0 _2 = j[0];
t.c:7:8: note:  [l] stmt 1 _2 = j[0];
t.c:7:8: note:  [l] stmt 2 _2 = j[0];
t.c:7:8: note:  [l] stmt 3 _2 = j[0];
t.c:7:8: note:  load permutation { 0 0 0 0 }

but only _1, _4, _8 and _12 are required and only _4 is part of a vector,
so that should have been live?  Ah, so SLP coverage excludes _4 because
it's used in an extern, it doesn't become PURE_SLP and so the use of _2
in it makes _2 live.  Likewise this makes _3 = _1 << _2 not PURE_SLP
and so we replace _2 therein with the live lane.

The whole thing is conservative for the scalar costing, but for vectorizing
we should probably prune the SLP graph when it has these kind of "cycles"
through externs for optimality reasons though this conflicts with having
analyzed the graph before.

vectorizable_shift itself is a bit of a mess :/  I'll fix it half-heartedly.
We then code generate

  _1 = x[0];
  vect__2.5_21 = MEM <vector(4) int> [(int *)&j];
  _22 = BIT_FIELD_REF <vect__2.5_21, 32, 0>;
  _3 = _1 << _22;
  _4 = _3 + _22;
  _8 = x[2];
  _12 = x[3];
  _23 = {_1, _4, _8, _12};
  vect__3.10_27 = _23 << _22;
  vect__4.11_28 = vect__2.5_21 + vect__3.10_27;
  MEM <vector(4) int> [(int *)&x] = vect__4.11_28;

and

        movdqa  j(%rip), %xmm2
        movl    x(%rip), %edx
        movd    x(%rip), %xmm0
        movd    x+12(%rip), %xmm3
        movd    %xmm2, %ecx
        sall    %cl, %edx
        addl    %ecx, %edx
        movslq  %ecx, %rcx
        movd    %edx, %xmm1
        movq    %rcx, %xmm4
        punpckldq       %xmm1, %xmm0
        movd    x+8(%rip), %xmm1
        punpckldq       %xmm3, %xmm1
        shufps  $68, %xmm1, %xmm0
        pslld   %xmm4, %xmm0
        paddd   %xmm2, %xmm0
        movaps  %xmm0, x(%rip)
        ret

vs

        movl    j(%rip), %ecx
        movl    x(%rip), %eax
        sall    %cl, %eax
        addl    %ecx, %eax
        movl    %eax, x(%rip)
        sall    %cl, %eax
        addl    j+4(%rip), %eax
        movl    %eax, x+4(%rip)
        movl    x+8(%rip), %eax
        sall    %cl, %eax
        addl    j+8(%rip), %eax
        movl    %eax, x+8(%rip)
        movl    x+12(%rip), %eax
        sall    %cl, %eax
        addl    j+12(%rip), %eax
        movl    %eax, x+12(%rip)
        ret

Reply via email to