From 65ea0024063eaa9623c8309edbe22e042325b7ea Mon Sep 17 00:00:00 2001 From: Eric Botcazou <ebotcazou@adacore.com> Date: Mon, 26 Jun 2023 20:33:53 +0200 Subject: [PATCH] ada: Do not unnecessarily use component-wise loop for slice assignment This relaxes the condition under which Expand_Assign_Array leaves the assignment to or from an array slice untouched. The main prerequisite for the code generator is that everything be aligned on byte boundaries and Is_Possibly_Unaligned_Slice is too strong a predicate for this, so it is replaced by the combination of Possible_Bit_Aligned_Component and Is_Bit_Packed_Array, modulo a change to Possible_Bit_Aligned_Component to take into account the specific case of slices. gcc/ada/ * exp_ch5.adb (Expand_Assign_Array): Adjust comment above the calls to Possible_Bit_Aligned_Component on the LHS and RHS. Do not call Is_Possibly_Unaligned_Slice in the slice case. * exp_util.ads (Component_May_Be_Bit_Aligned): Add For_Slice boolean parameter. (Possible_Bit_Aligned_Component): Likewise. * exp_util.adb (Component_May_Be_Bit_Aligned): Do not return False for the slice of a small record or bit-packed array component. (Possible_Bit_Aligned_Component): Pass For_Slice in recursive calls, except in the slice case where True is passed, as well as in call to Component_May_Be_Bit_Aligned. --- gcc/ada/exp_ch5.adb | 8 ++------ gcc/ada/exp_util.adb | 33 ++++++++++++++++++--------------- gcc/ada/exp_util.ads | 17 +++++++++++------ 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 258459b393dc..d55fdb3e2e5a 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -524,7 +524,7 @@ package body Exp_Ch5 is R_Type := Get_Actual_Subtype (Act_Rhs); Loop_Required := True; - -- We require a loop if the left side is possibly bit unaligned + -- We require a loop if either side is possibly bit aligned elsif Possible_Bit_Aligned_Component (Lhs) or else @@ -682,14 +682,10 @@ package body Exp_Ch5 is return; -- If either operand is bit packed, then we need a loop, since we can't - -- be sure that the slice is byte aligned. Similarly, if either operand - -- is a possibly unaligned slice, then we need a loop (since the back - -- end cannot handle unaligned slices). + -- be sure that the slice is byte aligned. elsif Is_Bit_Packed_Array (L_Type) or else Is_Bit_Packed_Array (R_Type) - or else Is_Possibly_Unaligned_Slice (Lhs) - or else Is_Possibly_Unaligned_Slice (Rhs) then Loop_Required := True; diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 0d0ad8a5d6c2..c74921e1772a 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -4959,7 +4959,10 @@ package body Exp_Util is -- Component_May_Be_Bit_Aligned -- ---------------------------------- - function Component_May_Be_Bit_Aligned (Comp : Entity_Id) return Boolean is + function Component_May_Be_Bit_Aligned + (Comp : Entity_Id; + For_Slice : Boolean := False) return Boolean + is UT : Entity_Id; begin @@ -4980,11 +4983,12 @@ package body Exp_Util is -- If we know that we have a small (at most the maximum integer size) -- record or bit-packed array, then everything is fine, since the back - -- end can handle these cases correctly. + -- end can handle these cases correctly, except if a slice is involved. elsif Known_Esize (Comp) and then Esize (Comp) <= System_Max_Integer_Size and then (Is_Record_Type (UT) or else Is_Bit_Packed_Array (UT)) + and then not For_Slice then return False; @@ -11318,7 +11322,10 @@ package body Exp_Util is -- Possible_Bit_Aligned_Component -- ------------------------------------ - function Possible_Bit_Aligned_Component (N : Node_Id) return Boolean is + function Possible_Bit_Aligned_Component + (N : Node_Id; + For_Slice : Boolean := False) return Boolean + is begin -- Do not process an unanalyzed node because it is not yet decorated and -- most checks performed below will fail. @@ -11356,7 +11363,7 @@ package body Exp_Util is -- indexing from a possibly unaligned component. else - return Possible_Bit_Aligned_Component (P); + return Possible_Bit_Aligned_Component (P, For_Slice); end if; end; @@ -11371,14 +11378,14 @@ package body Exp_Util is -- This is the crucial test: if the component itself causes -- trouble, then we can stop and return True. - if Component_May_Be_Bit_Aligned (Comp) then + if Component_May_Be_Bit_Aligned (Comp, For_Slice) then return True; -- Otherwise, we need to test the prefix, to see if we are -- selecting from a possibly unaligned component. else - return Possible_Bit_Aligned_Component (P); + return Possible_Bit_Aligned_Component (P, For_Slice); end if; end; @@ -11386,13 +11393,13 @@ package body Exp_Util is -- then for sure the slice is. when N_Slice => - return Possible_Bit_Aligned_Component (Prefix (N)); + return Possible_Bit_Aligned_Component (Prefix (N), True); -- For an unchecked conversion, check whether the expression may -- be bit aligned. when N_Unchecked_Type_Conversion => - return Possible_Bit_Aligned_Component (Expression (N)); + return Possible_Bit_Aligned_Component (Expression (N), For_Slice); -- If we have none of the above, it means that we have fallen off the -- top testing prefixes recursively, and we now have a stand alone @@ -11400,15 +11407,11 @@ package body Exp_Util is -- in which case we need to look into the renamed object. when others => - if Is_Entity_Name (N) + return Is_Entity_Name (N) and then Is_Object (Entity (N)) and then Present (Renamed_Object (Entity (N))) - then - return - Possible_Bit_Aligned_Component (Renamed_Object (Entity (N))); - else - return False; - end if; + and then Possible_Bit_Aligned_Component + (Renamed_Object (Entity (N)), For_Slice); end case; end Possible_Bit_Aligned_Component; diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 02324d23db0a..65bb9203009b 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -399,16 +399,19 @@ package Exp_Util is -- since for floating-point, abs, unary "-", and unary "+" can never -- case overflow. - function Component_May_Be_Bit_Aligned (Comp : Entity_Id) return Boolean; + function Component_May_Be_Bit_Aligned + (Comp : Entity_Id; + For_Slice : Boolean := False) return Boolean; -- This function is in charge of detecting record components that may cause - -- trouble for the back end if an attempt is made to access the component - -- as a whole. The back end can handle such accesses with no problem if the - -- components involved are small (64 bits or less) records or scalar items + -- trouble for the back end if an attempt is made to access the component, + -- either as a whole if For_Slice is False, or through an array slice if + -- For_Slice is True. The back end can handle such accesses only if the + -- components involved are small (64/128 bits or less) records or scalars -- (including bit-packed arrays represented with a modular type), or else -- if they are aligned on byte boundaries (i.e. starting on a byte boundary -- and occupying an integral number of bytes). -- - -- However, problems arise for records larger than 64 bits, or for arrays + -- However problems arise for records larger than 64/128 bits or for arrays -- (other than bit-packed arrays represented with a modular type) if the -- component either does not start on a byte boundary or does not occupy an -- integral number of bytes (i.e. there are some bits possibly shared with @@ -998,7 +1001,9 @@ package Exp_Util is -- address might be captured in a way we do not detect. A value of True is -- returned only if the replacement is safe. - function Possible_Bit_Aligned_Component (N : Node_Id) return Boolean; + function Possible_Bit_Aligned_Component + (N : Node_Id; + For_Slice : Boolean := False) return Boolean; -- This function is used during processing the assignment of a record or an -- array, or the construction of an aggregate. The argument N is either the -- left or the right hand side of an assignment and the function determines -- GitLab