diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mutils.adb | 4 | ||||
-rw-r--r-- | src/mutils.ads | 3 | ||||
-rw-r--r-- | src/synth/synth-oper.adb | 24 |
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); |