Magnus pushed to branch wip/mangoiv/9.12.5-rc4 at Glasgow Haskell Compiler / GHC
Commits:
-
3508dbe9
by mangoiv at 2026-09-17T16:49:35+02:00
4 changed files:
- + Repro019_minimal.hs
- compiler/GHC/Core/Opt/Specialise.hs
- + testsuite/tests/simplCore/should_compile/T27766.hs
- testsuite/tests/simplCore/should_compile/all.T
Changes:
| 1 | +module Repro019_minimal where
|
|
| 2 | + |
|
| 3 | +unpack :: Int -> [Int]
|
|
| 4 | +unpack b = unpackGo b
|
|
| 5 | +{-# NOINLINE unpack #-}
|
|
| 6 | + |
|
| 7 | +unpackGo :: Int -> [Int]
|
|
| 8 | +unpackGo len = go len
|
|
| 9 | + where go i = if i == 0 then [] else i : go (i - 1)
|
|
| 10 | +{-# INLINE unpackGo #-}
|
|
| 11 | + |
|
| 12 | +{-# RULES "unpack/late" [0] forall b. unpack b = unpackGo b #-}
|
|
| 13 | + |
|
| 14 | +conv :: [Int] -> Int
|
|
| 15 | +conv input = case unpack (length input) of
|
|
| 16 | + [] -> undefined
|
|
| 17 | + _ -> 0
|
|
| 18 | + |
|
| 19 | +opaque :: Int -> Bool
|
|
| 20 | +opaque x = x > 0
|
|
| 21 | +{-# NOINLINE opaque #-}
|
|
| 22 | + |
|
| 23 | +getUnchecked :: Int -> IO (Int, Maybe Int)
|
|
| 24 | +getUnchecked x = get x >>= maybe undefined pure
|
|
| 25 | + |
|
| 26 | +get :: Int -> IO (Maybe (Int, Maybe Int))
|
|
| 27 | +get x = do
|
|
| 28 | + a <- ((if opaque x then pure Nothing else pure (Just 0)) >>= \r -> case r of
|
|
| 29 | + Just _ -> pure (Just (1 :: Int))
|
|
| 30 | + _ -> pure Nothing)
|
|
| 31 | + b <- (if opaque x then pure Nothing else pure (Just 0))
|
|
| 32 | + pure ((,) <$> a <*> Just (fmap (conv . unpack) b))
|
|
| 33 | +{-# INLINE get #-}
|
|
| 34 | + |
|
| 35 | +top :: IO ()
|
|
| 36 | +top = () <$ getUnchecked (undefined :: Int)
|
|
| 37 | + |
| ... | ... | @@ -1211,14 +1211,21 @@ specExpr env (Tick tickish body) |
| 1211 | 1211 | ---------------- Applications might generate a call instance --------------------
|
| 1212 | 1212 | specExpr env expr@(App {})
|
| 1213 | 1213 | = do { let (fun_in, args_in) = collectArgs expr
|
| 1214 | + ; (fun_out, uds_fun) <- specExpr env fun_in
|
|
| 1214 | 1215 | ; (args_out, uds_args) <- mapAndCombineSM (specExpr env) args_in
|
| 1215 | - ; let env_args = env `bringFloatedDictsIntoScope` ud_binds uds_args
|
|
| 1216 | - -- Some dicts may have floated out of args_in;
|
|
| 1217 | - -- they should be in scope for fireRewriteRules (#21689)
|
|
| 1218 | - (fun_in', args_out') = fireRewriteRules env_args fun_in args_out
|
|
| 1219 | - ; (fun_out', uds_fun) <- specExpr env fun_in'
|
|
| 1216 | + ; let uds_app = uds_fun `thenUDs` uds_args
|
|
| 1217 | + env_args = zapSubst env `bringFloatedDictsIntoScope` ud_binds uds_app
|
|
| 1218 | + -- zapSubst: we have now fully applied the substitution
|
|
| 1219 | + -- bringFloatedDictsIntoScope: some dicts may have floated out of
|
|
| 1220 | + -- args_in; they should be in scope for fireRewriteRules (#21689)
|
|
| 1221 | + |
|
| 1222 | + -- Try firing rewrite rules
|
|
| 1223 | + -- See Note [Fire rules in the specialiser]
|
|
| 1224 | + ; let (fun_out', args_out') = fireRewriteRules env_args fun_out args_out
|
|
| 1225 | + |
|
| 1226 | + -- Make a call record, and return
|
|
| 1220 | 1227 | ; let uds_call = mkCallUDs env fun_out' args_out'
|
| 1221 | - ; return (fun_out' `mkApps` args_out', uds_fun `thenUDs` uds_call `thenUDs` uds_args) }
|
|
| 1228 | + ; return (fun_out' `mkApps` args_out', uds_app `thenUDs` uds_call) }
|
|
| 1222 | 1229 | |
| 1223 | 1230 | ---------------- Lambda/case require dumping of usage details --------------------
|
| 1224 | 1231 | specExpr env e@(Lam {})
|
| ... | ... | @@ -1252,16 +1259,17 @@ specExpr env (Let bind body) |
| 1252 | 1259 | -- See Note [Specialisation modulo dictionary selectors]
|
| 1253 | 1260 | -- Note [ClassOp/DFun selection]
|
| 1254 | 1261 | -- Note [Fire rules in the specialiser]
|
| 1255 | -fireRewriteRules :: SpecEnv -> InExpr -> [OutExpr] -> (InExpr, [OutExpr])
|
|
| 1262 | +fireRewriteRules :: SpecEnv -- Substitution is already zapped
|
|
| 1263 | + -> OutExpr -> [OutExpr] -> (OutExpr, [OutExpr])
|
|
| 1256 | 1264 | fireRewriteRules env (Var f) args
|
| 1257 | 1265 | | Just (rule, expr) <- specLookupRule env f args InitialPhase (getRules (se_rules env) f)
|
| 1258 | 1266 | , let rest_args = drop (ruleArity rule) args -- See Note [Extra args in the target]
|
| 1259 | - zapped_subst = Core.zapSubst (se_subst env)
|
|
| 1260 | - expr' = simpleOptExprWith defaultSimpleOpts zapped_subst expr
|
|
| 1267 | + zapped_subst = se_subst env -- Just needed for the InScopeSet
|
|
| 1268 | + expr' = simpleOptExprWith defaultSimpleOpts zapped_subst (mkApps expr rest_args)
|
|
| 1261 | 1269 | -- simplOptExpr needed because lookupRule returns
|
| 1262 | 1270 | -- (\x y. rhs) arg1 arg2
|
| 1263 | - , (fun, args) <- collectArgs expr'
|
|
| 1264 | - = fireRewriteRules env fun (args++rest_args)
|
|
| 1271 | + , (fun', args') <- collectArgs expr'
|
|
| 1272 | + = fireRewriteRules env fun' args'
|
|
| 1265 | 1273 | fireRewriteRules _ fun args = (fun, args)
|
| 1266 | 1274 | |
| 1267 | 1275 | --------------
|
| ... | ... | @@ -1736,6 +1744,12 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1736 | 1744 | do { -- Run the specialiser on the specialised RHS
|
| 1737 | 1745 | -- The "1" suffix is before we maybe add the void arg
|
| 1738 | 1746 | ; (rhs_body', rhs_uds) <- specExpr rhs_env2 rhs_body
|
| 1747 | + |
|
| 1748 | +{- ; pprTrace "spec_call2" (vcat
|
|
| 1749 | + [ text "fun:" <+> ppr fn
|
|
| 1750 | + , text "rhs_body':" <+> ppr rhs_body' ]) $
|
|
| 1751 | + return ()
|
|
| 1752 | +-}
|
|
| 1739 | 1753 | -- Add the { d1' = dx1; d2' = dx2 } usage stuff
|
| 1740 | 1754 | -- to the rhs_uds; see Note [Specialising Calls]
|
| 1741 | 1755 | ; let rhs_uds_w_dx = dx_binds `consDictBinds` rhs_uds
|
| 1 | +module Repro019_minimal where
|
|
| 2 | + |
|
| 3 | +unpack :: Int -> [Int]
|
|
| 4 | +unpack b = unpackGo b
|
|
| 5 | +{-# NOINLINE unpack #-}
|
|
| 6 | + |
|
| 7 | +unpackGo :: Int -> [Int]
|
|
| 8 | +unpackGo len = go len
|
|
| 9 | + where go i = if i == 0 then [] else i : go (i - 1)
|
|
| 10 | +{-# INLINE unpackGo #-}
|
|
| 11 | + |
|
| 12 | +{-# RULES "unpack/late" [0] forall b. unpack b = unpackGo b #-}
|
|
| 13 | + |
|
| 14 | +conv :: [Int] -> Int
|
|
| 15 | +conv input = case unpack (length input) of
|
|
| 16 | + [] -> undefined
|
|
| 17 | + _ -> 0
|
|
| 18 | + |
|
| 19 | +opaque :: Int -> Bool
|
|
| 20 | +opaque x = x > 0
|
|
| 21 | +{-# NOINLINE opaque #-}
|
|
| 22 | + |
|
| 23 | +getUnchecked :: Int -> IO (Int, Maybe Int)
|
|
| 24 | +getUnchecked x = get x >>= maybe undefined pure
|
|
| 25 | + |
|
| 26 | +get :: Int -> IO (Maybe (Int, Maybe Int))
|
|
| 27 | +get x = do
|
|
| 28 | + a <- ((if opaque x then pure Nothing else pure (Just 0)) >>= \r -> case r of
|
|
| 29 | + Just _ -> pure (Just (1 :: Int))
|
|
| 30 | + _ -> pure Nothing)
|
|
| 31 | + b <- (if opaque x then pure Nothing else pure (Just 0))
|
|
| 32 | + pure ((,) <$> a <*> Just (fmap (conv . unpack) b))
|
|
| 33 | +{-# INLINE get #-}
|
|
| 34 | + |
|
| 35 | +top :: IO ()
|
|
| 36 | +top = () <$ getUnchecked (undefined :: Int)
|
|
| 37 | + |
| ... | ... | @@ -542,3 +542,4 @@ test('T26681', normal, compile, ['-O']) |
| 542 | 542 | test('T26903', [grep_errmsg(r'reverse')], compile, ['-O -dno-typeable-binds -ddump-simpl -dsuppress-uniques -dsuppress-all'])
|
| 543 | 543 | test('T26682', normal, multimod_compile, ['T26682', '-O -v0'])
|
| 544 | 544 | test('T27261', [extra_files(['T27261_aux.hs'])], multimod_compile, ['T27261', '-v0 -O'])
|
| 545 | +test('T27766', normal, compile, ['-O2 -flate-specialise']) |