GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:32:14Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/11071"Not in scope" errors should be more informative for qualified names.2019-07-07T18:32:14Zmojojojo"Not in scope" errors should be more informative for qualified names.E.g., if I have something like `Maybe.maybeToList` in a module, which does not have such an import, I get the following error:
> Not in scope: ‘Maybe.maybeToList’
Which leads the user to conclude that the `Maybe` namespace does not co...E.g., if I have something like `Maybe.maybeToList` in a module, which does not have such an import, I get the following error:
> Not in scope: ‘Maybe.maybeToList’
Which leads the user to conclude that the `Maybe` namespace does not contain the `maybeToList` element, instead of informing that the `Maybe` namespace is not imported altogether instead8.0.1Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.dehttps://gitlab.haskell.org/ghc/ghc/-/issues/10186exprIsBottom should include isEmptyTy2019-07-07T18:37:11ZJoachim Breitnermail@joachim-breitner.deexprIsBottom should include isEmptyTyThis is a spin-of of [ticket:10180\#comment:97618](https://gitlab.haskell.org//ghc/ghc/issues/10180#note_97618): `exprIsBottom` (which currently only takes strictnes signatures into account) should also look at the type, via the new `isE...This is a spin-of of [ticket:10180\#comment:97618](https://gitlab.haskell.org//ghc/ghc/issues/10180#note_97618): `exprIsBottom` (which currently only takes strictnes signatures into account) should also look at the type, via the new `isEmptyTy`.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.8.4 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"exprIsBottom should include isEmptyTy","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"nomeata"},"version":"7.8.4","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"This is a spin-of of comment:3:ticket:10180: `exprIsBottom` (which currently only takes strictnes signatures into account) should also look at the type, via the new `isEmptyTy`.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.dehttps://gitlab.haskell.org/ghc/ghc/-/issues/10180Lint check: Empty alternatives imply bottoming scrutinee2019-07-07T18:37:12ZJoachim Breitnermail@joachim-breitner.deLint check: Empty alternatives imply bottoming scrutineeAs suggested by SPJ in https://phabricator.haskell.org/D747?id=2498\#inline-6057
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7...As suggested by SPJ in https://phabricator.haskell.org/D747?id=2498\#inline-6057
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.11 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Lint check: Empty alternatives imply bottoming scrutinee","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"nomeata"},"version":"7.11","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"As suggested by SPJ in https://phabricator.haskell.org/D747?id=2498#inline-6057","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.dehttps://gitlab.haskell.org/ghc/ghc/-/issues/10137Rewrite switch code generation2020-05-02T22:40:04ZJoachim Breitnermail@joachim-breitner.deRewrite switch code generationInspired by #10124 I looked at the code generation for enumeration and integer types, and I think this can be improved in a few ways. My goals are:
- Fancier code for integer types. Currently, the code for enumeration types will emit ju...Inspired by #10124 I looked at the code generation for enumeration and integer types, and I think this can be improved in a few ways. My goals are:
- Fancier code for integer types. Currently, the code for enumeration types will emit jump tables for dense choices; there is no reason to treat integer types differently.
- The ability to behave differently if some of the case alternatives are equal, and, as an extension of that,
- The possibility to create branchless code if multiple checks would go to the same jump.
The current scheme is roughly:
- When we generate Cmm code for a STG case expression, we handle enumeration types and literals separately.
- At this point, the decisions about what code to generate are made (jump tables (but only for enumeration types) or if-then-else trees).
- The Common Block Optimization on Cmm happens later in the pipeline, making it non-trivial to detect branches that do the same thing.
My plan is the following:
- In the STG→Cmm transformation, floats will be handled separately. Matching against literals is fishy anyways, so my suggestion is to simply generate a linear list of equality checks here – turning the intended operation (equality test) into something else (comparisons in a if-then-else tree) feels wrong to me for floats. And the rest would not work well for floats, so I’d like to have them out of the way.
- The case of enumeration types will be reduced to word literals, and treated the same from now on.
- For integer types, no code generation decisions is made at this point. Instead, always a `CmmSwitch` statement is generated.
- In a separate Cmm transformation pass, which will run /after/ the common block optimization, we visit all `CmmSwitches` and create proper code for them.
I’d like to separate the algorithm that plans the code generation into a function (possibly even module) of its own, so that the decisions can easily by analyized and modified.
The algorithm has a few choices to make:
- If multiple values point to the same code, we can generate branchless code (`y := x == 1 || x == 5 || x = 7; if (y==0) then goto l1 else goto l2`).
- If there are whole ranges pointing to the same code, the above can also use comparisons.
- If there are dense ranges (i.e. a range with more than half of the possible values mapped to something), we want to generate jump tables from them (still `CmmSwitch` values).
- Unless all options are handled by one of these possibilities, they need to be combined using `if-then-else` trees.
The `CmmSwitch` constructor needs to change for that. It currently takes a `[Maybe Label]` argument, which is not suitable for before that pass, when its table may be sparse. I think an `IntMap Label` would work nicely.8.0.1Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.dehttps://gitlab.haskell.org/ghc/ghc/-/issues/9020Massive blowup of code size on trivial program2021-09-25T20:04:42ZSimon Peyton JonesMassive blowup of code size on trivial programThe test `simplCore/should_compile/simpl015` was leading to massive compile times. This is weird: it looks like:
```
main = do { return ()
; return ()
... hundreds more times ...
; return () }
```
It turns...The test `simplCore/should_compile/simpl015` was leading to massive compile times. This is weird: it looks like:
```
main = do { return ()
; return ()
... hundreds more times ...
; return () }
```
It turns out that the cause was over-eager eta-expansion. Each `return ()` gives a top-level PAP thus
```
lvl17 :: IO ()
lvl17 = returnIO ()
```
But these definitions are then eta-expanded, thus:
```
lvl17 = ((\eta. returnIO () |> sym g) eta) |> g
where g :: State# RealWorld -> (# State# RealWorld, () #)
~
IO ()
```
Now in general it makes sense to eta-expand through newtypes (as is done here), because it exposes more lambadas. But it really doesn't make sense to eta-expand a PAP like this.
Fortunately the fix is easy: use `exprArity` rather than `manifestArity` in `SimplUtils.tryEtaExpandRhs`.
The effect on `simpl015` is dramatic: compiler allocation drops from 6.6G to 812M; and residency drops from 1.8G to 45M.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.8.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Massive blowup of code size on trivial program","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The test `simplCore/should_compile/simpl015` was leading to massive compile times. This is weird: it looks like:\r\n{{{\r\nmain = do { return ()\r\n ; return ()\r\n ... hundreds more times ...\r\n ; return () }\r\n}}}\r\nIt turns out that the cause was over-eager eta-expansion. Each `return ()` gives a top-level PAP thus\r\n{{{\r\nlvl17 :: IO ()\r\nlvl17 = returnIO ()\r\n}}}\r\nBut these definitions are then eta-expanded, thus:\r\n{{{\r\nlvl17 = ((\\eta. returnIO () |> sym g) eta) |> g\r\n\r\n where g :: State# RealWorld -> (# State# RealWorld, () #)\r\n ~\r\n IO ()\r\n}}}\r\nNow in general it makes sense to eta-expand through newtypes (as is done here), because it exposes more lambadas. But it really doesn't make sense to eta-expand a PAP like this.\r\n\r\nFortunately the fix is easy: use `exprArity` rather than `manifestArity` in `SimplUtils.tryEtaExpandRhs`.\r\n\r\nThe effect on `simpl015` is dramatic: compiler allocation drops from 6.6G to 812M; and residency drops from 1.8G to 45M.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.de