diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2018-06-04 15:02:07 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-06-04 15:02:07 +0000 |
commit | 8566678b9da3db996f7566ecb691be07ff376c8f (patch) | |
tree | 140b2b6b07bda90ed0314c7223b1b643c120011a | |
parent | 1fc9aa543f41a1485187c96806950795a7966974 (diff) | |
download | gcc-8566678b9da3db996f7566ecb691be07ff376c8f.zip gcc-8566678b9da3db996f7566ecb691be07ff376c8f.tar.gz gcc-8566678b9da3db996f7566ecb691be07ff376c8f.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/expr.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/extract_5.c | 71 |
4 files changed, 83 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eea0298..7854103 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-06-04 Richard Sandiford <richard.sandiford@linaro.org> + + * 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. + 2018-06-04 Jakub Jelinek <jakub@redhat.com> PR target/85832 @@ -10579,6 +10579,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, to a larger size. */ must_force_mem = (offset || mode1 == BLKmode + || (mode == BLKmode + && !int_mode_for_size (bitsize, 1).exists ()) || maybe_gt (bitpos + bitsize, GET_MODE_BITSIZE (mode2))); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 043a4f4..459958e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-06-04 Richard Sandiford <richard.sandiford@linaro.org> + + * gcc.target/aarch64/sve/extract_5.c: New test. + 2018-06-04 Jakub Jelinek <jakub@redhat.com> PR target/85832 diff --git a/gcc/testsuite/gcc.target/aarch64/sve/extract_5.c b/gcc/testsuite/gcc.target/aarch64/sve/extract_5.c new file mode 100644 index 0000000..652ba83 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/extract_5.c @@ -0,0 +1,71 @@ +/* Originally from gcc.dg/vect/vect-alias-check-10.c. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msve-vector-bits=512" } */ + +#define N 87 +#define M 6 + +typedef signed char sc; +typedef unsigned char uc; +typedef signed short ss; +typedef unsigned short us; +typedef int si; +typedef unsigned int ui; +typedef signed long long sll; +typedef unsigned long long ull; + +#define FOR_EACH_TYPE(M) \ + M (sc) M (uc) \ + M (ss) M (us) \ + M (si) M (ui) \ + M (sll) M (ull) \ + M (float) M (double) + +#define TEST_VALUE(I) ((I) * 5 / 2) + +#define ADD_TEST(TYPE) \ + void __attribute__((noinline, noclone)) \ + test_##TYPE (TYPE *a, int step) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + a[i * step + 0] = a[i * step + 0] + 1; \ + a[i * step + 1] = a[i * step + 1] + 2; \ + a[i * step + 2] = a[i * step + 2] + 4; \ + a[i * step + 3] = a[i * step + 3] + 8; \ + } \ + } \ + void __attribute__((noinline, noclone)) \ + ref_##TYPE (TYPE *a, int step) \ + { \ + for (int i = 0; i < N; ++i) \ + { \ + a[i * step + 0] = a[i * step + 0] + 1; \ + a[i * step + 1] = a[i * step + 1] + 2; \ + a[i * step + 2] = a[i * step + 2] + 4; \ + a[i * step + 3] = a[i * step + 3] + 8; \ + asm volatile (""); \ + } \ + } + +#define DO_TEST(TYPE) \ + for (int j = -M; j <= M; ++j) \ + { \ + TYPE a[N * M], b[N * M]; \ + for (int i = 0; i < N * M; ++i) \ + a[i] = b[i] = TEST_VALUE (i); \ + int offset = (j < 0 ? N * M - 4 : 0); \ + test_##TYPE (a + offset, j); \ + ref_##TYPE (b + offset, j); \ + if (__builtin_memcmp (a, b, sizeof (a)) != 0) \ + __builtin_abort (); \ + } + +FOR_EACH_TYPE (ADD_TEST) + +int +main (void) +{ + FOR_EACH_TYPE (DO_TEST) + return 0; +} |