aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorMarc Poulhiès <poulhies@adacore.com>2022-11-25 14:52:04 +0100
committerMarc Poulhiès <poulhies@adacore.com>2023-01-03 10:29:53 +0100
commit742084ada1e0974f5c7491fda65702e45bd07848 (patch)
treed6ce82392487f7e551768d8b7d11d3362f0eaee8 /gcc/ada
parent48d9f7cb215f1af996788aee07808339a786a18d (diff)
downloadgcc-742084ada1e0974f5c7491fda65702e45bd07848.zip
gcc-742084ada1e0974f5c7491fda65702e45bd07848.tar.gz
gcc-742084ada1e0974f5c7491fda65702e45bd07848.tar.bz2
ada: Adapt frontend optimization for aggregate assignment
The frontend currently relies on gigi to use efficient assignment in particular cases like: Some_Var.all := (others => (others => 0)); gigi would use memset to clear memory pointed to by Some_Var. In the case of an access with a Designated_Storage_Model aspect with a Copy_To procedure, memset can't be used directly. Instead of simply disabling this frontend/gigi optimization and having the frontend emit several assignments, a temporary is used (through the new Build_Assignment_With_Temporary): gigi can still memset it, and this temporary is then copied into the original target (and the regular storage model mechanism handles it). gcc/ada/ * exp_aggr.adb (Build_Assignment_With_Temporary): New. (Expand_Array_Aggregate): Tune backend optimization and insert a temporary in the case of an access with Designated_Storage_Model aspect. (Convert_Array_Aggr_In_Allocator): Likewise.
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/exp_aggr.adb106
1 files changed, 92 insertions, 14 deletions
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 4d8bb817..30f32a7 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -62,6 +62,7 @@ with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
with Sem_Res; use Sem_Res;
with Sem_Util; use Sem_Util;
+use Sem_Util.Storage_Model_Support;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
@@ -75,6 +76,15 @@ with Warnsw; use Warnsw;
package body Exp_Aggr is
+ function Build_Assignment_With_Temporary
+ (Target : Node_Id;
+ Typ : Node_Id;
+ Source : Node_Id) return List_Id;
+ -- Returns a list of actions to assign Source to Target of type Typ using
+ -- an extra temporary:
+ -- Tmp := Source;
+ -- Target := Tmp;
+
type Case_Bounds is record
Choice_Lo : Node_Id;
Choice_Hi : Node_Id;
@@ -2508,6 +2518,42 @@ package body Exp_Aggr is
return New_Code;
end Build_Array_Aggr_Code;
+ -------------------------------------
+ -- Build_Assignment_With_Temporary --
+ -------------------------------------
+
+ function Build_Assignment_With_Temporary
+ (Target : Node_Id;
+ Typ : Node_Id;
+ Source : Node_Id) return List_Id
+ is
+ Loc : constant Source_Ptr := Sloc (Source);
+
+ Aggr_Code : List_Id;
+ Tmp : Entity_Id;
+ Tmp_Decl : Node_Id;
+
+ begin
+ Tmp := Make_Temporary (Loc, 'A', Source);
+ Tmp_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Tmp,
+ Object_Definition => New_Occurrence_Of (Typ, Loc));
+ Set_No_Initialization (Tmp_Decl, True);
+
+ Aggr_Code := New_List (Tmp_Decl);
+ Append_To (Aggr_Code,
+ Make_OK_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (Tmp, Loc),
+ Expression => Source));
+
+ Append_To (Aggr_Code,
+ Make_OK_Assignment_Statement (Loc,
+ Name => Target,
+ Expression => New_Occurrence_Of (Tmp, Loc)));
+ return Aggr_Code;
+ end Build_Assignment_With_Temporary;
+
----------------------------
-- Build_Record_Aggr_Code --
----------------------------
@@ -4514,15 +4560,29 @@ package body Exp_Aggr is
New_Aggr := New_Copy_Tree (Aggr);
Set_Expansion_Delayed (New_Aggr, False);
- Aggr_Code :=
- New_List (
- Make_OK_Assignment_Statement (Sloc (New_Aggr),
- Name => Target,
- Expression => New_Aggr));
+ -- In the case of Target's type using the Designated_Storage_Model
+ -- aspect with a Copy_To procedure, insert a temporary and have the
+ -- back end handle the assignment to it. Copy the result to the
+ -- original target.
+
+ if Has_Designated_Storage_Model_Aspect
+ (Etype (Prefix (Expression (Target))))
+ and then Present (Storage_Model_Copy_To
+ (Storage_Model_Object
+ (Etype (Prefix (Expression (Target))))))
+ then
+ Aggr_Code := Build_Assignment_With_Temporary (Target,
+ Typ, New_Aggr);
+ else
+ Aggr_Code :=
+ New_List (
+ Make_OK_Assignment_Statement (Sloc (New_Aggr),
+ Name => Target,
+ Expression => New_Aggr));
+ end if;
-- Or else, generate component assignments to it, as for an aggregate
-- that appears on the right-hand side of an assignment statement.
-
else
Aggr_Code :=
Build_Array_Aggr_Code (Aggr,
@@ -7065,16 +7125,34 @@ package body Exp_Aggr is
and then not Is_Possibly_Unaligned_Slice (Target)
and then Aggr_Assignment_OK_For_Backend (N)
then
- if Maybe_In_Place_OK then
- return;
- end if;
- Aggr_Code :=
- New_List (
- Make_Assignment_Statement (Loc,
- Name => Target,
- Expression => New_Copy_Tree (N)));
+ -- In the case of an assignment using an access with the
+ -- Designated_Storage_Model aspect with a Copy_To procedure,
+ -- insert a temporary and have the back end handle the assignment
+ -- to it. Copy the result to the original target.
+
+ if Parent_Kind = N_Assignment_Statement
+ and then Nkind (Name (Parent_Node)) = N_Explicit_Dereference
+ and then Has_Designated_Storage_Model_Aspect
+ (Etype (Prefix (Name (Parent_Node))))
+ and then Present (Storage_Model_Copy_To
+ (Storage_Model_Object
+ (Etype (Prefix (Name (Parent_Node))))))
+ then
+ Aggr_Code := Build_Assignment_With_Temporary (Target,
+ Typ, New_Copy_Tree (N));
+ else
+ if Maybe_In_Place_OK then
+ return;
+ end if;
+ Aggr_Code :=
+ New_List (
+ Make_Assignment_Statement (Loc,
+ Name => Target,
+ Expression => New_Copy_Tree (N)));
+
+ end if;
else
Aggr_Code :=
Build_Array_Aggr_Code (N,