diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2024-02-27 18:01:00 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2024-02-27 18:08:56 +0100 |
commit | 27534e793e51560213cef999df66a7214ee7502a (patch) | |
tree | 7ecd42c81897ee1ee2e95e22c82c64ab081bea25 /gcc/testsuite/gnat.dg | |
parent | 8b3f1edf9b38cb8a88c0a101a675d092bf6135d2 (diff) | |
download | gcc-27534e793e51560213cef999df66a7214ee7502a.zip gcc-27534e793e51560213cef999df66a7214ee7502a.tar.gz gcc-27534e793e51560213cef999df66a7214ee7502a.tar.bz2 |
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.
Diffstat (limited to 'gcc/testsuite/gnat.dg')
-rw-r--r-- | gcc/testsuite/gnat.dg/opt104.adb | 22 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt104.ads | 40 |
2 files changed, 62 insertions, 0 deletions
diff --git a/gcc/testsuite/gnat.dg/opt104.adb b/gcc/testsuite/gnat.dg/opt104.adb new file mode 100644 index 0000000..1548c3e --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt104.adb @@ -0,0 +1,22 @@ +-- { dg-do compile } +-- { dg-options "-O -gnatws" } + +package body Opt104 is + + procedure Proc (R : Rec) is + Data : Packed_Rec; + + begin + case R.D is + when True => + for I in 1 .. R.Len loop + exit; + end loop; + + when False => + null; + end case; + end; + +end Opt104; + diff --git a/gcc/testsuite/gnat.dg/opt104.ads b/gcc/testsuite/gnat.dg/opt104.ads new file mode 100644 index 0000000..a177ed0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt104.ads @@ -0,0 +1,40 @@ +package Opt104 is + + type Time is record + S : Integer; + B1 : Boolean; + B2 : Boolean; + B3 : Boolean; + B4 : Boolean; + B5 : Boolean; + B6 : Boolean; + end record; + + Zero_Time : constant Time := + (S => 0, + B1 => False, + B2 => False, + B3 => False, + B4 => False, + B5 => False, + B6 => False); + + type Root is tagged null record; + + type Packed_Rec is record + R : Root; + B : Boolean; + T : Time := Zero_Time; + end record; + pragma Pack (Packed_Rec); + + type Rec (D : Boolean) is record + case D is + when True => Len : Integer; + when False => null; + end case; + end record; + + procedure Proc (R : Rec); + +end Opt104; |