diff options
author | Steve Baird <baird@adacore.com> | 2024-08-20 17:35:24 -0700 |
---|---|---|
committer | Marc Poulhiès <dkm@gcc.gnu.org> | 2024-09-03 10:16:28 +0200 |
commit | 1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b (patch) | |
tree | 64781cd7e9af04a6a90d06fb3f241b3c1d1609f0 /gcc | |
parent | d7e110d8fa18f734058e73424c398d8c69fcb6b3 (diff) | |
download | gcc-1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b.zip gcc-1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b.tar.gz gcc-1ef11f4bed8eb230f04e5fb09741ae6444ca3e7b.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/exp_attr.adb | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 84c7a4b..702c4bb 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 |