Hi,
this is a regression present on all the active branches and a sibling of:
https://gcc.gnu.org/pipermail/gcc-patches/2024-February/646628.html
during GIMPLE pass: dse
+===========================GNAT BUG DETECTED==============================+
| 16.0.1 20260331 (experimental) [master r16-8354-gbf6989de817] (x86_64-suse-
linux) GCC error:|
| in exact_div, at poly-int.h:2179 |
| Error detected around opt107.adb:26:11 |
| Compiling opt107.adb
So at least one caller of compute_trims, namely maybe_trim_constructor_store,
expects ref->size to be a multiple of a byte for trimming, and that's probably
the case for others in practice, from a cursory reading. Therefore the patch
adds the same test on ref->size as the one added to ref->offset above.
Tested on x86-64/Linux, OK for all the active branches?
2026-03-31 Eric Botcazou <[email protected]>
* tree-ssa-dse.cc (compute_trims): Bail out if ref->size is not
byte aligned either.
2026-03-31 Eric Botcazou <[email protected]>
* gnat.dg/opt107.adb: New test.
* gnat.dg/opt107_pkg.ads: New helper.
--
Eric Botcazoudiff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
index cc381b4cd7b..58cfa9ec129 100644
--- a/gcc/tree-ssa-dse.cc
+++ b/gcc/tree-ssa-dse.cc
@@ -423,8 +423,10 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail,
the bitmap extends through ref->max_size, so we know that in the original
bitmap bits 0 .. ref->max_size were true. But we need to check that this
covers the bytes of REF exactly. */
- const unsigned int align = known_alignment (ref->offset);
- if ((align > 0 && align < BITS_PER_UNIT)
+ const unsigned int offset_align = known_alignment (ref->offset);
+ const unsigned int size_align = known_alignment (ref->size);
+ if ((offset_align > 0 && offset_align < BITS_PER_UNIT)
+ || (size_align > 0 && size_align < BITS_PER_UNIT)
|| !known_eq (ref->size, ref->max_size))
return;
with System;
with Unchecked_Conversion;
package Opt107_Pkg is
Word_Size : constant := 32;
type Word_Type is mod 2 ** Word_Size;
for Word_Type'Size use Word_Size;
Word : constant := Word_Size / System.Storage_Unit;
Halfword_Size : constant := Word_Size / 2;
type Halfword_Type is range 0 .. 2 ** Halfword_Size - 1;
for Halfword_Type'Size use Halfword_Size;
type One_Bit_Type is mod 2 ** 1;
for One_Bit_Type'Size use 1;
type Four_Bit_Type is mod 2 ** 4;
for Four_Bit_Type'Size use 4;
type Seven_Bit_Type is mod 2 ** 7;
for Seven_Bit_Type'Size use 7;
type Eight_Bit_Type is mod 2 ** 8;
for Eight_Bit_Type'Size use 8;
type Twelve_Bit_Type is mod 2 ** 12;
for Twelve_Bit_Type'Size use 12;
type Thirty_One_Bit_Type is mod 2 ** 31;
for Thirty_One_Bit_Type'Size use 31;
type W0_Type is record
A : Eight_Bit_Type;
B : Eight_Bit_Type;
C : Halfword_Type;
end record;
for W0_Type use record
A at Word * 0 range 24 .. 31;
B at Word * 0 range 16 .. 23;
C at Word * 0 range 0 .. 15;
end record;
for W0_Type'Size use Word_Size;
type A_Type is (A0, A1);
for A_Type use (A0 => 0, A1 => 1);
for A_Type'Size use 1;
type B_Type is (B_A_1,
B_A_2,
B_A_3,
B_A_4,
B_A_5,
B_A_6,
B_A_7,
B_A_8,
B_B_1,
B_B_2,
B_B_3,
B_B_4,
B_B_5,
B_B_6,
B_B_7,
B_B_8);
for B_Type use (B_A_1 => 8#00#,
B_A_2 => 8#01#,
B_A_3 => 8#02#,
B_A_4 => 8#03#,
B_A_5 => 8#04#,
B_A_6 => 8#05#,
B_A_7 => 8#06#,
B_A_8 => 8#07#,
B_B_1 => 8#10#,
B_B_2 => 8#11#,
B_B_3 => 8#12#,
B_B_4 => 8#13#,
B_B_5 => 8#14#,
B_B_6 => 8#15#,
B_B_7 => 8#16#,
B_B_8 => 8#17#);
for B_Type'Size use 8;
type C_Type is (C_A, C_B);
for C_Type use (C_A => 0, C_B => 2);
for C_Type'Size use 4;
type D_Type is record
Spare : Twelve_Bit_Type;
D_A : One_Bit_Type;
D_B : One_Bit_Type;
D_C : One_Bit_Type;
D_D : One_Bit_Type;
end record;
for D_Type use record
Spare at 0 range 4 .. 15;
D_A at 0 range 3 .. 3;
D_B at 0 range 2 .. 2;
D_C at 0 range 1 .. 1;
D_D at 0 range 0 .. 0;
end record;
for D_Type'Size use Halfword_Size;
type E_Type is record
Spare : Seven_Bit_Type;
E_A : One_Bit_Type;
E_B : One_Bit_Type;
E_C : One_Bit_Type;
E_D : One_Bit_Type;
E_E : One_Bit_Type;
E_F : One_Bit_Type;
E_G : One_Bit_Type;
E_H : One_Bit_Type;
end record;
for E_Type use record
Spare at 0 range 8 .. 14;
E_A at 0 range 7 .. 7;
E_B at 0 range 6 .. 6;
E_C at 0 range 5 .. 5;
E_D at 0 range 4 .. 4;
E_E at 0 range 3 .. 3;
E_F at 0 range 2 .. 2;
E_G at 0 range 1 .. 1;
E_H at 0 range 0 .. 0;
end record;
for E_Type'Size use 15;
type Rec is record
W0 : W0_Type;
W1A : B_Type;
W1B : Four_Bit_Type;
W1C : C_Type;
W1D : D_Type;
W2A : A_Type;
W2B : E_Type;
W2C : Halfword_Type;
end record;
for Rec use record
W0 at Word * 0 range 0 .. 31;
W1A at Word * 1 range 24 .. 31;
W1B at Word * 1 range 20 .. 23;
W1C at Word * 1 range 16 .. 19;
W1D at Word * 1 range 0 .. 15;
W2A at Word * 2 range 31 .. 31;
W2B at Word * 2 range 16 .. 30;
W2C at Word * 2 range 0 .. 15;
end record;
for Rec'Size use 6 * Halfword_Size;
end Opt107_Pkg;
-- { dg-do compile }
-- { dg-options "-O" }
with Opt107_Pkg; use Opt107_Pkg;
function Opt107 return Rec is
R : Rec;
begin
R.W1A := B_A_7;
R.W1B := 0;
R.W1C := C_A;
R.W1D := (Spare => 0,
D_A => 0,
D_B => 0,
D_C => 0,
D_D => 0);
R.W2B := (Spare => 0,
E_A => 0,
E_B => 0,
E_C => 0,
E_D => 0,
E_E => 0,
E_F => 0,
E_G => 0,
E_H => 0);
return R;
end;