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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
struct LeafBucket {
     int coords[3][32];
};

void foo (unsigned long size, struct LeafBucket *bucket)
{
  bucket = __builtin_assume_aligned (bucket, 64);
  for (unsigned long i = size; i < 32; ++i)
    for (unsigned long d = 0; d < 3; ++d)
      bucket->coords[d][i] = 1;
}

is analyzed correctly (-fdisable-tree-cunrolli).  Likewise

struct LeafBucket {
     int coords[3][32];
     unsigned int ids[32];
};

struct LeafBucket bucket __attribute__((aligned(64)));

void foo (unsigned long size)
{
  for (unsigned long i = size; i < 32; ++i)
    for (unsigned long d = 0; d < 3; ++d)
      bucket.coords[d][i] = 1;
}


It would be nice to have a smaller testcase w/o so much of the standard
library.
But yes, it seems somehow the offset from 'size' is not honored.  We have

(gdb) p *dr_info->dr
$3 = {stmt = <gimple_assign 0x7ffff3b52c60>, ref = <array_ref 0x7ffff3ac3620>, 
  aux = 0x0, is_read = false, is_conditional_in_stmt = false, alias = {
    ptr_info = 0x7ffff3a62930}, innermost = {
    base_address = <pointer_plus_expr 0x7ffff3b6d0c8>, 
    offset = <nop_expr 0x7ffff3b68dc0>, init = <integer_cst 0x7ffff3b24e28>, 
    step = <integer_cst 0x7ffff3b24ee8>, base_alignment = 64, 
    base_misalignment = 0, offset_alignment = 4, step_alignment = 128}, 
  indices = {base_object = <mem_ref 0x7ffff3b636e0>, access_fns = {
      m_vec = 0x58109e0 = {0x7ffff3b6d118, 0x7ffff3b6cb68, 0x7ffff761b378}}, 
    unconstrained_base = false}, alt_indices = {base_object = <tree 0x0>, 
    access_fns = {m_vec = 0x0}, unconstrained_base = false}}

see offset_alignment.  But we only check drb for that (vect_dr_behavior):

(gdb) p *drb
$5 = {base_address = <pointer_plus_expr 0x7ffff3b6db68>, 
  offset = <integer_cst 0x7ffff6011a38>, init = <integer_cst 0x7ffff3b24e28>, 
  step = <integer_cst 0x7ffff60119c0>, base_alignment = 64, 
  base_misalignment = 0, offset_alignment = 128, step_alignment = 4}

which have different base addresses:

(gdb) p debug_generic_expr (drb->base_address)
(struct element_type &) _54 + (((sizetype) node_idx_512 - (sizetype) _589) *
128 + (sizetype) size_564) * 4

(gdb) p debug_generic_expr (dr_info->dr.innermost.base_address)
_54 + ((sizetype) node_idx_512 - (sizetype) _589) * 512
(gdb) p debug_generic_expr (dr_info->dr.innermost.offset)
(ssizetype) ((sizetype) i_492 * 4)

so to me it seems that 'drb' has somehow wrong alignments and

  if (drb->offset_alignment < vect_align_c
      || !step_preserves_misalignment_p
      /* We need to know whether the step wrt the vectorized loop is
         negative when computing the starting misalignment below.  */
      || TREE_CODE (drb->step) != INTEGER_CST)
    {
      if (dump_enabled_p ()) 
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "Unknown alignment for access: %T\n", ref); 
      return;

should have catched this or drb->misalignment should be set (size is unknown,
so alignment should be 4).

Oh, so I think the issue is that we do

          /* Build a reference to the first location accessed by the
             inner loop: *(BASE + INIT + OFFSET).  By construction,
             this address must be invariant in the inner loop, so we
             can consider it as being used in the outer loop.  */
          tree base = unshare_expr (DR_BASE_ADDRESS (dr));
          tree offset = unshare_expr (DR_OFFSET (dr)); 
          tree init = unshare_expr (DR_INIT (dr));
          tree init_offset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset),
                                          init, offset);
          tree init_addr = fold_build_pointer_plus (base, init_offset);
          tree init_ref = build_fold_indirect_ref (init_addr);

          if (dump_enabled_p ())
            dump_printf_loc (MSG_NOTE, vect_location,
                             "analyze in outer loop: %T\n", init_ref);

          opt_result res
            = dr_analyze_innermost (&STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info),
                                    init_ref, loop, stmt_info->stmt);

and dr_analyze_innermost does get_inner_reference and
get_object_alignment_1 on the base (which it returns literally).
But we build

 <indirect_ref 0x7ffff3b6e0a0
    type <record_type 0x7ffff420c348 element_type cxx-odr-p type_5 type_6 BLK
        size <integer_cst 0x7ffff4672cd8 constant 4096>
        unit-size <integer_cst 0x7ffff4672cc0 constant 512>
        user align:512 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff4690f18

which is of course not correct.

Reply via email to