module UHC.Light.Compiler.Core.Trf
( TrfCore (..), emptyTrfCore
, TrfCoreExtra (..), emptyTrfCoreExtra
, trfCore )
where
import qualified Data.Map as Map
import qualified Data.Set as Set
import Control.Monad
import Control.Monad.State
import UHC.Light.Compiler.Base.Target
import UHC.Light.Compiler.Base.Optimize
import UHC.Light.Compiler.EHC.Common
import UHC.Light.Compiler.CodeGen.ValAccess as VA
import UHC.Light.Compiler.LamInfo
import UHC.Light.Compiler.Core
import UHC.Light.Compiler.Core.Check
import UHC.Light.Compiler.Core.Trf.RenUniq
import UHC.Light.Compiler.Core.Trf.ANormal
import UHC.Light.Compiler.Core.Trf.InlineLetAlias
import UHC.Light.Compiler.Core.Trf.LetUnrec
import UHC.Light.Compiler.Core.Trf.LetDefBeforeUse
import UHC.Light.Compiler.Core.Trf.LamGlobalAsArg
import UHC.Light.Compiler.Core.Trf.CAFGlobalAsArg
import UHC.Light.Compiler.Core.Trf.FloatToGlobal
import UHC.Light.Compiler.Core.Trf.ConstProp
import UHC.Light.Compiler.Core.Trf.EtaRed
import UHC.Light.Compiler.Core.Trf.ElimTrivApp
import UHC.Light.Compiler.Core.Trf.AnnBasedSimplify
import UHC.Light.Compiler.Core.Trf.AnaRelevance
import UHC.Light.Compiler.Core.Trf.LetFlattenStrict
import UHC.Light.Compiler.Core.Trf.OptimizeStrictness
import UHC.Light.Compiler.Core.Trf.EraseExtractTysigCore
import UHC.Light.Compiler.Core.Trf.FixAfterParse
import UHC.Light.Compiler.CodeGen.TrfUtils
import UHC.Light.Compiler.Core.Trf.ExplicitStackTrace
type TrfCore = TrfState CModule TrfCoreExtra
emptyTrfCore :: TrfCore
emptyTrfCore = mkEmptyTrfState emptyCModule emptyTrfCoreExtra
data TrfCoreExtra
= TrfCoreExtra
{ trfcoreInhLamMp :: LamMp
, trfcoreGathLamMp :: !LamMp
, trfcoreExpNmOffMp :: !HsName2FldMp
, trfcoreExtraExports :: !FvS
, trfcoreECUState :: !EHCompileUnitState
, trfcoreNotYetTransformed:: !NotYetTransformedS
}
emptyTrfCoreExtra :: TrfCoreExtra
emptyTrfCoreExtra = TrfCoreExtra
Map.empty Map.empty
Map.empty
Set.empty
ECUS_Unknown
(Set.fromList [minBound .. maxBound])
trfCore :: EHCOpts -> OptimizationScope -> DataGam -> HsName -> TrfCore -> TrfCore
trfCore opts optimScope dataGam modNm trfcore
= runTrf opts modNm ehcOptDumpCoreStages (optimScope `elem`) trfcore trf
where isFromCoreSrc = ecuStateIsCore $ trfcoreECUState $ trfstExtra trfcore
notYetTransformed = trfcoreNotYetTransformed $ trfstExtra trfcore
isNotLamLifted = NotYetTransformed_LambdaLifted `Set.member` notYetTransformed
isNotANormal = NotYetTransformed_ANormal `Set.member` notYetTransformed
isLamLifted = not isNotLamLifted
isANormal = not isNotANormal
noOptims = ehcOptOptimizationLevel opts <= OptimizationLevel_Off
isCoreTarget = targetIsCore $ ehcOptTarget opts
isUnOptimCoreTarget = isCoreTarget && noOptims
trf
= do {
t_initial
; when isFromCoreSrc $ do
{
t_fix_postparse
}
; unless isFromCoreSrc $ do
{ unless noOptims $ do
{
t_ann_simpl
}
; t_eta_red
; unless (ehcOptCoreSysF opts)
t_erase_ty
}
; unless isLamLifted $ do
{
; unless isUnOptimCoreTarget $
t_ren_uniq emptyRenUniqOpts
; t_let_unrec
}
; when isFromCoreSrc $ do
{
t_let_defbefuse
}
; t_let_flatstr
; unless noOptims $ do
{
; t_inl_letali
; t_elim_trivapp
}
; when (ehcOptTargetFlavor opts == TargetFlavor_Debug)
(do { t_expl_trace
; t_let_unrec
})
; unless noOptims $ do
{
; t_const_prop
; t_inl_letali
; t_elim_trivapp
}
; when (isUnOptimCoreTarget || isNotLamLifted || isNotANormal) $ do
{
; u1 <- freshInfUID
; t_anormal u1
}
; when (isNotLamLifted && not isUnOptimCoreTarget) $ do
{
; t_lam_asarg
; t_caf_asarg
; t_let_unrec
; u2 <- freshInfUID
; t_anormal u2
; t_float_glob
}
; when (ehcOptOptimizes Optimize_StrictnessAnalysis opts)
(do { t_let_defbefuse
; t_ana_relev
; t_opt_strict
})
; when (ehcOptIsViaCoreJavaScript opts)
(do { t_ren_uniq (emptyRenUniqOpts {renuniqOptResetOnlyInLam = True})
})
; when (not isCoreTarget) $ do
{
t_let_defbefuse' osmw
}
}
lamMpPropagate l s@(TrfState {trfstExtra=e@(TrfCoreExtra{trfcoreGathLamMp=gl, trfcoreInhLamMp=il})})
= s {trfstExtra = e {trfcoreGathLamMp = gl', trfcoreInhLamMp = Map.union gl' il}}
where gl' = Map.union l gl
t_initial = liftTrfModPlain osmw "initial" $ id
t_fix_postparse = liftTrfModPlain osm "fix-postparse" $ cmodTrfFixAfterParse dataGam
t_eta_red = liftTrfModPlain osm "eta-red" $ cmodTrfEtaRed
t_erase_ty = liftTrfModWithStateExtra osmw "erase-ty" lamMpPropagate
$ \_ -> cmodTrfEraseExtractTysigCore opts
t_ann_simpl = liftTrfModPlain osm "ann-simpl" $ cmodTrfAnnBasedSimplify opts
t_ren_uniq o = liftTrfModPlain osm "ren-uniq" $ cmodTrfRenUniq o
t_let_unrec = liftTrfModPlain osm "let-unrec" $ cmodTrfLetUnrec
t_let_defbefuse' os
= liftTrfModPlain os "let-defbefuse" $ cmodTrfLetDefBeforeUse
t_let_defbefuse = t_let_defbefuse' osm
t_let_flatstr = liftTrfModPlain osm "let-flatstr" $ cmodTrfLetFlattenStrict
t_inl_letali = liftTrfModPlain osm "inl-letali" $ cmodTrfInlineLetAlias
(Map.keysSet $ trfcoreExpNmOffMp $ trfstExtra trfcore)
t_elim_trivapp = liftTrfModPlain osm "elim-trivapp" $ cmodTrfElimTrivApp opts
t_const_prop = liftTrfModPlain osm "const-prop" $ cmodTrfConstProp opts
t_anormal u = liftTrfModPlain osm "anormal" $ cmodTrfANormal modNm u
t_lam_asarg = liftTrfModPlain osm "lam-asarg" $ cmodTrfLamGlobalAsArg
t_caf_asarg = liftTrfModPlain osm "caf-asarg" $ cmodTrfCAFGlobalAsArg
t_float_glob = liftTrfModPlain osm "float-glob" $ cmodTrfFloatToGlobal
t_ana_relev = liftTrfModWithStateExtra osm "ana-relev" lamMpPropagate
$ \s -> cmodTrfAnaRelevance opts dataGam (trfcoreInhLamMp $ trfstExtra s)
t_opt_strict = liftTrfModWithStateExtra osm "optim-strict" lamMpPropagate
$ \s -> cmodTrfOptimizeStrictness opts (trfcoreInhLamMp $ trfstExtra s)
t_expl_trace = liftTrfModWithStateExtra osm "expl-sttrace"
(\m s@(TrfState {trfstExtra=e@(TrfCoreExtra {trfcoreExtraExports=exps})})
-> (lamMpPropagate m s)
{ trfstExtra =
e { trfcoreExtraExports = exps `Set.union`
Set.fromList [ n
| (n,LamInfo {laminfoStackTrace=(StackTraceInfo_IsStackTraceEquiv _)}) <- Map.toList m
]
} }
) $ \s -> cmodTrfExplicitStackTrace opts (trfcoreInhLamMp $ trfstExtra s)
osm = [OptimizationScope_PerModule]
osmw =
[OptimizationScope_WholeCore] ++
osm