aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gnat.dg
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2024-02-27 18:01:00 +0100
committerEric Botcazou <ebotcazou@adacore.com>2024-02-27 18:08:56 +0100
commit27534e793e51560213cef999df66a7214ee7502a (patch)
tree7ecd42c81897ee1ee2e95e22c82c64ab081bea25 /gcc/testsuite/gnat.dg
parent8b3f1edf9b38cb8a88c0a101a675d092bf6135d2 (diff)
downloadgcc-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.adb22
-rw-r--r--gcc/testsuite/gnat.dg/opt104.ads40
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;