Michael Matz <matz at gcc dot> changed:

           What    |Removed                     |Added
                 CC|                            |rakdver at gcc dot,
                   |                            |spop at gcc dot

--- Comment #5 from Michael Matz <matz at gcc dot> 2010-09-24 16:06:03 
UTC ---
This patch will set the correct misalign info on that data-reference:

Index: tree-vect-data-refs.c
--- tree-vect-data-refs.c       (revision 164476)
+++ tree-vect-data-refs.c       (working copy)
@@ -900,6 +900,19 @@ vect_compute_data_ref_alignment (struct
              || (TREE_CODE (base) == VAR_DECL
                  && DECL_ALIGN (base) >= TYPE_ALIGN (vectype)));

+  /* If this is a backward running DR then first access in the larger
+     vectype actually is N-1 elements before the address in the DR.
+     Adjust misalign accordingly.  */
+  if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0)
+    {
+      tree offset = ssize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
+      /* DR_STEP(dr) is the same as -TYPE_SIZE of the scalar type,
+         otherwise we wouldn't be here.  */
+      offset = fold_build2 (MULT_EXPR, ssizetype, offset, DR_STEP (dr));
+      /* PLUS because DR_STEP was negative.  */
+      misalign = size_binop (PLUS_EXPR, misalign, offset);
+    }
   /* Modulo alignment.  */
   misalign = size_binop (FLOOR_MOD_EXPR, misalign, alignment);

Unfortunately this will later result in an ICE during peeling.  It
wants to peel these data-refs that now are known misaligned, and during cost
computation changes data-refs that have the same alignment state to be
aligned too (makes sense because those data-refs will also be aligned when
the to-be-peeled DR is aligned).

Unfortunately the STMT_VINFO_SAME_ALIGN_REFS contains bogus reference,
because ultimately the distance vectors are wrong:

  (stmt_a = D.2097_46 = ibuf[D.2094_43];)
  (stmt_b = D.2100_64 = ibuf[D.2099_63];)
  (chrec_a = {64, +, -1}_2)
  (chrec_b = {64, +, 1}_2)
  (overlaps_a = [0]
  (overlaps_b = [0]
  (overlap_iterations_a = [0]
  (overlap_iterations_b = [0]
  dist_vector = (  0  )

So, we have two DRs running in opposite directions, which happen to
have the initial element in common (index 64), but afterwards diverge and
have nothing in common anymore.  So overlap_iterations_a/b is correct.
But the distance vector is 0, meaning 'same in all iterations'.  That
is used to initialize STMT_VINFO_SAME_ALIGN_REFS in
vect_find_same_alignment_drs .

Obviously the distance vector should be unknown (it could be a chrec, if
we really want, namely {0, +, 2}_2, but we don't do anything with such
distances).  I tried to determine why it is wrong, it's ultimately
coming from SUB_DISTANCE of that DDR, computed like so

          subscript = DDR_SUBSCRIPT (ddr, i);
          cf_a = SUB_CONFLICTS_IN_A (subscript);
          cf_b = SUB_CONFLICTS_IN_B (subscript);

          fn_a = common_affine_function (cf_a);
          fn_b = common_affine_function (cf_b);
          if (!fn_a || !fn_b)
              SUB_DISTANCE (subscript) = chrec_dont_know;
          diff = affine_fn_minus (fn_a, fn_b);

          if (affine_function_constant_p (diff))
            SUB_DISTANCE (subscript) = affine_function_base (diff);
            SUB_DISTANCE (subscript) = chrec_dont_know;

And this is baffling me a bit.  How could it be correct to
determine a distance vector from only the conflict functions?  Doing so
ignores all non-conflicting accesses, although they can (and indeed here do)
influence the distance too.

CCing Zdenek and Sebastian, maybe they have some insight in the latter
problem, as those aren't really related to the vectorizer.

Configure bugmail:
------- You are receiving this mail because: -------
You are on the CC list for the bug.

Reply via email to