From 64064cfee57161bb42ef5c17bbe434185893ee5f Mon Sep 17 00:00:00 2001 From: doyougnu Date: Thu, 6 Apr 2023 09:39:59 -0400 Subject: JS: add GHC.JS.Optimizer, remove RTS.Printer, add Linker.Opt This MR changes some simple optimizations and is a first step in re-architecting the JS backend pipeline to add the optimizer. In particular it: - removes simple peep hole optimizations from `GHC.StgToJS.Printer` and removes that module - adds module `GHC.JS.Optimizer` - defines the same peep hole opts that were removed only now they are `Syntax -> Syntax` transformations rather than `Syntax -> JS code` optimizations - hooks the optimizer into code gen - adds FuncStat and ForStat constructors to the backend. Working Ticket: - #22736 Related MRs: - MR !10142 - MR !10000 ------------------------- Metric Decrease: CoOpt_Read ManyAlternatives PmSeriesS PmSeriesT PmSeriesV T10421 T12707 T13253 T13253-spj T15164 T17516 T18140 T18282 T18698a T18698b T18923 T1969 T19695 T20049 T3064 T5321FD T5321Fun T783 T9198 T9233 T9630 ------------------------- --- testsuite/tests/javascript/opt/all.T | 4 + testsuite/tests/javascript/opt/deadCodeElim.hs | 96 ++++++++++++++++++++++ testsuite/tests/javascript/opt/deadCodeElim.stdout | 7 ++ testsuite/tests/linters/notes.stdout | 17 ++-- 4 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 testsuite/tests/javascript/opt/all.T create mode 100644 testsuite/tests/javascript/opt/deadCodeElim.hs create mode 100644 testsuite/tests/javascript/opt/deadCodeElim.stdout (limited to 'testsuite') diff --git a/testsuite/tests/javascript/opt/all.T b/testsuite/tests/javascript/opt/all.T new file mode 100644 index 0000000000..35bdb51ee2 --- /dev/null +++ b/testsuite/tests/javascript/opt/all.T @@ -0,0 +1,4 @@ +# These are JavaScript-specific tests for the JS backend optimizer +setTestOpts(when(not(js_arch()),skip)) + +test('deadCodeElim', normal, compile_and_run, ['-package ghc']) diff --git a/testsuite/tests/javascript/opt/deadCodeElim.hs b/testsuite/tests/javascript/opt/deadCodeElim.hs new file mode 100644 index 0000000000..70f6aa6a74 --- /dev/null +++ b/testsuite/tests/javascript/opt/deadCodeElim.hs @@ -0,0 +1,96 @@ + +import GHC.JS.Optimizer +import GHC.JS.Syntax +import GHC.JS.Unsat.Syntax (Ident (..)) + +import GHC.Data.FastString + +double_return :: JStat +double_return = BlockStat [ ReturnStat (SatInt 0) + , ReturnStat (SatInt 1) + ] + +double_return_opt :: JStat +double_return_opt = (BlockStat [ReturnStat (SatInt 0)]) + +in_func :: JStat +in_func = AssignStat (jvar (fsLit "foo")) AssignOp (ValExpr (JFunc [] double_return)) + +in_func_opt :: JStat +in_func_opt = AssignStat (jvar (fsLit "foo")) AssignOp (ValExpr (JFunc [] double_return_opt)) + +nested_blocks :: JStat +nested_blocks = BlockStat [ double_return <> double_return + , double_return + ] <> double_return + +nested_blocks_opt :: JStat +nested_blocks_opt = double_return_opt + +global_func :: JStat +global_func = FuncStat (TxtI (fsLit "bar")) [] double_return + +global_func_opt :: JStat +global_func_opt = FuncStat (TxtI (fsLit "bar")) [] double_return_opt + +func_with_locals :: JStat +func_with_locals = AssignStat (jvar (fsLit "foo")) + AssignOp + (ValExpr (JFunc [] + (BlockStat [ AssignStat (jvar (fsLit "one")) AssignOp (SatInt 2) + , AssignStat (jvar (fsLit "two")) AssignOp (SatInt 3) + , ApplStat (jvar (fsLit "f")) [(SatInt 100)] + , ReturnStat (SatInt 0) + , ReturnStat (SatInt 1) + ]))) + +func_with_locals_opt :: JStat +func_with_locals_opt = AssignStat (jvar (fsLit "foo")) + AssignOp + (ValExpr (JFunc [] + (BlockStat [ AssignStat (jvar (fsLit "one")) AssignOp (SatInt 2) + , AssignStat (jvar (fsLit "two")) AssignOp (SatInt 3) + , ApplStat (jvar (fsLit "f")) [(SatInt 100)] + , ReturnStat (SatInt 0) + ]))) + +-- This one comes straight from MR10260 where we noticed the optimizer was not catching the redundant return +bignum_test :: JStat +bignum_test = DeclStat (TxtI $ fsLit "h$ghczmbignumZCGHCziNumziIntegerziintegerToInt64zh_e") + (Just (ValExpr $ JFunc [] $ BlockStat [ DeclStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e") (Just (jvar $ fsLit "h$r2")) + , ApplStat (jvar $ fsLit "h$p1") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99"] + , ReturnStat (ApplExpr (jvar $ fsLit "h$e") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e"]) + , ReturnStat (ApplExpr (jvar $ fsLit "h$rs") [])])) + +bignum_test_opt :: JStat +bignum_test_opt = + DeclStat (TxtI $ fsLit "h$ghczmbignumZCGHCziNumziIntegerziintegerToInt64zh_e") + (Just (ValExpr $ JFunc [] $ BlockStat [ DeclStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e") (Just (jvar $ fsLit "h$r2")) + , ApplStat (jvar $ fsLit "h$p1") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99"] + , ReturnStat (ApplExpr (jvar $ fsLit "h$e") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e"]) + ])) + +bignum_test_2 :: JStat +bignum_test_2 = BlockStat [FuncStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99") [] (BlockStat [DeclStat (TxtI $ fsLit "h$ghczmbignumZCGHCziNumziIntegerziintegerToInt64zh_e") + (Just (ValExpr $ JFunc [] $ BlockStat [ DeclStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e") (Just (jvar $ fsLit "h$r2")) + , ApplStat (jvar $ fsLit "h$p1") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99"] + , ReturnStat (ApplExpr (jvar $ fsLit "h$e") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e"]) + , ReturnStat (ApplExpr (jvar $ fsLit "h$rs") [])]))])] + +bignum_test_opt_2 :: JStat +bignum_test_opt_2 = BlockStat [FuncStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99") [] (BlockStat [DeclStat (TxtI $ fsLit "h$ghczmbignumZCGHCziNumziIntegerziintegerToInt64zh_e") + (Just (ValExpr $ JFunc [] $ BlockStat [ DeclStat (TxtI $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e") (Just (jvar $ fsLit "h$r2")) + , ApplStat (jvar $ fsLit "h$p1") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziInteger_99"] + , ReturnStat (ApplExpr (jvar $ fsLit "h$e") [jvar $ fsLit "h$$ghczmbignumZCGHCziNumziIntegerzids_s_2f9e"]) + ]))])] + +main :: IO () +main = mapM_ print + [ jsOptimize double_return == double_return_opt + , jsOptimize in_func == in_func_opt + , jsOptimize nested_blocks == nested_blocks_opt + , jsOptimize global_func == global_func_opt + , jsOptimize func_with_locals == func_with_locals_opt + , jsOptimize bignum_test == bignum_test_opt + , jsOptimize bignum_test_2 == bignum_test_opt_2 + ] diff --git a/testsuite/tests/javascript/opt/deadCodeElim.stdout b/testsuite/tests/javascript/opt/deadCodeElim.stdout new file mode 100644 index 0000000000..672e08f95c --- /dev/null +++ b/testsuite/tests/javascript/opt/deadCodeElim.stdout @@ -0,0 +1,7 @@ +True +True +True +True +True +True +True diff --git a/testsuite/tests/linters/notes.stdout b/testsuite/tests/linters/notes.stdout index 51fef76584..aed259caf9 100644 --- a/testsuite/tests/linters/notes.stdout +++ b/testsuite/tests/linters/notes.stdout @@ -7,7 +7,7 @@ ref compiler/GHC/Core/Opt/Simplify/Utils.hs:1343:37: Note [Gentle mode] ref compiler/GHC/Core/Opt/Specialise.hs:1790:28: Note [Arity decrease] ref compiler/GHC/Core/TyCo/Rep.hs:1556:31: Note [What prevents a constraint from floating] ref compiler/GHC/Driver/Main.hs:1762:34: Note [simpleTidyPgm - mkBootModDetailsTc] -ref compiler/GHC/Driver/Session.hs:3993:49: Note [Eta-reduction in -O0] +ref compiler/GHC/Driver/Session.hs:4062:49: Note [Eta-reduction in -O0] ref compiler/GHC/Hs/Expr.hs:194:63: Note [Pending Splices] ref compiler/GHC/Hs/Expr.hs:1736:87: Note [Lifecycle of a splice] ref compiler/GHC/Hs/Expr.hs:1772:7: Note [Pending Splices] @@ -15,6 +15,7 @@ ref compiler/GHC/Hs/Extension.hs:146:5: Note [Strict argument type constr ref compiler/GHC/Hs/Pat.hs:143:74: Note [Lifecycle of a splice] ref compiler/GHC/HsToCore/Pmc/Solver.hs:858:20: Note [COMPLETE sets on data families] ref compiler/GHC/HsToCore/Quote.hs:1476:7: Note [How brackets and nested splices are handled] +ref compiler/GHC/JS/Optimizer.hs:206:7: Note [Unsafe JavaScript optimizations] ref compiler/GHC/Stg/Unarise.hs:442:32: Note [Renaming during unarisation] ref compiler/GHC/StgToCmm.hs:106:18: Note [codegen-split-init] ref compiler/GHC/StgToCmm.hs:109:18: Note [pipeline-split-init] @@ -25,14 +26,14 @@ ref compiler/GHC/Tc/Gen/HsType.hs:2621:7: Note [Matching a kind signature ref compiler/GHC/Tc/Gen/Pat.hs:176:20: Note [Typing patterns in pattern bindings] ref compiler/GHC/Tc/Gen/Pat.hs:1127:7: Note [Matching polytyped patterns] ref compiler/GHC/Tc/Gen/Sig.hs:81:10: Note [Overview of type signatures] -ref compiler/GHC/Tc/Gen/Splice.hs:357:16: Note [How brackets and nested splices are handled] -ref compiler/GHC/Tc/Gen/Splice.hs:532:35: Note [PendingRnSplice] -ref compiler/GHC/Tc/Gen/Splice.hs:656:7: Note [How brackets and nested splices are handled] -ref compiler/GHC/Tc/Gen/Splice.hs:889:11: Note [How brackets and nested splices are handled] +ref compiler/GHC/Tc/Gen/Splice.hs:356:16: Note [How brackets and nested splices are handled] +ref compiler/GHC/Tc/Gen/Splice.hs:531:35: Note [PendingRnSplice] +ref compiler/GHC/Tc/Gen/Splice.hs:655:7: Note [How brackets and nested splices are handled] +ref compiler/GHC/Tc/Gen/Splice.hs:888:11: Note [How brackets and nested splices are handled] ref compiler/GHC/Tc/Instance/Family.hs:474:35: Note [Constrained family instances] ref compiler/GHC/Tc/Module.hs:711:15: Note [Extra dependencies from .hs-boot files] ref compiler/GHC/Tc/Solver/Rewrite.hs:1008:7: Note [Stability of rewriting] -ref compiler/GHC/Tc/TyCl.hs:1120:6: Note [Unification variables need fresh Names] +ref compiler/GHC/Tc/TyCl.hs:1124:6: Note [Unification variables need fresh Names] ref compiler/GHC/Tc/Types.hs:692:33: Note [Extra dependencies from .hs-boot files] ref compiler/GHC/Tc/Types.hs:1423:47: Note [Care with plugin imports] ref compiler/GHC/Tc/Types/Constraint.hs:255:34: Note [NonCanonical Semantics] @@ -46,8 +47,8 @@ ref hadrian/src/Expression.hs:145:30: Note [Linking ghc-bin against threa ref linters/lint-notes/Notes.hs:32:29: Note [" <> T.unpack x <> "] ref linters/lint-notes/Notes.hs:69:22: Note [...] ref testsuite/config/ghc:272:10: Note [WayFlags] -ref testsuite/driver/testlib.py:160:10: Note [Why is there no stage1 setup function?] -ref testsuite/driver/testlib.py:164:2: Note [Why is there no stage1 setup function?] +ref testsuite/driver/testlib.py:165:10: Note [Why is there no stage1 setup function?] +ref testsuite/driver/testlib.py:169:2: Note [Why is there no stage1 setup function?] ref testsuite/mk/boilerplate.mk:267:2: Note [WayFlags] ref testsuite/tests/indexed-types/should_fail/ExtraTcsUntch.hs:30:27: Note [Extra TcS Untouchables] ref testsuite/tests/perf/should_run/all.T:8:6: Note [Solving from instances when interacting Dicts] -- cgit v1.2.1