aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mutils.adb4
-rw-r--r--src/mutils.ads3
-rw-r--r--src/synth/synth-oper.adb24
3 files changed, 31 insertions, 0 deletions
diff --git a/src/mutils.adb b/src/mutils.adb
index 1b40bff79..d51891f02 100644
--- a/src/mutils.adb
+++ b/src/mutils.adb
@@ -24,4 +24,8 @@ package body Mutils is
return 64;
end Clog2;
+ function Is_Power2 (V : Uns64) return Boolean is
+ begin
+ return (V and (V - 1)) = 0;
+ end Is_Power2;
end Mutils;
diff --git a/src/mutils.ads b/src/mutils.ads
index 4275fe6c0..1a3afd4f1 100644
--- a/src/mutils.ads
+++ b/src/mutils.ads
@@ -4,4 +4,7 @@ package Mutils is
-- Return the ceiling log2 of V.
-- Returns 0 for 0.
function Clog2 (V : Uns64) return Integer;
+
+ -- Return True IFF V is 0 or a power of 2.
+ function Is_Power2 (V : Uns64) return Boolean;
end Mutils;
diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb
index b5480a2b9..b887a66ed 100644
--- a/src/synth/synth-oper.adb
+++ b/src/synth/synth-oper.adb
@@ -21,6 +21,8 @@
with Ada.Unchecked_Conversion;
with Types; use Types;
with Types_Utils; use Types_Utils;
+with Mutils;
+
with Vhdl.Ieee.Std_Logic_1164; use Vhdl.Ieee.Std_Logic_1164;
with Vhdl.Std_Package;
with Vhdl.Errors; use Vhdl.Errors;
@@ -182,6 +184,7 @@ package body Synth.Oper is
Right_Expr : Node;
Expr : Node) return Value_Acc
is
+ Ctxt : constant Context_Acc := Get_Build (Syn_Inst);
Def : constant Iir_Predefined_Functions :=
Get_Implicit_Definition (Imp);
Inter_Chain : constant Node :=
@@ -710,6 +713,27 @@ package body Synth.Oper is
when Iir_Predefined_Integer_Div =>
return Synth_Int_Dyadic (Id_Sdiv);
when Iir_Predefined_Integer_Mod =>
+ if Is_Static_Val (Right) then
+ -- Optimize when the divisor is a power of 2.
+ declare
+ use Mutils;
+ Etype : constant Type_Acc :=
+ Get_Value_Type (Syn_Inst, Expr_Type);
+ R : constant Int64 := Get_Static_Discrete (Right);
+ Log_R : Natural;
+ N : Net;
+ begin
+ if R > 0 and then Is_Power2 (Uns64 (R)) then
+ Log_R := Clog2 (Uns64 (R));
+ pragma Assert (Log_R <= Natural (Left.Typ.W));
+ N := Get_Net (Left);
+ N := Build2_Extract (Ctxt, N, 0, Width (Log_R));
+ N := Build2_Uresize (Ctxt, N, Left.Typ.W,
+ Get_Location (Expr));
+ return Create_Value_Net (N, Etype);
+ end if;
+ end;
+ end if;
return Synth_Int_Dyadic (Id_Smod);
when Iir_Predefined_Integer_Rem =>
return Synth_Int_Dyadic (Id_Srem);