Fix expand_expr_real_1 handling of BLKmode bitfield references
authorRichard Sandiford <richard.sandiford@linaro.org>
Mon, 4 Jun 2018 15:02:07 +0000 (15:02 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 4 Jun 2018 15:02:07 +0000 (15:02 +0000)
commit8566678b9da3db996f7566ecb691be07ff376c8f
tree140b2b6b07bda90ed0314c7223b1b643c120011a
parent1fc9aa543f41a1485187c96806950795a7966974
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.

From-SVN: r261150
gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/extract_5.c [new file with mode: 0644]