summaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2020-08-24 14:36:57 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-09-22 05:37:24 -0400
commit6de40f83c53c3b1899f7b4912badbe98e4fbde88 (patch)
tree9a311c2630a5ecd66abcee3a02ce8efef7364262 /testsuite
parentaaa51dcfdb729f130aeefeaeac15029b62096a74 (diff)
downloadhaskell-6de40f83c53c3b1899f7b4912badbe98e4fbde88.tar.gz
Better eta-expansion (again) and don't specilise DFuns
This patch fixes #18223, which made GHC generate an exponential amount of code. There are three quite separate changes in here 1. Re-engineer eta-expansion (again). The eta-expander was generating lots of intermediate stuff, which could be optimised away, but which choked the simplifier meanwhile. Relatively easy to kill it off at source. See Note [The EtaInfo mechanism] in GHC.Core.Opt.Arity. The main new thing is the use of pushCoArg in getArg_maybe. 2. Stop Specialise specalising DFuns. This is the cause of a huge (and utterly unnecessary) blowup in program size in #18223. See Note [Do not specialise DFuns] in GHC.Core.Opt.Specialise. I also refactored the Specialise monad a bit... it was silly, because it passed on unchanging values as if they were mutable state. 3. Do an extra Simplifer run, after SpecConstra and before late-Specialise. I found (investigating perf/compiler/T16473) that failing to do this was crippling *both* SpecConstr *and* Specialise. See Note [Simplify after SpecConstr] in GHC.Core.Opt.Pipeline. This change does mean an extra run of the Simplifier, but only with -O2, and I think that's acceptable. T16473 allocates *three* times less with this change. (I changed it to check runtime rather than compile time.) Some smaller consequences * I moved pushCoercion, pushCoArg and friends from SimpleOpt to Arity, because it was needed by the new etaInfoApp. And pushCoValArg now returns a MCoercion rather than Coercion for the argument Coercion. * A minor, incidental improvement to Core pretty-printing This does fix #18223, (which was otherwise uncompilable. Hooray. But there is still a big intermediate because there are some very deeply nested types in that program. Modest reductions in compile-time allocation on a couple of benchmarks T12425 -2.0% T13253 -10.3% Metric increase with -O2, due to extra simplifier run T9233 +5.8% T12227 +1.8% T15630 +5.0% There is a spurious apparent increase on heap residency on T9630, on some architectures at least. I tried it with -G1 and the residency is essentially unchanged. Metric Increase T9233 T12227 T9630 Metric Decrease T12425 T13253
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/tests/perf/compiler/Makefile4
-rw-r--r--testsuite/tests/perf/compiler/T16473.stdout98
-rw-r--r--testsuite/tests/perf/compiler/T18223.hs78
-rw-r--r--testsuite/tests/perf/compiler/all.T13
-rw-r--r--testsuite/tests/printer/T18052a.stderr2
-rw-r--r--testsuite/tests/simplCore/should_compile/T17966.stdout3
-rw-r--r--testsuite/tests/stranal/should_compile/T18122.stderr40
7 files changed, 111 insertions, 127 deletions
diff --git a/testsuite/tests/perf/compiler/Makefile b/testsuite/tests/perf/compiler/Makefile
index b27c842e91..ded99684b3 100644
--- a/testsuite/tests/perf/compiler/Makefile
+++ b/testsuite/tests/perf/compiler/Makefile
@@ -7,7 +7,3 @@ T4007:
$(RM) -f T4007.hi T4007.o
'$(TEST_HC)' $(TEST_HC_OPTS) -c -O -ddump-rule-firings T4007.hs
-T16473:
- $(RM) -f T16473.hi T16473.o
- '$(TEST_HC)' $(TEST_HC_OPTS) -c -O -ddump-rule-firings T16473.hs
-
diff --git a/testsuite/tests/perf/compiler/T16473.stdout b/testsuite/tests/perf/compiler/T16473.stdout
index e6063e01e8..c3ac783e70 100644
--- a/testsuite/tests/perf/compiler/T16473.stdout
+++ b/testsuite/tests/perf/compiler/T16473.stdout
@@ -1,97 +1 @@
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op liftA2 (BUILTIN)
-Rule fired: Class op <*> (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: Class op <$ (BUILTIN)
-Rule fired: Class op <*> (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op get (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op >> (BUILTIN)
-Rule fired: Class op put (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op get (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op >> (BUILTIN)
-Rule fired: Class op put (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op show (BUILTIN)
-Rule fired: Class op mempty (BUILTIN)
-Rule fired: Class op fromInteger (BUILTIN)
-Rule fired: Integer -> Int# (BUILTIN)
-Rule fired: Class op <> (BUILTIN)
-Rule fired: Class op + (BUILTIN)
-Rule fired: Class op enumFromTo (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op *> (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: fold/build (GHC.Base)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: ># (BUILTIN)
-Rule fired: ==# (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op <*> (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op pure (BUILTIN)
-Rule fired: Class op $p1Monad (BUILTIN)
-Rule fired: Class op $p1Applicative (BUILTIN)
-Rule fired: SPEC/Main $fMonadStateT_$c>>= @Identity _ (Main)
-Rule fired: SPEC/Main $fApplicativeStateT_$c<*> @Identity _ (Main)
-Rule fired: SPEC/Main $fApplicativeStateT_$cpure @Identity _ (Main)
-Rule fired: SPEC/Main $fFunctorStateT @Identity _ (Main)
-Rule fired: SPEC/Main $fFunctorStateT_$cfmap @Identity _ (Main)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: SPEC/Main $fFunctorStateT_$cfmap @Identity _ (Main)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op fmap (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op return (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op >>= (BUILTIN)
-Rule fired: Class op return (BUILTIN)
+5050
diff --git a/testsuite/tests/perf/compiler/T18223.hs b/testsuite/tests/perf/compiler/T18223.hs
new file mode 100644
index 0000000000..3e160cc957
--- /dev/null
+++ b/testsuite/tests/perf/compiler/T18223.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE PartialTypeSignatures #-}
+{-# LANGUAGE Strict #-}
+
+import Control.Monad.State
+
+tester :: MonadState a m => m ()
+tester = modify' id
+
+-- manyState :: StateT () (StateT () IO) () -> IO ()
+-- manyState :: _ -> IO ()
+manyState x =
+ (flip evalStateT () -- 1
+ . flip evalStateT () -- 2
+ . flip evalStateT () -- 3
+ . flip evalStateT () -- 4
+ . flip evalStateT () -- 5
+ . flip evalStateT () -- 6
+ . flip evalStateT () -- 7
+ . flip evalStateT () -- 8
+ . flip evalStateT () -- 9
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ . flip evalStateT ()
+ ) x :: IO ()
+
+main :: IO ()
+main = manyState tester >>= print
diff --git a/testsuite/tests/perf/compiler/all.T b/testsuite/tests/perf/compiler/all.T
index a8eea78729..f6e56c56b3 100644
--- a/testsuite/tests/perf/compiler/all.T
+++ b/testsuite/tests/perf/compiler/all.T
@@ -367,7 +367,13 @@ test('T16190',
multimod_compile,
['T16190.hs', '-v0'])
-test('T16473', normal, makefile_test, ['T16473'])
+# Run this program. If specialisation fails, it'll start to allocate much more
+test ('T16473',
+ [ collect_stats('bytes allocated',5)
+ , only_ways(['normal'])
+ ],
+ compile_and_run,
+ ['-O2 -flate-specialise'])
test('T17516',
[ collect_compiler_stats('bytes allocated', 5),
@@ -415,3 +421,8 @@ test ('T13253-spj',
],
compile,
['-v0 -O'])
+test ('T18223',
+ [ collect_compiler_stats('bytes allocated',2)
+ ],
+ compile,
+ ['-v0 -O'])
diff --git a/testsuite/tests/printer/T18052a.stderr b/testsuite/tests/printer/T18052a.stderr
index a45c9c958c..d8d9f94ba3 100644
--- a/testsuite/tests/printer/T18052a.stderr
+++ b/testsuite/tests/printer/T18052a.stderr
@@ -20,7 +20,7 @@ T18052a.$b:||: = \ (@a) (@b) (x :: a) (y :: b) -> (x, y)
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
(+++) :: forall {a}. [a] -> [a] -> [a]
[GblId]
-(+++) = (++)
+(+++) = ++
-- RHS size: {terms: 13, types: 20, coercions: 0, joins: 0/0}
T18052a.$m:||:
diff --git a/testsuite/tests/simplCore/should_compile/T17966.stdout b/testsuite/tests/simplCore/should_compile/T17966.stdout
index dc34ec8fae..9abaee2af2 100644
--- a/testsuite/tests/simplCore/should_compile/T17966.stdout
+++ b/testsuite/tests/simplCore/should_compile/T17966.stdout
@@ -1,5 +1,2 @@
RULES: "SPEC $cm @()" [0]
RULES: "SPEC f @Bool @() @(Maybe Integer)" [0]
-"SPEC/T17966 $fShowMaybe_$cshow @Integer"
-"SPEC/T17966 $fShowMaybe_$cshowList @Integer"
-"SPEC/T17966 $fShowMaybe @Integer"
diff --git a/testsuite/tests/stranal/should_compile/T18122.stderr b/testsuite/tests/stranal/should_compile/T18122.stderr
index ff18350279..f94751fb55 100644
--- a/testsuite/tests/stranal/should_compile/T18122.stderr
+++ b/testsuite/tests/stranal/should_compile/T18122.stderr
@@ -13,9 +13,8 @@ Lib.$trModule4 = "main"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Lib.$trModule3 :: GHC.Types.TrName
[GblId,
- Cpr=m1,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
Lib.$trModule3 = GHC.Types.TrNameS Lib.$trModule4
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
@@ -28,27 +27,25 @@ Lib.$trModule2 = "Lib"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Lib.$trModule1 :: GHC.Types.TrName
[GblId,
- Cpr=m1,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
Lib.$trModule1 = GHC.Types.TrNameS Lib.$trModule2
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
Lib.$trModule :: GHC.Types.Module
[GblId,
- Cpr=m1,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 30}]
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
Lib.$trModule = GHC.Types.Module Lib.$trModule3 Lib.$trModule1
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
Lib.$wfoo [InlPrag=NOINLINE]
:: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=2, Str=<L,U><L,U>, Unf=OtherCon []]
-Lib.$wfoo = (GHC.Prim.+#)
+Lib.$wfoo = GHC.Prim.+#
-- RHS size: {terms: 18, types: 14, coercions: 0, joins: 0/0}
-foo [InlPrag=NOUSERINLINE[0]] :: (Int, Int) -> Int -> Int
+foo [InlPrag=NOUSERINLINE[final]] :: (Int, Int) -> Int -> Int
[GblId,
Arity=2,
Str=<S(SL),1*U(1*U(U),A)><S,1*U(U)>,
@@ -56,24 +53,25 @@ foo [InlPrag=NOUSERINLINE[0]] :: (Int, Int) -> Int -> Int
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
- Tmpl= \ (w_sHs [Occ=Once!] :: (Int, Int))
- (w1_sHt [Occ=Once!] :: Int) ->
- case w_sHs of { (ww1_sHw [Occ=Once!], _ [Occ=Dead]) ->
- case ww1_sHw of { GHC.Types.I# ww4_sHz [Occ=Once] ->
- case w1_sHt of { GHC.Types.I# ww6_sHF [Occ=Once] ->
- case Lib.$wfoo ww4_sHz ww6_sHF of ww7_sHJ [Occ=Once] { __DEFAULT ->
- GHC.Types.I# ww7_sHJ
+ Tmpl= \ (w_sEf [Occ=Once1!] :: (Int, Int))
+ (w1_sEg [Occ=Once1!] :: Int) ->
+ case w_sEf of { (ww1_sEj [Occ=Once1!], _ [Occ=Dead]) ->
+ case ww1_sEj of { GHC.Types.I# ww4_sEm [Occ=Once1] ->
+ case w1_sEg of { GHC.Types.I# ww6_sEs [Occ=Once1] ->
+ case Lib.$wfoo ww4_sEm ww6_sEs of ww7_sEw [Occ=Once1]
+ { __DEFAULT ->
+ GHC.Types.I# ww7_sEw
}
}
}
}}]
foo
- = \ (w_sHs :: (Int, Int)) (w1_sHt :: Int) ->
- case w_sHs of { (ww1_sHw, ww2_sHB) ->
- case ww1_sHw of { GHC.Types.I# ww4_sHz ->
- case w1_sHt of { GHC.Types.I# ww6_sHF ->
- case Lib.$wfoo ww4_sHz ww6_sHF of ww7_sHJ { __DEFAULT ->
- GHC.Types.I# ww7_sHJ
+ = \ (w_sEf :: (Int, Int)) (w1_sEg :: Int) ->
+ case w_sEf of { (ww1_sEj, ww2_sEo) ->
+ case ww1_sEj of { GHC.Types.I# ww4_sEm ->
+ case w1_sEg of { GHC.Types.I# ww6_sEs ->
+ case Lib.$wfoo ww4_sEm ww6_sEs of ww7_sEw { __DEFAULT ->
+ GHC.Types.I# ww7_sEw
}
}
}