diff --git a/app/Commands/Dev/Reg/Read.hs b/app/Commands/Dev/Reg/Read.hs index f8a86ebe5f..2d58b6f64f 100644 --- a/app/Commands/Dev/Reg/Read.hs +++ b/app/Commands/Dev/Reg/Read.hs @@ -2,7 +2,7 @@ module Commands.Dev.Reg.Read where import Commands.Base import Commands.Dev.Reg.Read.Options -import Juvix.Compiler.Reg.Pretty qualified as Reg +import Juvix.Compiler.Reg.Pretty qualified as Reg hiding (defaultOptions) import Juvix.Compiler.Reg.Transformation qualified as Reg import Juvix.Compiler.Reg.Translation.FromSource qualified as Reg import RegInterpreter @@ -15,7 +15,10 @@ runCommand opts = do Left err -> exitJuvixError (JuvixError err) Right tab -> do - r <- runError @JuvixError (Reg.applyTransformations (project opts ^. regReadTransformations) tab) + r <- + runError @JuvixError + . runReader Reg.defaultOptions + $ (Reg.applyTransformations (project opts ^. regReadTransformations) tab) case r of Left err -> exitJuvixError (JuvixError err) Right tab' -> do diff --git a/src/Juvix/Compiler/Asm/Options.hs b/src/Juvix/Compiler/Asm/Options.hs index 417d95c541..46cb60789e 100644 --- a/src/Juvix/Compiler/Asm/Options.hs +++ b/src/Juvix/Compiler/Asm/Options.hs @@ -6,11 +6,13 @@ where import Juvix.Compiler.Backend import Juvix.Compiler.Pipeline.EntryPoint +import Juvix.Compiler.Tree.Options qualified as Tree import Juvix.Prelude data Options = Options { _optDebug :: Bool, - _optLimits :: Limits + _optLimits :: Limits, + _optTreeOptions :: Tree.Options } makeLenses ''Options @@ -19,7 +21,8 @@ makeOptions :: Target -> Bool -> Options makeOptions tgt debug = Options { _optDebug = debug, - _optLimits = getLimits tgt debug + _optLimits = getLimits tgt debug, + _optTreeOptions = Tree.defaultOptions } getClosureSize :: Options -> Int -> Int @@ -29,5 +32,6 @@ fromEntryPoint :: EntryPoint -> Options fromEntryPoint e@EntryPoint {..} = Options { _optDebug = _entryPointDebug, - _optLimits = getLimits (getEntryPointTarget e) _entryPointDebug + _optLimits = getLimits (getEntryPointTarget e) _entryPointDebug, + _optTreeOptions = Tree.fromEntryPoint e } diff --git a/src/Juvix/Compiler/Pipeline.hs b/src/Juvix/Compiler/Pipeline.hs index 8fac49cc11..d63fd02027 100644 --- a/src/Juvix/Compiler/Pipeline.hs +++ b/src/Juvix/Compiler/Pipeline.hs @@ -358,7 +358,7 @@ regToRust = regToRust' Rust.BackendRust regToRiscZeroRust :: (Member (Reader EntryPoint) r) => Reg.InfoTable -> Sem r Rust.Result regToRiscZeroRust = regToRust' Rust.BackendRiscZero -regToCasm :: Reg.InfoTable -> Sem r Casm.Result +regToCasm :: (Member (Reader EntryPoint) r) => Reg.InfoTable -> Sem r Casm.Result regToCasm = Reg.toCasm >=> return . Casm.fromReg casmToCairo :: Casm.Result -> Sem r Cairo.Result @@ -367,7 +367,7 @@ casmToCairo Casm.Result {..} = . Cairo.serialize _resultOutputSize (map Casm.builtinName _resultBuiltins) $ Cairo.fromCasm _resultCode -regToCairo :: Reg.InfoTable -> Sem r Cairo.Result +regToCairo :: (Member (Reader EntryPoint) r) => Reg.InfoTable -> Sem r Cairo.Result regToCairo = regToCasm >=> casmToCairo treeToAnoma' :: (Members '[Error JuvixError, Reader NockmaTree.CompilerOptions] r) => Tree.InfoTable -> Sem r NockmaTree.AnomaResult @@ -378,6 +378,6 @@ asmToMiniC' = mapError (JuvixError @Asm.AsmError) . Asm.toReg' >=> regToMiniC' . regToMiniC' :: (Member (Reader Asm.Options) r) => Reg.InfoTable -> Sem r C.MiniCResult regToMiniC' tab = do - tab' <- Reg.toC tab + tab' <- mapReader (^. Asm.optTreeOptions) $ Reg.toC' tab e <- ask return $ C.fromReg (e ^. Asm.optLimits) tab' diff --git a/src/Juvix/Compiler/Reg/Data/TransformationId.hs b/src/Juvix/Compiler/Reg/Data/TransformationId.hs index c7f09f39ac..4d7b6821fc 100644 --- a/src/Juvix/Compiler/Reg/Data/TransformationId.hs +++ b/src/Juvix/Compiler/Reg/Data/TransformationId.hs @@ -12,6 +12,8 @@ data TransformationId | CopyPropagation | ConstantPropagation | DeadCodeElimination + | OptPhaseMain + | OptPhaseCairo deriving stock (Data, Bounded, Enum, Show) data PipelineId @@ -29,7 +31,7 @@ toRustTransformations :: [TransformationId] toRustTransformations = [Cleanup] toCasmTransformations :: [TransformationId] -toCasmTransformations = [Cleanup, CopyPropagation, ConstantPropagation, DeadCodeElimination, SSA] +toCasmTransformations = [Cleanup, OptPhaseCairo, SSA] instance TransformationId' TransformationId where transformationText :: TransformationId -> Text @@ -41,6 +43,8 @@ instance TransformationId' TransformationId where CopyPropagation -> strCopyPropagation ConstantPropagation -> strConstantPropagation DeadCodeElimination -> strDeadCodeElimination + OptPhaseMain -> strOptPhaseMain + OptPhaseCairo -> strOptPhaseCairo instance PipelineId' TransformationId PipelineId where pipelineText :: PipelineId -> Text diff --git a/src/Juvix/Compiler/Reg/Data/TransformationId/Strings.hs b/src/Juvix/Compiler/Reg/Data/TransformationId/Strings.hs index e410691dde..aa44771ee0 100644 --- a/src/Juvix/Compiler/Reg/Data/TransformationId/Strings.hs +++ b/src/Juvix/Compiler/Reg/Data/TransformationId/Strings.hs @@ -31,3 +31,9 @@ strConstantPropagation = "constant-propagation" strDeadCodeElimination :: Text strDeadCodeElimination = "dead-code" + +strOptPhaseMain :: Text +strOptPhaseMain = "opt-main" + +strOptPhaseCairo :: Text +strOptPhaseCairo = "opt-cairo" diff --git a/src/Juvix/Compiler/Reg/Pipeline.hs b/src/Juvix/Compiler/Reg/Pipeline.hs index 43eee4a079..76a5e14249 100644 --- a/src/Juvix/Compiler/Reg/Pipeline.hs +++ b/src/Juvix/Compiler/Reg/Pipeline.hs @@ -4,6 +4,7 @@ module Juvix.Compiler.Reg.Pipeline ) where +import Juvix.Compiler.Pipeline.EntryPoint (EntryPoint) import Juvix.Compiler.Reg.Data.Blocks.InfoTable qualified as Blocks import Juvix.Compiler.Reg.Data.InfoTable import Juvix.Compiler.Reg.Transformation @@ -11,14 +12,25 @@ import Juvix.Compiler.Reg.Transformation.Blocks.Liveness qualified as Blocks import Juvix.Compiler.Reg.Translation.Blocks.FromReg qualified as Blocks -- | Perform transformations on JuvixReg necessary before the translation to C -toC :: InfoTable -> Sem r InfoTable -toC = applyTransformations toCTransformations +toC' :: (Member (Reader Options) r) => InfoTable -> Sem r InfoTable +toC' = applyTransformations toCTransformations -- | Perform transformations on JuvixReg necessary before the translation to Rust -toRust :: InfoTable -> Sem r InfoTable -toRust = applyTransformations toRustTransformations +toRust' :: (Member (Reader Options) r) => InfoTable -> Sem r InfoTable +toRust' = applyTransformations toRustTransformations -- | Perform transformations on JuvixReg necessary before the translation to -- Cairo assembly -toCasm :: InfoTable -> Sem r Blocks.InfoTable -toCasm = applyTransformations toCasmTransformations >=> return . Blocks.computeLiveness . Blocks.fromReg +toCasm' :: (Member (Reader Options) r) => InfoTable -> Sem r Blocks.InfoTable +toCasm' = + applyTransformations toCasmTransformations + >=> return . Blocks.computeLiveness . Blocks.fromReg + +toC :: (Member (Reader EntryPoint) r) => InfoTable -> Sem r InfoTable +toC = mapReader fromEntryPoint . toC' + +toRust :: (Member (Reader EntryPoint) r) => InfoTable -> Sem r InfoTable +toRust = mapReader fromEntryPoint . toRust' + +toCasm :: (Member (Reader EntryPoint) r) => InfoTable -> Sem r Blocks.InfoTable +toCasm = mapReader fromEntryPoint . toCasm diff --git a/src/Juvix/Compiler/Reg/Transformation.hs b/src/Juvix/Compiler/Reg/Transformation.hs index 5d43a926b0..e932652b08 100644 --- a/src/Juvix/Compiler/Reg/Transformation.hs +++ b/src/Juvix/Compiler/Reg/Transformation.hs @@ -8,14 +8,16 @@ where import Juvix.Compiler.Reg.Data.TransformationId import Juvix.Compiler.Reg.Transformation.Base import Juvix.Compiler.Reg.Transformation.Cleanup -import Juvix.Compiler.Reg.Transformation.ConstantPropagation -import Juvix.Compiler.Reg.Transformation.CopyPropagation -import Juvix.Compiler.Reg.Transformation.DeadCodeElimination import Juvix.Compiler.Reg.Transformation.IdentityTrans import Juvix.Compiler.Reg.Transformation.InitBranchVars +import Juvix.Compiler.Reg.Transformation.Optimize.ConstantPropagation +import Juvix.Compiler.Reg.Transformation.Optimize.CopyPropagation +import Juvix.Compiler.Reg.Transformation.Optimize.DeadCodeElimination +import Juvix.Compiler.Reg.Transformation.Optimize.Phase.Cairo qualified as Phase.Cairo +import Juvix.Compiler.Reg.Transformation.Optimize.Phase.Main qualified as Phase.Main import Juvix.Compiler.Reg.Transformation.SSA -applyTransformations :: forall r. [TransformationId] -> InfoTable -> Sem r InfoTable +applyTransformations :: forall r. (Member (Reader Options) r) => [TransformationId] -> InfoTable -> Sem r InfoTable applyTransformations ts tbl = foldM (flip appTrans) tbl ts where appTrans :: TransformationId -> InfoTable -> Sem r InfoTable @@ -27,3 +29,5 @@ applyTransformations ts tbl = foldM (flip appTrans) tbl ts CopyPropagation -> return . copyPropagate ConstantPropagation -> return . constantPropagate DeadCodeElimination -> return . removeDeadAssignments + OptPhaseMain -> Phase.Main.optimize + OptPhaseCairo -> Phase.Cairo.optimize diff --git a/src/Juvix/Compiler/Reg/Transformation/Base.hs b/src/Juvix/Compiler/Reg/Transformation/Base.hs index 60131d0e39..9f734efb5d 100644 --- a/src/Juvix/Compiler/Reg/Transformation/Base.hs +++ b/src/Juvix/Compiler/Reg/Transformation/Base.hs @@ -1,5 +1,6 @@ module Juvix.Compiler.Reg.Transformation.Base ( module Juvix.Compiler.Tree.Transformation.Generic.Base, + module Juvix.Compiler.Tree.Options, module Juvix.Compiler.Reg.Data.InfoTable, module Juvix.Compiler.Reg.Language, ) @@ -7,4 +8,5 @@ where import Juvix.Compiler.Reg.Data.InfoTable import Juvix.Compiler.Reg.Language +import Juvix.Compiler.Tree.Options import Juvix.Compiler.Tree.Transformation.Generic.Base diff --git a/src/Juvix/Compiler/Reg/Transformation/ConstantPropagation.hs b/src/Juvix/Compiler/Reg/Transformation/Optimize/ConstantPropagation.hs similarity index 96% rename from src/Juvix/Compiler/Reg/Transformation/ConstantPropagation.hs rename to src/Juvix/Compiler/Reg/Transformation/Optimize/ConstantPropagation.hs index 99d269d960..071d4ab40f 100644 --- a/src/Juvix/Compiler/Reg/Transformation/ConstantPropagation.hs +++ b/src/Juvix/Compiler/Reg/Transformation/Optimize/ConstantPropagation.hs @@ -1,4 +1,4 @@ -module Juvix.Compiler.Reg.Transformation.ConstantPropagation where +module Juvix.Compiler.Reg.Transformation.Optimize.ConstantPropagation where import Data.HashMap.Strict qualified as HashMap import Juvix.Compiler.Reg.Extra diff --git a/src/Juvix/Compiler/Reg/Transformation/CopyPropagation.hs b/src/Juvix/Compiler/Reg/Transformation/Optimize/CopyPropagation.hs similarity index 95% rename from src/Juvix/Compiler/Reg/Transformation/CopyPropagation.hs rename to src/Juvix/Compiler/Reg/Transformation/Optimize/CopyPropagation.hs index dc9a4c43d7..1d47bfaa4d 100644 --- a/src/Juvix/Compiler/Reg/Transformation/CopyPropagation.hs +++ b/src/Juvix/Compiler/Reg/Transformation/Optimize/CopyPropagation.hs @@ -1,4 +1,4 @@ -module Juvix.Compiler.Reg.Transformation.CopyPropagation where +module Juvix.Compiler.Reg.Transformation.Optimize.CopyPropagation where import Data.HashMap.Strict qualified as HashMap import Juvix.Compiler.Reg.Extra diff --git a/src/Juvix/Compiler/Reg/Transformation/DeadCodeElimination.hs b/src/Juvix/Compiler/Reg/Transformation/Optimize/DeadCodeElimination.hs similarity index 94% rename from src/Juvix/Compiler/Reg/Transformation/DeadCodeElimination.hs rename to src/Juvix/Compiler/Reg/Transformation/Optimize/DeadCodeElimination.hs index 8d3a8fd999..4f2540a4e4 100644 --- a/src/Juvix/Compiler/Reg/Transformation/DeadCodeElimination.hs +++ b/src/Juvix/Compiler/Reg/Transformation/Optimize/DeadCodeElimination.hs @@ -1,4 +1,4 @@ -module Juvix.Compiler.Reg.Transformation.DeadCodeElimination where +module Juvix.Compiler.Reg.Transformation.Optimize.DeadCodeElimination where import Data.HashSet qualified as HashSet import Juvix.Compiler.Reg.Extra diff --git a/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Cairo.hs b/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Cairo.hs new file mode 100644 index 0000000000..ba4033ebdf --- /dev/null +++ b/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Cairo.hs @@ -0,0 +1,7 @@ +module Juvix.Compiler.Reg.Transformation.Optimize.Phase.Cairo where + +import Juvix.Compiler.Reg.Transformation.Base +import Juvix.Compiler.Reg.Transformation.Optimize.Phase.Main qualified as Main + +optimize :: (Member (Reader Options) r) => InfoTable -> Sem r InfoTable +optimize = withOptimizationLevel 1 Main.optimize diff --git a/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Main.hs b/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Main.hs new file mode 100644 index 0000000000..4dfcdcffaa --- /dev/null +++ b/src/Juvix/Compiler/Reg/Transformation/Optimize/Phase/Main.hs @@ -0,0 +1,20 @@ +module Juvix.Compiler.Reg.Transformation.Optimize.Phase.Main where + +import Juvix.Compiler.Reg.Transformation.Base +import Juvix.Compiler.Reg.Transformation.Optimize.ConstantPropagation +import Juvix.Compiler.Reg.Transformation.Optimize.CopyPropagation +import Juvix.Compiler.Reg.Transformation.Optimize.DeadCodeElimination + +optimize' :: Options -> InfoTable -> InfoTable +optimize' Options {..} = + compose + (2 * _optOptimizationLevel) + ( copyPropagate + . constantPropagate + . removeDeadAssignments + ) + +optimize :: (Member (Reader Options) r) => InfoTable -> Sem r InfoTable +optimize tab = do + opts <- ask + return $ optimize' opts tab diff --git a/src/Juvix/Compiler/Tree/Options.hs b/src/Juvix/Compiler/Tree/Options.hs new file mode 100644 index 0000000000..ab9684f9c3 --- /dev/null +++ b/src/Juvix/Compiler/Tree/Options.hs @@ -0,0 +1,26 @@ +module Juvix.Compiler.Tree.Options where + +import Juvix.Compiler.Pipeline.EntryPoint +import Juvix.Data.Field +import Juvix.Prelude + +data Options = Options + { _optOptimizationLevel :: Int, + _optFieldSize :: Natural + } + +makeLenses ''Options + +defaultOptions :: Options +defaultOptions = + Options + { _optOptimizationLevel = defaultOptimizationLevel, + _optFieldSize = defaultFieldSize + } + +fromEntryPoint :: EntryPoint -> Options +fromEntryPoint EntryPoint {..} = + Options + { _optOptimizationLevel = _entryPointOptimizationLevel, + _optFieldSize = _entryPointFieldSize + } diff --git a/src/Juvix/Compiler/Tree/Transformation/Generic/Base.hs b/src/Juvix/Compiler/Tree/Transformation/Generic/Base.hs index 15d547e24d..84c5fe66e8 100644 --- a/src/Juvix/Compiler/Tree/Transformation/Generic/Base.hs +++ b/src/Juvix/Compiler/Tree/Transformation/Generic/Base.hs @@ -4,6 +4,7 @@ import Data.HashMap.Strict qualified as HashMap import Juvix.Compiler.Tree.Data.InfoTable.Base import Juvix.Compiler.Tree.Data.InfoTableBuilder.Base import Juvix.Compiler.Tree.Language.Base +import Juvix.Compiler.Tree.Options mapFunctionsM :: (Monad m) => (FunctionInfo' a e -> m (FunctionInfo' a e)) -> InfoTable' a e -> m (InfoTable' a e) mapFunctionsM = overM infoFunctions . mapM @@ -36,3 +37,13 @@ mapT' f tab = walkT :: (Applicative f) => (Symbol -> a -> f ()) -> InfoTable' a e -> f () walkT f tab = for_ (HashMap.toList (tab ^. infoFunctions)) (\(k, v) -> f k (v ^. functionCode)) + +withOptimizationLevel :: (Member (Reader Options) r) => Int -> (InfoTable' a e -> Sem r (InfoTable' a e)) -> InfoTable' a e -> Sem r (InfoTable' a e) +withOptimizationLevel n f tab = do + l <- asks (^. optOptimizationLevel) + if + | l >= n -> f tab + | otherwise -> return tab + +withOptimizationLevel' :: (Member (Reader Options) r) => InfoTable' a e -> Int -> (InfoTable' a e -> Sem r (InfoTable' a e)) -> Sem r (InfoTable' a e) +withOptimizationLevel' tab n f = withOptimizationLevel n f tab