diff options
author | Ömer Sinan Ağacan <omeragacan@gmail.com> | 2016-08-10 16:47:47 +0000 |
---|---|---|
committer | Ömer Sinan Ağacan <omeragacan@gmail.com> | 2016-08-10 16:48:17 +0000 |
commit | 9684dbb1d776a8e086f8db4191b3bcf826867dda (patch) | |
tree | 9ecdca8cca16090aeb5cccf135f84c6120f7a805 /compiler/simplStg | |
parent | e79bb2c10d66ec8f0c037e66c7d0a22aa887fdc1 (diff) | |
download | haskell-9684dbb1d776a8e086f8db4191b3bcf826867dda.tar.gz |
Remove StgRubbishArg and CmmArg
The idea behind adding special "rubbish" arguments was in unboxed sum types
depending on the tag some arguments are not used and we don't want to move some
special values (like 0 for literals and some special pointer for boxed slots)
for those arguments (to stack locations or registers). "StgRubbishArg" was an
indicator to the code generator that the value won't be used. During Stg-to-Cmm
we were then not generating any move or store instructions at all.
This caused problems in the register allocator because some variables were only
initialized in some code paths. As an example, suppose we have this STG: (after
unarise)
Lib.$WT =
\r [dt_sit]
case
case dt_sit of {
Lib.F dt_siv [Occ=Once] ->
(#,,#) [1# dt_siv StgRubbishArg::GHC.Prim.Int#];
Lib.I dt_siw [Occ=Once] ->
(#,,#) [2# StgRubbishArg::GHC.Types.Any dt_siw];
}
of
dt_six
{ (#,,#) us_giC us_giD us_giE -> Lib.T [us_giC us_giD us_giE];
};
This basically unpacks a sum type to an unboxed sum with 3 fields, and then
moves the unboxed sum to a constructor (`Lib.T`).
This is the Cmm for the inner case expression (case expression in the scrutinee
position of the outer case):
ciN:
...
-- look at dt_sit's tag
if (_ciT::P64 != 1) goto ciS; else goto ciR;
ciS: -- Tag is 2, i.e. Lib.F
_siw::I64 = I64[_siu::P64 + 6];
_giE::I64 = _siw::I64;
_giD::P64 = stg_RUBBISH_ENTRY_info;
_giC::I64 = 2;
goto ciU;
ciR: -- Tag is 1, i.e. Lib.I
_siv::P64 = P64[_siu::P64 + 7];
_giD::P64 = _siv::P64;
_giC::I64 = 1;
goto ciU;
Here one of the blocks `ciS` and `ciR` is executed and then the execution
continues to `ciR`, but only `ciS` initializes `_giE`, in the other branch
`_giE` is not initialized, because it's "rubbish" in the STG and so we don't
generate an assignment during code generator. The code generator then panics
during the register allocations:
ghc-stage1: panic! (the 'impossible' happened)
(GHC version 8.1.20160722 for x86_64-unknown-linux):
LocalReg's live-in to graph ciY {_giE::I64}
(`_giD` is also "rubbish" in `ciS`, but it's still initialized because it's a
pointer slot, we have to initialize it otherwise garbage collector follows the
pointer to some random place. So we only remove assignment if the "rubbish" arg
has unboxed type.)
This patch removes `StgRubbishArg` and `CmmArg`. We now always initialize
rubbish slots. If the slot is for boxed types we use the existing `absentError`,
otherwise we initialize the slot with literal 0.
Reviewers: simonpj, erikd, austin, simonmar, bgamari
Reviewed By: erikd
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2446
Diffstat (limited to 'compiler/simplStg')
-rw-r--r-- | compiler/simplStg/UnariseStg.hs | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/compiler/simplStg/UnariseStg.hs b/compiler/simplStg/UnariseStg.hs index 24c0ce84a8..80848793fc 100644 --- a/compiler/simplStg/UnariseStg.hs +++ b/compiler/simplStg/UnariseStg.hs @@ -188,6 +188,7 @@ import DataCon import FastString (FastString, mkFastString) import Id import Literal (Literal (..)) +import MkCore (aBSENT_ERROR_ID) import MkId (voidPrimId, voidArgId) import MonadUtils (mapAccumLM) import Outputable @@ -288,8 +289,6 @@ unariseExpr rho e@(StgApp f []) -> return (StgApp f' []) Just (UnaryVal (StgLitArg f')) -> return (StgLit f') - Just (UnaryVal arg@(StgRubbishArg {})) - -> pprPanic "unariseExpr - app1" (ppr e $$ ppr arg) Nothing -> return e @@ -389,7 +388,6 @@ elimCase rho args bndr (MultiValAlt _) alts scrut' = case tag_arg of StgVarArg v -> StgApp v [] StgLitArg l -> StgLit l - StgRubbishArg _ -> pprPanic "unariseExpr" (ppr args) alts' <- unariseSumAlts rho1 real_args alts return (StgCase scrut' tag_bndr tagAltTy alts') @@ -561,7 +559,14 @@ mkUbxSum dc ty_args args0 | Just stg_arg <- IM.lookup arg_idx arg_map = stg_arg : mkTupArgs (arg_idx + 1) slots_left arg_map | otherwise - = StgRubbishArg (slotTyToType slot) : mkTupArgs (arg_idx + 1) slots_left arg_map + = slotRubbishArg slot : mkTupArgs (arg_idx + 1) slots_left arg_map + + slotRubbishArg :: SlotTy -> StgArg + slotRubbishArg PtrSlot = StgVarArg aBSENT_ERROR_ID + slotRubbishArg WordSlot = StgLitArg (MachWord 0) + slotRubbishArg Word64Slot = StgLitArg (MachWord64 0) + slotRubbishArg FloatSlot = StgLitArg (MachFloat 0) + slotRubbishArg DoubleSlot = StgLitArg (MachDouble 0) in tag_arg : mkTupArgs 0 sum_slots arg_idxs @@ -659,7 +664,7 @@ unariseConArg :: UnariseEnv -> InStgArg -> [OutStgArg] unariseConArg rho (StgVarArg x) = case lookupVarEnv rho x of Just (UnaryVal arg) -> [arg] - Just (MultiVal as) -> as -- 'as' can be empty + Just (MultiVal as) -> as -- 'as' can be empty Nothing | isVoidTy (idType x) -> [] -- e.g. C realWorld# -- Here realWorld# is not in the envt, but |