On Mon, Aug 24, 2026 at 8:53 AM Eric Botcazou <[email protected]> wrote:
>
> Hi,
>
> This is a regression present on the mainline, 16 and 15 branches.  The problem
> is that the DSE3 pass incorrectly deletes a store to an up-level reference to
> an array with negative low bound:
>
> Deleted dead store: FRAME.19.s[0]{lb: 18446744073709551613 sz: 8} = 0.0;
>
> because IPA modref incorrectly flags it as dead for this call:
>
> ipa-modref: call stmt opt110.term (1, 0,
> 2.37000000000000010658141036401502788066864013671875e+0,
> 2.79323000000000001818989403545856475830078125e+3); [static-chain: &FRAME.19]
> ipa-modref: call to Opt110.Term/3 does not use ref: FRAME.19.s[0]{lb:
> 18446744073709551613 sz: 8} alias sets: 13->11
>
> The array at stake is declared with a negative low bound:
>
> N : constant := 3;
>
> S : array (-N..0) of REAL;
>
>
> The origin of the problem is visible when you compare the modref1 and modref2
> dump files:
>
>  - Analyzing load: CHAIN.20_21(D)->s[_7]{lb: 18446744073709551613 sz: 8}
>  (can throw; marking side effects)    - Recording base_set=0 ref_set=0  Static
> chain param offset:0 offset:960 size:64 max_size:256
>
> vs
>
>  - Analyzing load: CHAIN.20_12(D)->s[_4]{lb: 18446744073709551613 sz: 8}
>  (can throw; marking side effects)    - Recording base_set=0 ref_set=0  Static
> chain param offset:0 offset:960 size:64 max_size:192
>
> The max_size has been incorrectly shrunk from 256 to 192 bits, the missing 64
> bits being the FRAME.19.s[0]{lb: 18446744073709551613 sz: 8} element.
>
>
> The problematic code is in get_ref_base_and_extent:
>
>         if (TREE_CODE (index) == SSA_NAME
>             && (low_bound = array_ref_low_bound (exp),
>                 poly_int_tree_p (low_bound))
>             && (unit_size = array_ref_element_size (exp),
>                 TREE_CODE (unit_size) == INTEGER_CST)
>             && query->range_of_expr (vr, index)
>             && !vr.varying_p ()
>             && !vr.undefined_p ())
>           {
>             wide_int min = vr.lower_bound ();
>             wide_int max = vr.upper_bound ();
>             poly_offset_int lbound = wi::to_poly_offset (low_bound);
>             /* Try to constrain maxsize with range information.  */
>
> It uses the range of the index expression to constrain the maxsize:
>
> [irange] sizetype [0, 0][18446744073709551613, +INF]
>
> but that's not correct in the general case, the correct range being instead
> the range of the difference between the low bound and the index expression,
> as implemented by the model computation in get_inner_reference:
>
> [irange] sizetype [0, 3]
>
> Of course this makes no difference for the C family of languages where the low
> bound is always 0.  There is also the problematic case where this low bound is
> a poly_int instead of an integer, given that ranges do not support poly_ints,
> but I'm not sure whether that's a practical concern; that's why I'm proposing
> two versions of the fix, one filtering it out and the other keeping it.
>
> Bootstrapped/regtested on x86-64/Linux, OK for the mainline as well as the 16
> and 15 branches?  If so, which version?

The first version, requiring INTEGER_CST low_bound.  But ...

                    && query->range_of_expr (vr, index)
                    && !vr.varying_p ()
-                   && !vr.undefined_p ())
+                   && !vr.undefined_p ()
+                   && (integer_zerop (low_bound)
+                       || query->range_of_expr
+                            (vr,
+                             build2 (MINUS_EXPR, TREE_TYPE (index),
+                                     index, low_bound))))

can you try to use

  range_op_handler op (MINUS_EXPR);

  || !op.fold_range (vr, TREE_TYPE (index), vr, low_bound_range)

with building a constant range for low_bound (not exactly sure how to
best do that)?  I think you'll also need to repeat the
!vr.varying_p () / !vr.undefined_p () checks -- possibly they
could be simply delayed and feeding fold_range with those could
be OK.

I have CCed Andrew who sould be able to give better guidance.

I'll note the existing code tried to account for low_bound != 0, I trust
you identified where it failed to, I refrained from trying to understand it ;)

Thanks,
Richard.

>
>
> 2026-08-24  Eric Botcazou  <[email protected]>
>
>         PR ada/125984
>         * tree-dfa.cc (get_ref_base_and_extent) <ARRAY_REF>: Use the range
>         of the difference between the index expression and the low bound,
>         instead of that of the index expression itself, to constrain the
>         maximum size of the access.
>
>
> 2026-08-24  Eric Botcazou  <[email protected]>
>
>         * gnat.dg/opt110.adb: New test.
>
> --
> Eric Botcazou

Reply via email to