Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
b3ddee95
by Andreas Klebinger at 2026-08-28T13:57:46-04:00
-
a1d81390
by Andreas Klebinger at 2026-08-28T13:58:37-04:00
-
5bd65f00
by Andreas Klebinger at 2026-08-28T13:59:16-04:00
-
e3760dba
by mangoiv at 2026-08-29T03:15:03-04:00
-
0a5cb788
by Andreas Klebinger at 2026-08-29T03:15:03-04:00
22 changed files:
- .gitlab-ci.yml
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- + changelog.d/T27705
- + changelog.d/T27722-cbe-entry-block.md
- compiler/GHC/Cmm/CommonBlockElim.hs
- compiler/GHC/Core/Opt/Specialise.hs
- hadrian/README.md
- hadrian/doc/cross-compile.md
- hadrian/doc/flavours.md
- hadrian/doc/make.md
- hadrian/doc/windows.md
- hadrian/hadrian.cabal
- hadrian/src/CommandLine.hs
- hadrian/src/Flavour.hs
- hadrian/src/Settings.hs
- − hadrian/src/Settings/Flavours/Quickest.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/simplCore/should_run/T27705.hs
- + testsuite/tests/simplCore/should_run/T27705.stdout
- + testsuite/tests/simplCore/should_run/T27705_Inst.hs
- testsuite/tests/simplCore/should_run/all.T
- utils/ghc-toolchain/src/GHC/Toolchain/Target.hs
Changes:
| ... | ... | @@ -1300,7 +1300,7 @@ ghcup-metadata-nightly: |
| 1300 | 1300 | artifacts: false
|
| 1301 | 1301 | - job: project-version
|
| 1302 | 1302 | script:
|
| 1303 | - - nix shell -f .gitlab/rel_eng -c ghcup-metadata --metadata ghcup-0.0.7.yaml --date="$(date -d $CI_PIPELINE_CREATED_AT +%Y-%m-%d)" --pipeline-id="$CI_PIPELINE_ID" --version="$ProjectVersion" > "metadata_test.yaml"
|
|
| 1303 | + - nix shell -f .gitlab/rel_eng -c ghcup-metadata --metadata ghcup-0.0.7.yaml --date="$(date -d $CI_PIPELINE_CREATED_AT +%Y-%m-%d)" --pipeline-id="$CI_PIPELINE_ID" --version="$ProjectVersion" metadata_test.yaml
|
|
| 1304 | 1304 | rules:
|
| 1305 | 1305 | - if: $NIGHTLY
|
| 1306 | 1306 |
| ... | ... | @@ -324,6 +324,7 @@ def main() -> None: |
| 324 | 324 | # TODO: We could work out the --version from the project-version CI job.
|
| 325 | 325 | parser.add_argument('--version', required=True, type=str, help='Version of the GHC compiler')
|
| 326 | 326 | parser.add_argument('--date', required=True, type=str, help='Date of the compiler release')
|
| 327 | + parser.add_argument('output_path', nargs='?', type=Path, help='Path to write the output to, if not set, dump to stdout')
|
|
| 327 | 328 | args = parser.parse_args()
|
| 328 | 329 | |
| 329 | 330 | project = gl.projects.get(1, lazy=True)
|
| ... | ... | @@ -352,13 +353,14 @@ def main() -> None: |
| 352 | 353 | with open(args.metadata, 'r') as file:
|
| 353 | 354 | ghcup_metadata = yaml.safe_load(file)
|
| 354 | 355 | if args.version in ghcup_metadata['ghcupDownloads']['GHC']:
|
| 355 | - # if there are days without a commit, then the nightly metadata
|
|
| 356 | - # is up to date by default, no need to fail, no need to upload anything
|
|
| 357 | - print("Refusing to override existing version in metadata, exiting")
|
|
| 358 | - sys.exit()
|
|
| 356 | + eprint("GHCUp nightly run produced the same metadata as last night")
|
|
| 359 | 357 | setNightlyTags(ghcup_metadata)
|
| 360 | 358 | ghcup_metadata['ghcupDownloads']['GHC'][args.version] = new_yaml
|
| 361 | - print(yaml.dump(ghcup_metadata))
|
|
| 359 | + if args.output_path:
|
|
| 360 | + with open(args.output_path, 'w') as ofile:
|
|
| 361 | + yaml.dump(ghcup_metadata, ofile)
|
|
| 362 | + else:
|
|
| 363 | + print(yaml.dump(ghcup_metadata))
|
|
| 362 | 364 | |
| 363 | 365 | |
| 364 | 366 |
| 1 | +section: compiler
|
|
| 2 | +synopsis: Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses.
|
|
| 3 | +issues: #27705
|
|
| 4 | +mrs: !16559
|
|
| 5 | + |
| 1 | +section: cmm
|
|
| 2 | +issues: #27722
|
|
| 3 | +mrs: !16592
|
|
| 4 | +synopsis:
|
|
| 5 | + Fix common block elimination dropping entry block info table in hand written cmm. |
| ... | ... | @@ -26,6 +26,7 @@ import GHC.Types.Literal.Floating |
| 26 | 26 | import GHC.Types.Unique.FM
|
| 27 | 27 | import GHC.Types.Unique
|
| 28 | 28 | import GHC.Utils.Word64 (truncateWord64ToWord32)
|
| 29 | +import GHC.Utils.Panic.Plain (assert)
|
|
| 29 | 30 | import Control.Arrow (first, second)
|
| 30 | 31 | import Data.List.NonEmpty (NonEmpty (..))
|
| 31 | 32 | import qualified Data.List.NonEmpty as NE
|
| ... | ... | @@ -60,16 +61,31 @@ import qualified Data.List.NonEmpty as NE |
| 60 | 61 | |
| 61 | 62 | -- TODO: Use optimization fuel
|
| 62 | 63 | elimCommonBlocks :: CmmGraph -> CmmGraph
|
| 63 | -elimCommonBlocks g = replaceLabels env $ copyTicks env g
|
|
| 64 | +elimCommonBlocks g =
|
|
| 65 | + assert (g_entry g == g_entry g') g'
|
|
| 64 | 66 | where
|
| 67 | + g' = replaceLabels env $ copyTicks env g
|
|
| 65 | 68 | env = iterate mapEmpty blocks_with_key
|
| 66 | 69 | -- The order of blocks doesn't matter here. While we could use
|
| 67 | 70 | -- revPostorder which drops unreachable blocks this is done in
|
| 68 | 71 | -- ContFlowOpt already which runs before this pass. So we use
|
| 69 | 72 | -- toBlockList since it is faster.
|
| 70 | - groups = groupByInt hash_block (toBlockList g) :: [[CmmBlock]]
|
|
| 73 | + -- One exception: The entry block most come first or we risk eliminating it
|
|
| 74 | + -- in favour of another block. See Note [Retain entry block during common block elimination.]
|
|
| 75 | + groups = groupByInt hash_block (toBlockListEntryFirst g) :: [[CmmBlock]]
|
|
| 71 | 76 | blocks_with_key = [ [ (successors b, [b]) | b <- bs] | bs <- groups]
|
| 72 | 77 | |
| 78 | +-- Note [Retain entry block during common block elimination.]
|
|
| 79 | +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 80 | +-- At the stage we run common block elimination (CBE) we only have one info
|
|
| 81 | +-- table for the entry label. Which means we can get away without applying the
|
|
| 82 | +-- block label substitution to the info table *as long as we keep the first block*.
|
|
| 83 | +-- When combining blocks the first block in the list of blocks is kept, and the later
|
|
| 84 | +-- one eliminated, so we can achieve this by simply using toBlockListEntryFirst.
|
|
| 85 | +--
|
|
| 86 | +-- If we don't we end up with #27722 where the entry block was eliminated in favour
|
|
| 87 | +-- of another block.
|
|
| 88 | + |
|
| 73 | 89 | -- Invariant: The blocks in the list are pairwise distinct
|
| 74 | 90 | -- (so avoid comparing them again)
|
| 75 | 91 | type DistinctBlocks = [CmmBlock]
|
| ... | ... | @@ -3120,8 +3120,8 @@ interestingDict :: SpecEnv -> CoreExpr -> Bool |
| 3120 | 3120 | -- This is a subtle and important function
|
| 3121 | 3121 | -- See Note [Interesting dictionary arguments]
|
| 3122 | 3122 | interestingDict env (Var v) -- See (ID3) and (ID5)
|
| 3123 | + -- (ID6.a) Might fail for loop breaker dicts but that seems fine.
|
|
| 3123 | 3124 | | Just rhs <- maybeUnfoldingTemplate (idUnfolding v)
|
| 3124 | - -- Might fail for loop breaker dicts but that seems fine.
|
|
| 3125 | 3125 | = interestingDict env rhs
|
| 3126 | 3126 | |
| 3127 | 3127 | interestingDict env arg -- Main Plan: use exprIsConApp_maybe
|
| ... | ... | @@ -3136,9 +3136,9 @@ interestingDict env arg -- Main Plan: use exprIsConApp_maybe |
| 3136 | 3136 | , isIPClass cls -- See (ID5)
|
| 3137 | 3137 | -> False
|
| 3138 | 3138 | |
| 3139 | - -- Otherwise we are unwrapping a unary type class
|
|
| 3139 | + -- Shouldn't happen.
|
|
| 3140 | 3140 | | otherwise
|
| 3141 | - -> exprIsHNF arg -- See (ID7)
|
|
| 3141 | + -> pprTraceDebug "shouldn't happen anymore" (ppr arg) $ exprIsHNF arg -- See (ID7)
|
|
| 3142 | 3142 | |
| 3143 | 3143 | | Just (_, _, data_con, _tys, args) <- exprIsConApp_maybe in_scope_env arg
|
| 3144 | 3144 | , Just cls <- tyConClass_maybe (dataConTyCon data_con)
|
| ... | ... | @@ -3152,7 +3152,8 @@ interestingDict env arg -- Main Plan: use exprIsConApp_maybe |
| 3152 | 3152 | where
|
| 3153 | 3153 | arg_ty = exprType arg
|
| 3154 | 3154 | definitely_not_ip_like = not (couldBeIPLike arg_ty)
|
| 3155 | - in_scope_env = ISE (substInScopeSet $ se_subst env) realIdUnfolding
|
|
| 3155 | + -- idUnfolding rather than realIdUnfolding: See (ID6.a)
|
|
| 3156 | + in_scope_env = ISE (substInScopeSet $ se_subst env) idUnfolding
|
|
| 3156 | 3157 | |
| 3157 | 3158 | {- Note [Ticks on applications]
|
| 3158 | 3159 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -3268,11 +3269,27 @@ case we can clearly specialise. But there are wrinkles: |
| 3268 | 3269 | (Remember: a constraint tuple is just a class with N superclasses and no methods.)
|
| 3269 | 3270 | See discussion on #26831.
|
| 3270 | 3271 | |
| 3271 | -(ID7) A unary (single-method) class is currently represented by (meth |> co). We
|
|
| 3272 | - will unwrap the cast (see (ID5)) and then want to reply "yes" if the method
|
|
| 3273 | - has any struture. We rather arbitrarily use `exprIsHNF` for this. (We plan a
|
|
| 3274 | - new story for unary classes, see #23109, and this special case will become
|
|
| 3275 | - irrelevant.)
|
|
| 3272 | +(ID6.a) If we deal with a recursive dictionary as in #27705 we want to avoid
|
|
| 3273 | + infinite recursion while recursing into superclasses.
|
|
| 3274 | + |
|
| 3275 | + For example we might have:
|
|
| 3276 | + |
|
| 3277 | + class D1 a => D2 a
|
|
| 3278 | + class D2 a => D1 a
|
|
| 3279 | + |
|
| 3280 | + The primary concern is that we want to avoid looping on recursive instances.
|
|
| 3281 | + We can achieve this by simply not looking through loop breakers by using idUnfolding
|
|
| 3282 | + rather than realIdUnfolding.
|
|
| 3283 | + |
|
| 3284 | + It's possible that this prevents specialization of edge cases that have loop breakers
|
|
| 3285 | + in their recursive loop. But even if we can find a dictionary like this the simplifier
|
|
| 3286 | + won't look through loopbreaker dictionaries either killing any potential benefit.
|
|
| 3287 | + So while we could handle this case via a already-seen set or fuel we simply don't bother
|
|
| 3288 | + for now.
|
|
| 3289 | + |
|
| 3290 | +(ID7) A unary (single-method) class is currently handled by the same path as regular dicts
|
|
| 3291 | + since they are represented by faking a regular Dictionary.
|
|
| 3292 | + See Note [Unary class magic] for the details.
|
|
| 3276 | 3293 | |
| 3277 | 3294 | (ID8) Sadly, if `exprIsConApp_maybe` says Nothing, we still want to treat a
|
| 3278 | 3295 | non-trivial argument as interesting. In T19695 we have this:
|
| ... | ... | @@ -55,10 +55,9 @@ changes. Build results are placed into `_build` by default. |
| 55 | 55 | There are many different ways to build a compiler, each way is called a flavour.
|
| 56 | 56 | |
| 57 | 57 | * `--flavour=FLAVOUR`: choose a build flavour. The following settings are
|
| 58 | -currently supported: `default`, `quick`, `quickest`, `perf`, `prof`, `devel1`
|
|
| 59 | -and `devel2`. As an example, the `quickest` flavour adds `-O0` flag to all GHC
|
|
| 60 | -invocations and builds libraries only in the `vanilla` way, which speeds up
|
|
| 61 | -builds by 3-4x.
|
|
| 58 | +currently supported: `default`, `quick`, `perf`, `prof`, `devel1`
|
|
| 59 | +and `devel2`. As an example, the `quick` flavour builds the GHC binary with `-O0`
|
|
| 60 | +which speeds up builds and rebuilds significantly.
|
|
| 62 | 61 | |
| 63 | 62 | In addition to the overall build flavour there are also "flavour transformers"
|
| 64 | 63 | which can slightly modify the build settings for a flavour. Some common flavour
|
| ... | ... | @@ -16,7 +16,7 @@ After all the dependencies are in place: |
| 16 | 16 | - `git submodule update --init`
|
| 17 | 17 | - `./configure --target=arm-linux-gnueabihf`
|
| 18 | 18 | - `cd hadrian`
|
| 19 | -- Build the compiler by e.g. `./build.sh --flavour=quickest --integer-simple -V -j`
|
|
| 19 | +- Build the compiler by e.g. `./build.sh --flavour=quick --integer-simple -V -j`
|
|
| 20 | 20 | |
| 21 | 21 | After that, you should have built `inplace/bin/ghc-stage1` cross compiler. We will go to the next section to validate this.
|
| 22 | 22 |
| ... | ... | @@ -82,18 +82,6 @@ when compiling the `compiler` library, and `hsGhc` when compiling/linking the GH |
| 82 | 82 | <td>-O</td>
|
| 83 | 83 | <td>-debug (link)</td>
|
| 84 | 84 | </tr>
|
| 85 | - <tr>
|
|
| 86 | - <th>quickest</td>
|
|
| 87 | - <td></td>
|
|
| 88 | - <td>-O0<br>+RTS<br>-O64M<br>-RTS</td>
|
|
| 89 | - <td>-O0<br>+RTS<br>-O64M<br>-RTS</td>
|
|
| 90 | - <td></td>
|
|
| 91 | - <td></td>
|
|
| 92 | - <td>-O</td>
|
|
| 93 | - <td></td>
|
|
| 94 | - <td>-O</td>
|
|
| 95 | - <td></td>
|
|
| 96 | - </tr>
|
|
| 97 | 85 | <tr>
|
| 98 | 86 | <th>perf</td>
|
| 99 | 87 | <td> Yes (on supported platforms) </td>
|
| ... | ... | @@ -367,11 +355,4 @@ information. The following table lists ways that are built in different flavours |
| 367 | 355 | <td>debug<br>threaded<br>threadedDebug<br>debugDynamic<br>threadedDynamic<br>threadedDebugDynamic</td>
|
| 368 | 356 | <td>debug<br>threaded<br>threadedDebug<br>debugDynamic<br>threadedDynamic<br>threadedDebugDynamic</td>
|
| 369 | 357 | </tr>
|
| 370 | -<tr>
|
|
| 371 | - <th>quickest</th>
|
|
| 372 | - <td>vanilla</td>
|
|
| 373 | - <td>vanilla</td>
|
|
| 374 | - <td>vanilla<br>threaded</td>
|
|
| 375 | - <td>vanilla<br>threaded</td>
|
|
| 376 | -</tr>
|
|
| 377 | 358 | </table> |
| ... | ... | @@ -80,15 +80,15 @@ time you fire up a build. This is not possible with the Make build system. |
| 80 | 80 | build _build/stage1/lib/package.conf.d/text-1.2.3.0.conf # OR actual path
|
| 81 | 81 | ```
|
| 82 | 82 | |
| 83 | -- Building with a particular flavour (e.g `quickest`)
|
|
| 83 | +- Building with a particular flavour (e.g `quick`)
|
|
| 84 | 84 | |
| 85 | 85 | ``` sh
|
| 86 | 86 | # Make
|
| 87 | - echo "BuildFlavour=quickest" >> mk/build.mk
|
|
| 87 | + echo "BuildFlavour=quick" >> mk/build.mk
|
|
| 88 | 88 | make
|
| 89 | 89 | |
| 90 | 90 | # Hadrian
|
| 91 | - build --flavour=quickest
|
|
| 91 | + build --flavour=quick
|
|
| 92 | 92 | ```
|
| 93 | 93 | See [flavours documentation](https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/flavours.md) for info on flavours.
|
| 94 | 94 |
| ... | ... | @@ -20,7 +20,7 @@ stack exec -- pacman -S autoconf automake-wrapper make patch python tar --noconf |
| 20 | 20 | stack build
|
| 21 | 21 | |
| 22 | 22 | # Build GHC
|
| 23 | -stack exec hadrian -- --directory ".." -j --flavour=quickest
|
|
| 23 | +stack exec hadrian -- --directory ".." -j --flavour=quick
|
|
| 24 | 24 | |
| 25 | 25 | # Test GHC
|
| 26 | 26 | cd ..
|
| ... | ... | @@ -28,7 +28,7 @@ _build\stage1\bin\ghc -e 1+2 |
| 28 | 28 | ```
|
| 29 | 29 | |
| 30 | 30 | The entire process should take about 20 minutes. Note, this will build GHC
|
| 31 | -without optimisations. If you need an optimised GHC, drop the `--flavour=quickest`
|
|
| 31 | +without optimisations. If you need an optimised GHC, drop the `--flavour=quick`
|
|
| 32 | 32 | flag from the build command line (this will slow down the build to about an hour).
|
| 33 | 33 | |
| 34 | 34 | These are currently not the
|
| ... | ... | @@ -37,7 +37,7 @@ but are much simpler and may also be more robust. |
| 37 | 37 | |
| 38 | 38 | The `stack build` and `stack exec hadrian` commands can be replaced by an
|
| 39 | 39 | invocation of Hadrian's Stack-based build script:
|
| 40 | -`build-stack.bat -j --flavour=quickest`. Use this script if you plan to work on
|
|
| 40 | +`build-stack.bat -j --flavour=quick`. Use this script if you plan to work on
|
|
| 41 | 41 | Hadrian and/or rebuild GHC often.
|
| 42 | 42 | |
| 43 | 43 | ## Prerequisites
|
| ... | ... | @@ -125,7 +125,6 @@ executable hadrian |
| 125 | 125 | , Settings.Flavours.Performance
|
| 126 | 126 | , Settings.Flavours.Quick
|
| 127 | 127 | , Settings.Flavours.QuickCross
|
| 128 | - , Settings.Flavours.Quickest
|
|
| 129 | 128 | , Settings.Flavours.Validate
|
| 130 | 129 | , Settings.Flavours.Release
|
| 131 | 130 | , Settings.Packages
|
| ... | ... | @@ -281,7 +281,7 @@ optDescrs = |
| 281 | 281 | , Option ['o'] ["build-root"] (ReqArg readBuildRoot "BUILD_ROOT")
|
| 282 | 282 | "Where to store build artifacts. (Default _build)."
|
| 283 | 283 | , Option [] ["flavour"] (OptArg readFlavour "FLAVOUR")
|
| 284 | - "Build flavour (Default, Devel1, Devel2, Perf, Prof, Quick or Quickest)."
|
|
| 284 | + "Build flavour (Default, Devel1, Devel2, Perf, Prof or Quick)."
|
|
| 285 | 285 | , Option [] ["freeze1"] (NoArg readFreeze1)
|
| 286 | 286 | "Freeze Stage1 GHC."
|
| 287 | 287 | , Option [] ["freeze2"] (NoArg readFreeze2)
|
| ... | ... | @@ -531,7 +531,7 @@ It now also offers a more "old-school" interface, in the form of |
| 531 | 531 | @foo.bar.baz = v@ or @foo.bar.baz += v@ expressions, that one can
|
| 532 | 532 | pass on the command line that invokes hadrian:
|
| 533 | 533 | |
| 534 | -> $ hadrian/build --flavour=quickest -j "stage1.ghc-bin.ghc.link.opts += -v3"
|
|
| 534 | +> $ hadrian/build --flavour=quick -j "stage1.ghc-bin.ghc.link.opts += -v3"
|
|
| 535 | 535 | |
| 536 | 536 | or in a file at <build root>/hadrian.settings, where <build root>
|
| 537 | 537 | is the build root to be used for the build, which is _build by default.
|
| ... | ... | @@ -19,7 +19,6 @@ import Settings.Flavours.Development |
| 19 | 19 | import Settings.Flavours.GhcInGhci
|
| 20 | 20 | import Settings.Flavours.Performance
|
| 21 | 21 | import Settings.Flavours.Quick
|
| 22 | -import Settings.Flavours.Quickest
|
|
| 23 | 22 | import Settings.Flavours.QuickCross
|
| 24 | 23 | import Settings.Flavours.Validate
|
| 25 | 24 | import Settings.Flavours.Release
|
| ... | ... | @@ -55,7 +54,6 @@ hadrianFlavours = |
| 55 | 54 | , developmentFlavour Stage2, performanceFlavour
|
| 56 | 55 | , releaseFlavour
|
| 57 | 56 | , quickFlavour, quickValidateFlavour, quickDebugFlavour
|
| 58 | - , quickestFlavour
|
|
| 59 | 57 | , quickCrossFlavour
|
| 60 | 58 | , ghcInGhciFlavour, validateFlavour, slowValidateFlavour
|
| 61 | 59 | ]
|
| ... | ... | @@ -69,6 +67,10 @@ hadrianFlavours = |
| 69 | 67 | flavour :: Action Flavour
|
| 70 | 68 | flavour = do
|
| 71 | 69 | flavourName <- fromMaybe userDefaultFlavour <$> cmdFlavour
|
| 70 | + when ("quickest" `isPrefixOf` flavourName) $
|
|
| 71 | + fail $ "The `quickest` flavour has been deprecated. Use `quick` instead.\n"
|
|
| 72 | + ++ "Skip building dynamic libraries with `quick+no_dynamic_libs`\n"
|
|
| 73 | + ++ "to get closer to the old quickest behaviour."
|
|
| 72 | 74 | kvs <- userSetting ([] :: [KeyVal])
|
| 73 | 75 | let flavours = hadrianFlavours ++ userFlavours
|
| 74 | 76 | (settingErrs, tweak) = applySettings kvs
|
| 1 | -module Settings.Flavours.Quickest (quickestFlavour) where
|
|
| 2 | - |
|
| 3 | -import Expression
|
|
| 4 | -import Flavour
|
|
| 5 | -import {-# SOURCE #-} Settings.Default
|
|
| 6 | - |
|
| 7 | --- Please update doc/flavours.md when changing this file.
|
|
| 8 | -quickestFlavour :: Flavour
|
|
| 9 | -quickestFlavour = disableDynamicLibs $ disableProfiledLibs $ defaultFlavour
|
|
| 10 | - { name = "quickest"
|
|
| 11 | - , extraArgs = quickestArgs
|
|
| 12 | - }
|
|
| 13 | - |
|
| 14 | -quickestArgs :: Args
|
|
| 15 | -quickestArgs = sourceArgs SourceArgs
|
|
| 16 | - { hsDefault = mconcat $
|
|
| 17 | - [ pure ["-O0", "+RTS", "-O64M", "-RTS"]
|
|
| 18 | - ]
|
|
| 19 | - , hsLibrary = mempty
|
|
| 20 | - , hsCompiler = stage0 ? arg "-O"
|
|
| 21 | - , hsGhc = stage0 ? arg "-O" } |
| ... | ... | @@ -192,7 +192,6 @@ test ('T13386', |
| 192 | 192 | # Performance test for lookups in the family application cache
|
| 193 | 193 | test('FamAppCachePerf',
|
| 194 | 194 | [ only_ways(['normal'])
|
| 195 | - , collect_compiler_residency(20)
|
|
| 196 | 195 | , collect_compiler_stats('bytes allocated',2)
|
| 197 | 196 | ],
|
| 198 | 197 | compile,
|
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +import T27705_Inst
|
|
| 4 | + |
|
| 5 | +-- The dictionaries (D1/D2) are mutually recursive. We have to watch
|
|
| 6 | +-- out for the specializer looping on them. This was first detected in #22802
|
|
| 7 | +-- but no test was added, which caused it to break again #27705 :(
|
|
| 8 | +main :: IO ()
|
|
| 9 | +main = print (b (3 :: Int)) |
| 1 | +42 |
| 1 | +{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, FlexibleInstances #-}
|
|
| 2 | +module T27705_Inst where
|
|
| 3 | + |
|
| 4 | +-- The two dictionaries are mutually recursive, and we have to ensure the specialiser
|
|
| 5 | +-- doesn't loop when it's peaking through their unfoldings.
|
|
| 6 | +class D2 a => D1 a
|
|
| 7 | +class D1 a => D2 a
|
|
| 8 | +instance D2 Int => D1 Int
|
|
| 9 | +instance D1 Int => D2 Int
|
|
| 10 | + |
|
| 11 | +{-# NOINLINE b #-}
|
|
| 12 | +b :: D1 a => a -> Int
|
|
| 13 | +b _ = 42 |
| ... | ... | @@ -123,3 +123,5 @@ test('T24359b', normal, compile_and_run, ['-O']) |
| 123 | 123 | test('T23429', normal, compile_and_run, ['-O'])
|
| 124 | 124 | test('T27071', normal, compile_and_run, ['-O -fworker-wrapper-cbv'])
|
| 125 | 125 | test('T27005', [], multimod_compile_and_run, ['T27005', '-O'])
|
| 126 | +test('T27705', [extra_hc_opts('+RTS -M500M -RTS')], multimod_compile_and_run,
|
|
| 127 | + ['T27705', '-O2 -fexpose-all-unfoldings']) |
| ... | ... | @@ -199,7 +199,7 @@ tgtSupportsSMP Target{..} = do |
| 199 | 199 | -- 5. The testsuite driver will use dyn way for TH/ghci tests even
|
| 200 | 200 | -- when host GHC is static.
|
| 201 | 201 | -- 6. TH/ghci doesn't work if stage1 is built without shared libraries
|
| 202 | --- (e.g. quickest/fully_static).
|
|
| 202 | +-- (e.g. no_dynamic_libs/fully_static).
|
|
| 203 | 203 | tgtRTSLinkerOnlySupportsSharedLibs :: Target -> Bool
|
| 204 | 204 | tgtRTSLinkerOnlySupportsSharedLibs Target{tgtArchOs} =
|
| 205 | 205 | archOS_arch tgtArchOs `elem`
|