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

--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> ---
t.c:15:35: note:   vect_compute_data_ref_alignment: 
t.c:15:35: note:   force alignment of *_3
...
t.c:15:35: note:   ==> examining statement: _4 = *_3;
t.c:15:35: note:   vect_model_load_cost: aligned.

the vectorizer over-aligns 'b' in ensure_base_align but RTL expansion
allocates the variable to

(gdb) p $rsp + 0xc
$1 = (void *) 0x7fffffffde0c

besides that, tree_could_trap_p is overly optimistic:

    case MEM_REF:
...
      if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
        {
...
          tree size = DECL_SIZE_UNIT (base);
          if (size == NULL_TREE
              || !poly_int_tree_p (size)
              || maybe_le (wi::to_poly_offset (size), off))
            return true;
          /* Now we are sure the first byte of the access is inside
             the object.  */
          return false;

but taking into account alignment it could still conclude the access doesn't
trap.  tree_could_trap_p does not track the overall offset from all
handled-components, so it can only be optimistic in case the MEM_REF
would be fully within the decl.

So there are two bugs here - RTL expansion not honoring stack var alignment
and tree_could_trap_p being overly optimistic.

RTL expansion drops user alignment on the floor by expanding the variable
as a register and later we do

12147           /* Otherwise, if this is a constant or the object is not in
memory
12148              and need be, put it there.  */
12149           else if (CONSTANT_P (op0) || (!MEM_P (op0) && must_force_mem))
12150             {
12151               memloc = assign_temp (TREE_TYPE (tem), 1, 1);

but that assigns a stack temp for 'int' without the required over-alignment
of the MEM.  This is because we go BIT_FIELD_REF expansion again which
doesn't really honor an over-aligned access as we build it and later we
restore the slots alignment based on the BIT_FIELD_REF type.  IMO the error
is again in the

        /* Handle expansion of non-aliased memory with non-BLKmode.  That
           might end up in a register.  */
        if (mem_ref_refers_to_non_mem_p (exp))
          {
            if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0))
              {
                temp = assign_stack_temp (DECL_MODE (base),
                                          GET_MODE_SIZE (DECL_MODE (base)));
                store_expr (base, temp, 0, false, false);
                temp = adjust_address (temp, TYPE_MODE (type), offset);
                if (TYPE_MODE (type) == BLKmode)
                  set_mem_size (temp, int_size_in_bytes (type));
                return temp;
              }
            exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type),
                          bitsize_int (offset * BITS_PER_UNIT));
            REF_REVERSE_STORAGE_ORDER (exp) = reverse;
            return expand_expr (exp, target, tmode, modifier);

path.  The BIT_FIELD_REF path hopes to avoid allocating a temporary on the
stack, but as seen this doesn't work with respect to alignment (neither
would the mode based temporary allocation, but that could be fixed).

Reply via email to