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

--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
We're expanding <retval> = _2 via expand_return:

    arg:0 <result_decl 0x7ffff6c88000 D.4676 type <pointer_type 0x7ffff6e20150>
        unsigned ignored regdecl SI t.c:1:1 size <integer_cst 0x7ffff6e15120
32> unit-size <integer_cst 0x7ffff6e15138 4>
        align:32 warn_if_not_align:0 context <function_decl 0x7ffff6c71800 g>
        (reg/f:SI 114 [ <retval> ])>
    arg:1 <ssa_name 0x7ffff6e0d828 type <pointer_type 0x7ffff6e20150>
        visited
        def_stmt _2 = MEM[(int * *)&obj + 4294967295B];
        version:2
        ptr-info 0x7ffff6c6ed80>>

where DECL_RESULT has (reg/f:SI 114 [ <retval> ])

so we go

  else if (retval_rhs != 0
           && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
           && (REG_P (result_rtl)
               || (GET_CODE (result_rtl) == PARALLEL)))
    {
      /* Compute the return value into a temporary (usually a pseudo reg).  */
      val
        = assign_temp (TREE_TYPE (DECL_RESULT (current_function_decl)), 0, 1);
      val = expand_expr (retval_rhs, val, GET_MODE (val), EXPAND_NORMAL);
      val = force_not_mem (val);
      expand_value_return (val);

where assign_temp gets us (reg:SI 116) but expand_expr () ends up expanding
to

(mem/c:SI (plus:SI (reg/f:SI 109 virtual-stack-vars)
        (const_int -5 [0xfffffffffffffffb])) [0  S4 A8])

because we run into

    case MEM_REF:
      {
...
            if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0))
              {
                temp = assign_stack_temp (DECL_MODE (base),
                                          GET_MODE_SIZE (DECL_MODE (base)));

which creates (mem/c:SI (plus:SI (reg/f:SI 109 virtual-stack-vars)
        (const_int -4 [0xfffffffffffffffc])) [0  S4 A32])
but then

                temp = adjust_address (temp, TYPE_MODE (type), offset);

makes the MEM unaligned (offset is minus one).  But the original ref
was aligned (bogously).  We already do

                if (TYPE_MODE (type) == BLKmode)
                  set_mem_size (temp, int_size_in_bytes (type));

I suppose we can similarly do a set_mem_align though in this case
get_object_alignment on the MEM_REF correctly returns 8.  I suppose
we fail to properly go the extract_bitfield path here that we'd chosen
when going expand_assignment or previous to the -1 offset handling
when dispatching to BIT_FIELD_REF expansion (which cannot handle a -1
offset correctly - we've generated "wrong" code before).

Reply via email to