]> git.ipfire.org Git - thirdparty/gcc.git/commit
Fix internal error on non-byte-aligned reference in GIMPLE DSE
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 27 Feb 2024 17:01:00 +0000 (18:01 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Tue, 27 Feb 2024 18:50:47 +0000 (19:50 +0100)
commit27abb0ed5890455f876b75e37a06dd679c78baf7
tree29ce1f1b3ee1d2a63f61d97c6b4c86982c57e6ec
parente8c1c2b6c220bc3518c11e11af5a8c6ca1cdf7e8
Fix internal error on non-byte-aligned reference in GIMPLE DSE

This is a regression present on the mainline, 13 and 12 branches.  For the
attached Ada case, it's a tree checking failure on the mainline at -O:

+===========================GNAT BUG DETECTED==============================+
| 14.0.1 20240226 (experimental) [master r14-9171-g4972f97a265]  GCC error:|
| tree check: expected tree that contains 'decl common' structure,         |
| have 'component_ref' in tree_could_trap_p, at tree-eh.cc:2733        |
| Error detected around /home/eric/cvs/gcc/gcc/testsuite/gnat.dg/opt104.adb:

Time is a 10-byte record and Packed_Rec.T is placed at bit-offset 65 because
of the packing. so tree-ssa-dse.cc:setup_live_bytes_from_ref has computed a
const_size of 88 from ref->offset of 65 and ref->max_size of 80.

Then in tree-ssa-dse.cc:compute_trims:

411       int last_live = bitmap_last_set_bit (live);
(gdb) next
412       if (ref->size.is_constant (&const_size))
(gdb)
414           int last_orig = (const_size / BITS_PER_UNIT) - 1;
(gdb)
418           *trim_tail = last_orig - last_live;

(gdb) call debug_bitmap (live)
n_bits = 256, set = {0 1 2 3 4 5 6 7 8 9 10 }
(gdb) p last_live
$33 = 10
(gdb) p const_size
$34 = 80
(gdb) p last_orig
$35 = 9
(gdb) p *trim_tail
$36 = -1

In other words, compute_trims is overlooking the alignment adjustments that
setup_live_bytes_from_ref applied earlier.  Moveover it reads:

  /* We use sbitmaps biased such that ref->offset is bit zero and the bitmap
     extends through ref->size.  So we know that in the original bitmap
     bits 0..ref->size were true.  We don't actually need the bitmap, just
     the REF to compute the trims.  */

but setup_live_bytes_from_ref used ref->max_size instead of ref->size.

It appears that all the callers of compute_trims assume that ref->offset is
byte aligned and that the trimmed bytes are relative to ref->size, so the
patch simply adds an early return if either condition is not fulfilled.

gcc/
* tree-ssa-dse.cc (compute_trims): Fix description.  Return early
if either ref->offset is not byte aligned or ref->size is not known
to be equal to ref->max_size.
(maybe_trim_complex_store): Fix description.
(maybe_trim_constructor_store): Likewise.
(maybe_trim_partially_dead_store): Likewise.

gcc/testsuite/
* gnat.dg/opt104.ads, gnat.dg/opt104.adb: New test.
gcc/testsuite/gnat.dg/opt104.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt104.ads [new file with mode: 0644]
gcc/tree-ssa-dse.cc