https://gcc.gnu.org/g:1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b
commit r15-3401-g1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b Author: Steve Baird <ba...@adacore.com> Date: Tue Aug 20 17:35:24 2024 -0700 ada: Transform Length attribute references for non-Strict overflow mode. The non-strict overflow checking code does a better job of eliminating overflow checks if given an expression consisting only of predefined operators (including relationals), literals, identifiers, and conditional expressions. If it is both feasible and useful, rewrite a Length attribute reference as such an expression. "Feasible" means "index type is same type as attribute reference type, so we can rewrite without using type conversions". "Useful" means "Overflow_Mode is something other than Strict, so there is value in making overflow check elimination easier". gcc/ada/ * exp_attr.adb (Expand_N_Attribute_Reference): If it makes sense to do so, then rewrite a Length attribute reference as an equivalent conditional expression. Diff: --- gcc/ada/exp_attr.adb | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 84c7a4bbdeeb..702c4bb120a3 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -4797,7 +4797,7 @@ package body Exp_Attr is -- then replace this attribute with a reference to 'Range_Length -- of the appropriate index subtype (since otherwise the -- back end will try to give us the value of 'Length for - -- this implementation type).s + -- this implementation type). elsif Is_Constrained (Ptyp) then Rewrite (N, @@ -4868,6 +4868,73 @@ package body Exp_Attr is end if; end; + -- Overflow-related transformations need Length attribute rewritten + -- using non-attribute expressions. So generate + -- (if Pref'First > Pref'Last + -- then 0 + -- else ((Pref'Last - Pref'First) + 1)) . + + elsif Overflow_Check_Mode in Minimized_Or_Eliminated + + -- This Comes_From_Source test fixes a regression test failure + -- involving a Length attribute reference generated as part of + -- the expansion of a concatentation operator; it is unclear + -- whether this is the right solution to that problem. + + and then Comes_From_Source (N) + + -- This Base_Type equality test is so that we only perform this + -- transformation if we can do it without introducing + -- a type conversion anywhere in the resulting expansion; + -- a type conversion is just as bad as a Length attribute + -- reference for those overflow-related transformations. + + and then Btyp = Base_Type (Get_Index_Subtype (N)) + + then + declare + function Prefix_Bound + (Bound_Attr_Name : Name_Id; Is_First_Copy : Boolean := False) + return Node_Id; + -- constructs a Pref'First or Pref'Last attribute reference + + ------------------ + -- Prefix_Bound -- + ------------------ + + function Prefix_Bound + (Bound_Attr_Name : Name_Id; Is_First_Copy : Boolean := False) + return Node_Id + is + Prefix : constant Node_Id := + (if Is_First_Copy + then Duplicate_Subexpr (Pref) + else Duplicate_Subexpr_No_Checks (Pref)); + begin + return Make_Attribute_Reference (Loc, + Prefix => Prefix, + Attribute_Name => Bound_Attr_Name, + Expressions => New_Copy_List (Exprs)); + end Prefix_Bound; + begin + Rewrite (N, + Make_If_Expression (Loc, + Expressions => + New_List ( + Node1 => Make_Op_Gt (Loc, + Prefix_Bound (Name_First, + Is_First_Copy => True), + Prefix_Bound (Name_Last)), + Node2 => Make_Integer_Literal (Loc, 0), + Node3 => Make_Op_Add (Loc, + Make_Op_Subtract (Loc, + Prefix_Bound (Name_Last), + Prefix_Bound (Name_First)), + Make_Integer_Literal (Loc, 1))))); + + Analyze_And_Resolve (N, Typ); + end; + -- Otherwise leave it to the back end else