GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-06-11T08:58:55Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/18078Worker-wrapper optimization working in GHC 8.8 no longer works in 8.102020-06-11T08:58:55ZharendraWorker-wrapper optimization working in GHC 8.8 no longer works in 8.10## Summary
For a particular case in the streamly library, worker wrapper that was working well in GHC 8.8 does not seem to be working in 8.10.
## Steps to reproduce
1. Clone the streamly repo from https://github.com/composewell/stream...## Summary
For a particular case in the streamly library, worker wrapper that was working well in GHC 8.8 does not seem to be working in 8.10.
## Steps to reproduce
1. Clone the streamly repo from https://github.com/composewell/streamly . checkout the `ghc-8.10-worker-wrapper` branch.
2. Have ghc-8.8 in your PATH and use `cabal build streamly` to build
3. from the repo root run `ghc -O2 -fmax-worker-args=16 -ddump-simpl -ddump-to-file -dsuppress-all src/Streamly/Internal/Data/Stream/SVar.hs`
4. Save src/Streamly/Internal/Data/Stream/SVar.dump-simpl
Repeat these steps for ghc-8.10 and compare the resulting Core files. Look at the core of the function `fromStreamVar`. In GHC 8.8 the worker function `$wfromStreamVar` has calls to itself, whereas in GHC 8.10 it calls the wrapped function `fromStreamVar`.
I did a phase wise comparison of GHC 8.8 and 8.10 output and found that the code has almost no difference before the worker-wrapper bind phase, the above mentioned difference starts from that phase onwards. I am attaching the cores before and after worker-wrapper bind phase for both GHC 8.8 and 8.10 in this issue for quick look.
* [ghc-8.8-After-Demand-analysis.hs](/uploads/774f88f8e3487c4072b087915a74cebd/ghc-8.8-After-Demand-analysis.hs)
* [ghc-8.8-After-Worker-Wrapper-binds.hs](/uploads/81bdacd1c29e2b0f8a3ef89a3ec93c42/ghc-8.8-After-Worker-Wrapper-binds.hs)
* [ghc-8.10-After-Demand-analysis.hs](/uploads/a1271f04321aef0ba2b7959650f8e0f9/ghc-8.10-After-Demand-analysis.hs)
* [ghc-8.10-After-Worker-Wrapper-binds.hs](/uploads/5741a003936a740c929f0d3cc9080c54/ghc-8.10-After-Worker-Wrapper-binds.hs)
## Expected behavior
Worker wrapper should work in 8.10 in the same way as it works in 8.8 . If not what is the reason behind it why it cannot work?
## Environment
GHC 8.8 and GHC 8.10 comparison.
Optional:
Mac OS X x86_648.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/18012Case-of-known-constructor is broken in GHC 8.10 for floated DataCon wrappers2020-04-23T03:49:05ZAlexis KingCase-of-known-constructor is broken in GHC 8.10 for floated DataCon wrappersAs the issue title states, case-of-known-constructor does *not* fire if a `case` expression scrutinizes a floated-out value built from a DataCon wrapper. This program reproduces the issue:
```haskell
module KnownCon where
data T = D !B...As the issue title states, case-of-known-constructor does *not* fire if a `case` expression scrutinizes a floated-out value built from a DataCon wrapper. This program reproduces the issue:
```haskell
module KnownCon where
data T = D !Bool
f :: T -> T -> T
f (D a) (D b) = D (a && b)
{-# INLINE [100] f #-} -- so it isn’t inlined before FloatOut
g :: Bool -> T
g x = f (D True) (D x)
```
To see the bad behavior, we have to compile with `-dverbose-core2core`, since we need to see the output of simplifier phase 2 (or phase 1). Inspecting it shows that `D True` is floated out of `g` by FloatOut, and even though `f` is inlined, case-of-known-constructor does *not* fire!
```haskell
==================== Simplifier ====================
Max iterations = 4
SimplMode {Phase = 2 [main],
inline,
rules,
eta-expand,
case-of-case}
lvl_s1gm :: T
[LclId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False,
WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}]
lvl_s1gm = $WD True
g :: Bool -> T
[LclIdX,
Arity=1,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [20] 80 0}]
g = \ (x_a1eV :: Bool) ->
case lvl_s1gm of { D a_atX ->
case x_a1eV of dt_X0 { __DEFAULT ->
case a_atX of {
False -> $WD False;
True -> $WD dt_X0
}
}
}
```
This seems quite bad to me. It is a regression from GHC 8.8, since GHC 8.8 inlines DataCon wrappers much more aggressively.
---
The source of this issue appears to be the `Expandable=False` in the floated-out binding’s unfolding. The root cause is `isExpandableApp`, which does not classify applications of DataCon wrappers as expandable:
```haskell
isExpandableApp :: CheapAppFun
isExpandableApp fn n_val_args
| isWorkFreeApp fn n_val_args = True
| otherwise
= case idDetails fn of
DataConWorkId {} -> True -- Actually handled by isWorkFreeApp
RecSelId {} -> n_val_args == 1 -- See Note [Record selection]
ClassOpId {} -> n_val_args == 1
PrimOpId {} -> False
_ | isBottomingId fn -> False
-- See Note [isExpandableApp: bottoming functions]
| isConLike (idRuleMatchInfo fn) -> True
| all_args_are_preds -> True
| otherwise -> False
```
One point of note is that DataCon wrappers do not appear to be considered “conlike”; `isConLikeId` returns `True` on DataCon workers and ids with user-defined `CONLIKE` pragmas, but it returns `False` on DataCon wrappers. I suppose it is possible to argue in favor of this behavior, as it’s true that a DataCon wrapper is not work-free! But it is not an especially large amount of work, and the purpose of `CONLIKE` is to annotate something as worth duplicating *if and only if it exposes further optimizations*. From that perspective, DataCon wrappers certainly seem conlike to me.
In any case, DataCon wrappers definitely ought to be *expandable*, even if they are not conlike. In fact, `Note [exprIsConApp_maybe on data constructors with wrappers]` assumes they are:
```
1. Inline $WMkT on-the-fly. That's why data-constructor wrappers are marked
as expandable. (See GHC.Core.Utils.isExpandableApp.) Now we have
```
So this seems clearly a mistake to me.8.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/17619"Tick in rule" impossible error in 8.10.1-alpha2 using Megaparsec.2021-04-07T15:57:15ZGalen Huntington"Tick in rule" impossible error in 8.10.1-alpha2 using Megaparsec.## Summary
A parser I'm working on that uses [Megaparsec](https://hackage.haskell.org/package/megaparsec) (either 7.0.5 or 8.0.0) is failing to compile under the pre-release of 8.10.1 with an "impossible" error.
## Steps to reproduce
...## Summary
A parser I'm working on that uses [Megaparsec](https://hackage.haskell.org/package/megaparsec) (either 7.0.5 or 8.0.0) is failing to compile under the pre-release of 8.10.1 with an "impossible" error.
## Steps to reproduce
I have stripped it down to the following:
```haskell
module TickInRule where
import Control.Monad (void)
import Text.Megaparsec
import Text.Megaparsec.Char
foo :: String -> Parsec () String ()
foo s = do
manyTill (foo "a") (lookAhead $ void (string s) <|> eof)
void (string s)
```
(This parser doesn't make much sense of course, but I've removed everything not necessary for the error.)
I get this using `ghc -O2 bad.hs`:
```
[1 of 1] Compiling TickInRule ( bad.hs, bad.o )
ghc: panic! (the 'impossible' happened)
(GHC version 8.10.0.20191210:
Tick in rule
src<libraries/base/GHC/Base.hs:(1448,1)-(1453,15)>
src<libraries/base/Data/List/NonEmpty.hs:(187,1)-(190,51)>
src<libraries/base/GHC/Base.hs:(1403,1)-(1418,26)> lvl_s3lT
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/utils/Outputable.hs:1179:37 in ghc:Outputable
pprPanic, called at compiler/specialise/Rules.hs:720:5 in ghc:Rules
Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
```
Oddly, factoring out the void part (`let v = void (string s)`) makes the error go away; indeed, so does factoring out just `string s`.
Using no optimization or even `-O` also results in no error.
This is as far as I've gotten.
## Environment
* GHC version used: ghc-8.10.0.20191210-x86_64-deb9-linux-dwarf8.10.2Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/17151Optimizer produces Core with an infinite <<loop>> v22022-08-06T23:27:36ZAlexey KuleshevichOptimizer produces Core with an infinite <<loop>> v2## Summary
I am not quite sure what it is? Is it coincidence, my coding style or just luck. Two years later after I reported a bug #13429 about optimizer generating an infinite loop, I stumble upon exactly the same bug, while implementi...## Summary
I am not quite sure what it is? Is it coincidence, my coding style or just luck. Two years later after I reported a bug #13429 about optimizer generating an infinite loop, I stumble upon exactly the same bug, while implementing the same algorithm (convolution), but in a completely different library and using a totally different approach. There are some similarities in types, but I can't draw a concrete comparison.
Unlike previous bug #13429, which was applicable to ghc-8.0 and was supposably fixed in ghc-8.2, this one is triggered in ghc-8.2 and up, but not for the prior version.
It is way too easy not not trigger the bug, in fact I initially noticed my tests failing for ghc-8.4.4 only, but once I reduced it to a smaller example, my tests started failing for ghc-8.6.5 as well as ghc-8.8.1
I apologize for the size of the uploaded module, but it took me a while to reduce it even to that level.
## Steps to reproduce
Uploaded are the two files needed to reproduce the bug:
* [Main.hs](/uploads/336cf55e11fb30f34178d2d0cd1d4ffe/Main.hs)
* [Array.hs](/uploads/0680b1bdd353b7632f6d3d96e6d95f8b/Array.hs)
Those modules only depend on `primitive` package, but this is only for convenience, since this bug could equally well be reproduced using either `ForeignPtr` or by dropping down to `ByteArray#` or `MutableByteArray#` prims.
Compiling with optimizations is necessary to trigger the bug:
```shell
$ ghc Main.hs Array.hs -O1 -fforce-recomp && ./Main
[1 of 2] Compiling Array ( Array.hs, Array.o )
[2 of 2] Compiling Main ( Main.hs, Main.o )
Linking Main ...
Main: <<loop>>
```
When inspecting Core we can see where the loop occurs right away:
```
Rec {
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
$s$fConstructPixe1 :: Index Int
$s$fConstructPixe1 = $s$fConstructPixe1
end Rec }
```
I found something peculiar, which could be useful for debugging this issue, is that the `Construct` instance for `P` representation is not used anywhere directly in the source code.
## Expected behavior
No infinite loop in the produced binary.
## Environment
* GHC version used: 8.2.2 - 8.8.1
Optional:
* Operating System: Ubuntu 18.04 LTS
* System Architecture: x86_648.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/17133Performance regression in bsb-http-chunked from GHC-8.6.5 to GHC-8.8.12020-01-23T18:06:53ZSimon JakobiPerformance regression in bsb-http-chunked from GHC-8.6.5 to GHC-8.8.1Some benchmarks in the [`bsb-http-chunked` package](https://github.com/sjakobi/bsb-http-chunked) are [up to ~13% slower](https://github.com/sjakobi/bsb-http-chunked/issues/26) with GHC-8.8.1 when compared with GHC-8.6.5.
A diff of the C...Some benchmarks in the [`bsb-http-chunked` package](https://github.com/sjakobi/bsb-http-chunked) are [up to ~13% slower](https://github.com/sjakobi/bsb-http-chunked/issues/26) with GHC-8.8.1 when compared with GHC-8.6.5.
A diff of the Core of the relevant module can be viewed [here](https://github.com/sjakobi/bsb-http-chunked/commit/653179c18adcd3d08ce8f19e1f3d97d0cc993b6e). Virtually all changes are in the demand analysis annotations, so I suspect that this is the cause of the slowdown. [The module](https://github.com/sjakobi/bsb-http-chunked/blob/17f74814be7adeb60b09e6a52ff1aca9032e0f56/Data/ByteString/Builder/HTTP/Chunked.hs) depends only on `base` and `bytestring`, and `bytestring` didn't have any relevant code changes from v0.10.8.2 to v0.10.9.0.
I don't really understand demand analysis, but one questions that popped up was, why multiple let-bindings lost their `[Dmd=<S,U>]` annotation although they are used in case analyses right after their definitions. For example `outRemaining`:
```
let {
outRemaining :: ghc-prim-0.5.3:GHC.Prim.Int#
[LclId]
outRemaining = ghc-prim-0.5.3:GHC.Prim.minusAddr# ww1 ww } in
case ghc-prim-0.5.3:GHC.Prim.<# outRemaining 23# of {
```
Another question is why a join point binding previously called `exit`, was renamed to `w$j` and gained the annotation `InlPrag=NOUSERINLINE[2]`.
```
join {
$w$j [InlPrag=NOUSERINLINE[2], Dmd=<C(S),C(U(U,U))>]
:: ghc-prim-0.5.3:GHC.Prim.State# ghc-prim-0.5.3:GHC.Prim.RealWorld
-> (# ghc-prim-0.5.3:GHC.Prim.State#
ghc-prim-0.5.3:GHC.Prim.RealWorld,
BuildSignal r #)
[LclId[JoinId(1)], Arity=1, Str=<L,U>]
```8.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/7411Exceptions are optimized away in certain situations2020-05-27T16:04:30ZSimon Hengelsol@typeful.netExceptions are optimized away in certain situationsThe issue came up in [this thread on glasgow-haskell-users](http://www.haskell.org/pipermail/glasgow-haskell-users/2012-November/023027.html).
## Steps to reproduce:
```hs
-- file Foo.hs
import Control.Exception
import Control.DeepSeq
...The issue came up in [this thread on glasgow-haskell-users](http://www.haskell.org/pipermail/glasgow-haskell-users/2012-November/023027.html).
## Steps to reproduce:
```hs
-- file Foo.hs
import Control.Exception
import Control.DeepSeq
main = evaluate (('a' : undefined) `deepseq` return () :: IO ())
```
```
$ ghc -fforce-recomp -fpedantic-bottoms -O Foo.hs
```
### Expected result:
The program should fail with:
```
Foo: Prelude.undefined
```
### Actual result:
The program succeeds.
Compiling the program with `-fno-state-hack` helps.8.10.2Tobias Dammerstdammers@gmail.comTobias Dammerstdammers@gmail.com