diff options
| -rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr97764.c | 14 | ||||
| -rw-r--r-- | gcc/tree-ssa-sccvn.c | 5 |
2 files changed, 18 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97764.c b/gcc/testsuite/gcc.c-torture/execute/pr97764.c new file mode 100644 index 0000000..4ceaab8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr97764.c @@ -0,0 +1,14 @@ +/* PR tree-optimization/97764 */ +/* { dg-require-effective-target int32plus } */ + +struct S { int b : 3; int c : 28; int d : 1; }; + +int +main () +{ + struct S e = {}; + e.c = -1; + if (e.d) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 24bbd8d..8c93e51 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2039,12 +2039,12 @@ vn_walk_cb_data::push_partial_def (pd_data pd, } else { - size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT); if (pd.offset >= 0) { /* LSB of this_buffer[0] byte should be at pd.offset bits in buffer. */ unsigned int msk; + size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT); amnt = pd.offset % BITS_PER_UNIT; if (amnt) shift_bytes_in_array_left (this_buffer, len + 1, amnt); @@ -2074,6 +2074,9 @@ vn_walk_cb_data::push_partial_def (pd_data pd, { amnt = (unsigned HOST_WIDE_INT) pd.offset % BITS_PER_UNIT; if (amnt) + size -= BITS_PER_UNIT - amnt; + size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT); + if (amnt) shift_bytes_in_array_left (this_buffer, len + 1, amnt); } memcpy (p, this_buffer + (amnt != 0), size / BITS_PER_UNIT); |
