aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/translate/trans-chap8.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-01-31 20:08:44 +0100
committerTristan Gingold <tgingold@free.fr>2020-01-31 20:08:44 +0100
commit3c84d8097b9e6edbaceb5d644e9da3f68eec52a3 (patch)
tree654a43a8cb5e2c8dfda95cc6562b5ca1ca17e63e /src/vhdl/translate/trans-chap8.adb
parentc83bce97cdb629fc52d5b9f73f9d236c79122ae4 (diff)
downloadghdl-3c84d8097b9e6edbaceb5d644e9da3f68eec52a3.tar.gz
ghdl-3c84d8097b9e6edbaceb5d644e9da3f68eec52a3.tar.bz2
ghdl-3c84d8097b9e6edbaceb5d644e9da3f68eec52a3.zip
trans-chap8: optimize assignment for non-overlapping targets.
Diffstat (limited to 'src/vhdl/translate/trans-chap8.adb')
-rw-r--r--src/vhdl/translate/trans-chap8.adb119
1 files changed, 108 insertions, 11 deletions
diff --git a/src/vhdl/translate/trans-chap8.adb b/src/vhdl/translate/trans-chap8.adb
index 00faaa0da..1e762e933 100644
--- a/src/vhdl/translate/trans-chap8.adb
+++ b/src/vhdl/translate/trans-chap8.adb
@@ -944,10 +944,8 @@ package body Trans.Chap8 is
if Final then
Translate_Variable_Aggregate_Assignment
(Get_Associated_Expr (El), El_Type,
- Chap3.Index_Base
- (Val, Targ_Type,
- New_Lit (New_Unsigned_Literal
- (Ghdl_Index_Type, Index))));
+ Chap3.Index_Base (Val, Targ_Type,
+ New_Lit (New_Index_Lit (Index))));
Index := Index + 1;
else
Translate_Variable_Array_Aggr
@@ -1017,6 +1015,100 @@ package body Trans.Chap8 is
end if;
end Translate_Variable_Aggregate_Assignment;
+ function Aggregate_Overlap_Variable (Aggr : Iir; Name : Iir) return Boolean
+ is
+ Assoc : Iir;
+ Expr : Iir;
+ begin
+ Assoc := Get_Association_Choices_Chain (Aggr);
+ while Assoc /= Null_Iir loop
+ Expr := Get_Associated_Expr (Assoc);
+ if Get_Kind (Expr) = Iir_Kind_Aggregate then
+ if Aggregate_Overlap_Variable (Expr, Name) then
+ return True;
+ end if;
+ else
+ Expr := Get_Base_Name (Expr);
+ if Expr = Name then
+ return True;
+ end if;
+ end if;
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ return False;
+ end Aggregate_Overlap_Variable;
+
+ function Aggregate_Overlap_Dereference (Aggr : Iir; Atype : Iir)
+ return Boolean
+ is
+ Assoc : Iir;
+ Expr : Iir;
+ begin
+ Assoc := Get_Association_Choices_Chain (Aggr);
+ while Assoc /= Null_Iir loop
+ Expr := Get_Associated_Expr (Assoc);
+ if Get_Kind (Expr) = Iir_Kind_Aggregate then
+ if Aggregate_Overlap_Dereference (Expr, Atype) then
+ return True;
+ end if;
+ else
+ Expr := Get_Base_Name (Expr);
+ if Get_Kind (Expr) in Iir_Kinds_Dereference
+ and then Get_Base_Type (Get_Type (Expr)) = Atype
+ then
+ return True;
+ end if;
+ end if;
+ Assoc := Get_Chain (Assoc);
+ end loop;
+ return False;
+ end Aggregate_Overlap_Dereference;
+
+ -- Return true if there is a possible overlap between source and
+ -- target in an assignment whose target is an aggregate.
+ function Assignment_Overlap (Targ : Iir; Expr : Iir) return Boolean
+ is
+ Base : Iir;
+ begin
+ Base := Expr;
+
+ -- Strip qualified expression/parenthesis/type conversion. Although
+ -- they are expression, code generation doesn't copy the value.
+ loop
+ case Get_Kind (Base) is
+ when Iir_Kind_Qualified_Expression
+ | Iir_Kind_Parenthesis_Expression
+ | Iir_Kind_Type_Conversion =>
+ Base := Get_Expression (Base);
+ when others =>
+ exit;
+ end case;
+ end loop;
+
+ case Get_Kind (Base) is
+ when Iir_Kinds_Name =>
+ Base := Get_Base_Name (Base);
+ when Iir_Kinds_Dereference =>
+ null;
+ when others =>
+ -- An expression.
+ return False;
+ end case;
+
+ case Get_Kind (Base) is
+ when Iir_Kinds_Dereference =>
+ return Aggregate_Overlap_Dereference
+ (Targ, Get_Base_Type (Get_Type (Base)));
+ when Iir_Kind_Interface_Variable_Declaration
+ | Iir_Kind_Variable_Declaration =>
+ return Aggregate_Overlap_Variable (Targ, Base);
+ when Iir_Kind_External_Variable_Name =>
+ return True;
+ when others =>
+ return False;
+ end case;
+ end Assignment_Overlap;
+
procedure Translate_Variable_Assignment_Statement
(Stmt : Iir_Variable_Assignment_Statement)
is
@@ -1031,15 +1123,20 @@ package body Trans.Chap8 is
Temp : Mnode;
begin
Chap3.Translate_Anonymous_Subtype_Definition (Targ_Type, False);
+ E := Chap7.Translate_Expression (Expr, Targ_Type);
- -- Use a temporary variable, to avoid overlap.
- Temp := Create_Temp (Get_Info (Targ_Type));
- Chap4.Allocate_Complex_Object (Targ_Type, Alloc_Stack, Temp);
+ if Assignment_Overlap (Target, Expr) then
+ -- Use a temporary variable, to avoid overlap.
+ Temp := Create_Temp (Get_Info (Targ_Type));
+ Chap4.Allocate_Complex_Object (Targ_Type, Alloc_Stack, Temp);
- E := Chap7.Translate_Expression (Expr, Targ_Type);
- Chap3.Translate_Object_Copy (Temp, E, Targ_Type);
- Translate_Variable_Aggregate_Assignment
- (Target, Targ_Type, Temp);
+ Chap3.Translate_Object_Copy (Temp, E, Targ_Type);
+ E := Temp;
+ else
+ -- FIXME: check bounds.
+ Stabilize (E);
+ end if;
+ Translate_Variable_Aggregate_Assignment (Target, Targ_Type, E);
return;
end;
else