summaryrefslogtreecommitdiff
path: root/compiler/simplStg
diff options
context:
space:
mode:
authorÖmer Sinan Ağacan <omeragacan@gmail.com>2018-02-18 11:12:53 -0500
committerBen Gamari <ben@smart-cactus.org>2018-02-18 11:57:46 -0500
commit7f389a580f42a105623853adad15ab3323b41ed5 (patch)
treece072fb7732bd1626ed9ed214e60d2bdd5dee848 /compiler/simplStg
parentfc33f8b31b9c23cc12f02a028bbaeab06ba8fe96 (diff)
downloadhaskell-7f389a580f42a105623853adad15ab3323b41ed5.tar.gz
StgLint overhaul
- Remove all type checks - Check two STG invariants (no unboxed let bindings, variables defined before used) and post-unarisation invariants. See the module header and #14787. This version validates with `-dstg-lint` added to `GhcStage2HcOpts` and `GhcLibHcOpts` and `EXTRA_HC_OPTS`. Unarise changes: - `unariseConArgBinder` and `unariseFunArgBinder` functions were almost the same; only difference was when unarising fun args we keep void args while in con args we drop them. A new function `unariseArgBinder` added with a `Bool` argument for whether we're unarising a con arg. `unariseConArgBinder` and `unariseFunArgBinder` are now defined as unariseConArgBinder = unarsieArgBinder True -- data con unariseFunArgBinder = unariseArgBinder False -- not data con - A bug in `unariseConArgBinder` and `unariseFunArgBinder` (which are just calls to `unariseArgBinder` now) that invalidated the post-unarise invariants when the argument has single type rep (i.e. `length (typePrimRep x) == 1`) fixed. This isn't a correctness issue (it's fine not to unarise if a variable is already represented as single value), but it triggers StgLint. Test Plan: - Pass testsuite with `-dstg-lint` [done] - Boot stage2 (including libraries) with `-dstg-lint` [done] Reviewers: simonpj, bgamari Reviewed By: bgamari Subscribers: duog, rwbarton, thomie, carter GHC Trac Issues: #14787 Differential Revision: https://phabricator.haskell.org/D4404
Diffstat (limited to 'compiler/simplStg')
-rw-r--r--compiler/simplStg/SimplStg.hs12
-rw-r--r--compiler/simplStg/UnariseStg.hs60
2 files changed, 48 insertions, 24 deletions
diff --git a/compiler/simplStg/SimplStg.hs b/compiler/simplStg/SimplStg.hs
index 6bdc1c9573..854bb92258 100644
--- a/compiler/simplStg/SimplStg.hs
+++ b/compiler/simplStg/SimplStg.hs
@@ -46,8 +46,9 @@ stg2stg dflags binds
; dumpIfSet_dyn dflags Opt_D_dump_stg "Pre unarise:"
(pprStgTopBindings processed_binds)
- ; let un_binds = stg_linter True "Unarise"
- $ unarise us processed_binds
+ ; let un_binds = unarise us processed_binds
+
+ ; stg_linter True "Unarise" un_binds
; dumpIfSet_dyn dflags Opt_D_dump_stg "STG syntax:"
(pprStgTopBindings un_binds)
@@ -57,8 +58,8 @@ stg2stg dflags binds
where
stg_linter unarised
- | gopt Opt_DoStgLinting dflags = lintStgTopBindings unarised
- | otherwise = \ _whodunnit binds -> binds
+ | gopt Opt_DoStgLinting dflags = lintStgTopBindings dflags unarised
+ | otherwise = \ _whodunnit _binds -> return ()
-------------------------------------------
do_stg_pass binds to_do
@@ -78,7 +79,8 @@ stg2stg dflags binds
= do -- report verbosely, if required
dumpIfSet_dyn dflags Opt_D_verbose_stg2stg what
(vcat (map ppr binds2))
- return (stg_linter False what binds2)
+ stg_linter False what binds2
+ return binds2
-- -----------------------------------------------------------------------------
-- StgToDo: abstraction of stg-to-stg passes to run.
diff --git a/compiler/simplStg/UnariseStg.hs b/compiler/simplStg/UnariseStg.hs
index 6fb8d0ea2d..57dd699f70 100644
--- a/compiler/simplStg/UnariseStg.hs
+++ b/compiler/simplStg/UnariseStg.hs
@@ -203,7 +203,7 @@ import CoreSyn
import DataCon
import FastString (FastString, mkFastString)
import Id
-import Literal (Literal (..))
+import Literal (Literal (..), literalType)
import MkCore (aBSENT_ERROR_ID)
import MkId (voidPrimId, voidArgId)
import MonadUtils (mapAccumLM)
@@ -334,7 +334,7 @@ unariseExpr _ e@StgLam{}
= pprPanic "unariseExpr: found lambda" (ppr e)
unariseExpr rho (StgCase scrut bndr alt_ty alts)
- -- a tuple/sum binders in the scrutinee can always be eliminated
+ -- tuple/sum binders in the scrutinee can always be eliminated
| StgApp v [] <- scrut
, Just (MultiVal xs) <- lookupVarEnv rho v
= elimCase rho xs bndr alt_ty alts
@@ -351,7 +351,8 @@ unariseExpr rho (StgCase scrut bndr alt_ty alts)
= do scrut' <- unariseExpr rho scrut
alts' <- unariseAlts rho alt_ty bndr alts
return (StgCase scrut' bndr alt_ty alts')
- -- bndr will be dead after unarise
+ -- bndr may have a unboxed sum/tuple type but it will be
+ -- dead after unarise (checked in StgLint)
unariseExpr rho (StgLet bind e)
= StgLet <$> unariseBinding rho bind <*> unariseExpr rho e
@@ -642,6 +643,35 @@ So in short, when we have a void id,
in argument position of a DataCon application.
-}
+unariseArgBinder
+ :: Bool -- data con arg?
+ -> UnariseEnv -> Id -> UniqSM (UnariseEnv, [Id])
+unariseArgBinder is_con_arg rho x =
+ case typePrimRep (idType x) of
+ []
+ | is_con_arg
+ -> return (extendRho rho x (MultiVal []), [])
+ | otherwise -- fun arg, do not remove void binders
+ -> return (extendRho rho x (MultiVal []), [voidArgId])
+
+ [rep]
+ -- Arg represented as single variable, but original type may still be an
+ -- unboxed sum/tuple, e.g. (# Void# | Void# #).
+ --
+ -- While not unarising the binder in this case does not break any programs
+ -- (because it unarises to a single variable), it triggers StgLint as we
+ -- break the the post-unarisation invariant that says unboxed tuple/sum
+ -- binders should vanish. See Note [Post-unarisation invariants].
+ | isUnboxedSumType (idType x) || isUnboxedTupleType (idType x)
+ -> do x' <- mkId (mkFastString "us") (primRepToType rep)
+ return (extendRho rho x (MultiVal [StgVarArg x']), [x'])
+ | otherwise
+ -> return (rho, [x])
+
+ reps -> do
+ xs <- mkIds (mkFastString "us") (map primRepToType reps)
+ return (extendRho rho x (MultiVal (map StgVarArg xs)), xs)
+
--------------------------------------------------------------------------------
-- | MultiVal a function argument. Never returns an empty list.
@@ -660,16 +690,9 @@ unariseFunArgs = concatMap . unariseFunArg
unariseFunArgBinders :: UnariseEnv -> [Id] -> UniqSM (UnariseEnv, [Id])
unariseFunArgBinders rho xs = second concat <$> mapAccumLM unariseFunArgBinder rho xs
-unariseFunArgBinder :: UnariseEnv -> Id -> UniqSM (UnariseEnv, [Id])
-- Result list of binders is never empty
-unariseFunArgBinder rho x =
- case typePrimRep (idType x) of
- [] -> return (extendRho rho x (MultiVal []), [voidArgId])
- -- NB: do not remove void binders
- [_] -> return (rho, [x])
- reps -> do
- xs <- mkIds (mkFastString "us") (map primRepToType reps)
- return (extendRho rho x (MultiVal (map StgVarArg xs)), xs)
+unariseFunArgBinder :: UnariseEnv -> Id -> UniqSM (UnariseEnv, [Id])
+unariseFunArgBinder = unariseArgBinder False
--------------------------------------------------------------------------------
@@ -684,7 +707,9 @@ unariseConArg rho (StgVarArg x) =
-- Here realWorld# is not in the envt, but
-- is a void, and so should be eliminated
| otherwise -> [StgVarArg x]
-unariseConArg _ arg = [arg] -- We have no void literals
+unariseConArg _ arg@(StgLitArg lit) =
+ ASSERT(not (isVoidTy (literalType lit))) -- We have no void literals
+ [arg]
unariseConArgs :: UnariseEnv -> [InStgArg] -> [OutStgArg]
unariseConArgs = concatMap . unariseConArg
@@ -692,13 +717,10 @@ unariseConArgs = concatMap . unariseConArg
unariseConArgBinders :: UnariseEnv -> [Id] -> UniqSM (UnariseEnv, [Id])
unariseConArgBinders rho xs = second concat <$> mapAccumLM unariseConArgBinder rho xs
+-- Different from `unariseFunArgBinder`: result list of binders may be empty.
+-- See DataCon applications case in Note [Post-unarisation invariants].
unariseConArgBinder :: UnariseEnv -> Id -> UniqSM (UnariseEnv, [Id])
-unariseConArgBinder rho x =
- case typePrimRep (idType x) of
- [_] -> return (rho, [x])
- reps -> do
- xs <- mkIds (mkFastString "us") (map primRepToType reps)
- return (extendRho rho x (MultiVal (map StgVarArg xs)), xs)
+unariseConArgBinder = unariseArgBinder True
unariseFreeVars :: UnariseEnv -> [InId] -> [OutId]
unariseFreeVars rho fvs