Fix expand_expr_real_1 handling of BLKmode bitfield references
commit5228d413970208645b7a3397465d682335ddd9ee
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Jun 2018 15:02:07 +0000 (4 15:02 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Jun 2018 15:02:07 +0000 (4 15:02 +0000)
tree140b2b6b07bda90ed0314c7223b1b643c120011a
parent84b3cf31c302f60bb9fc56542e4bbaba0b1f7a01
Fix expand_expr_real_1 handling of BLKmode bitfield references

The handling of bitfield references in expand_expr_real_1 includes:

            machine_mode ext_mode = mode;

            if (ext_mode == BLKmode
                && ! (target != 0 && MEM_P (op0)
                      && MEM_P (target)
                      && multiple_p (bitpos, BITS_PER_UNIT)))
              ext_mode = int_mode_for_size (bitsize, 1).else_blk ();

            if (ext_mode == BLKmode)
              {
                [...]
                gcc_assert (MEM_P (op0)

Here "mode" is the TYPE_MODE of the result, so when mode == BLKmode,
the target must be a MEM if nonnull, since no other rtl objects can
have BLKmode.  But there's no guarantee that the source value op0 is also
BLKmode and thus also a MEM: we can reach the assert for any source if
the bitsize being extracted is larger than the largest integer mode
(or larger than MAX_FIXED_MODE_SIZE).

This triggered for SVE with -msve-vector-bits=512, where we could
sometimes try to extract a BLKmode value from a 512-bit vector,
and where int_mode_for_size would rightly fail for large bitsizes.

The patch reuses the existing:

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

to handle this case.

2018-05-29  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* expr.c (expand_expr_real_1): Force the operand into memory if
its TYPE_MODE is BLKmode and if there is no integer mode for
the number of bits being extracted.

gcc/testsuite/
* gcc.target/aarch64/sve/extract_5.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@261150 138bc75d-0d04-0410-961f-82ee72b054a4
gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/extract_5.c [new file with mode: 0644]