| ... |
... |
@@ -2265,19 +2265,6 @@ Some programs have a /lot/ of data constructors in the source program |
|
2265
|
2265
|
valuable.
|
|
2266
|
2266
|
-}
|
|
2267
|
2267
|
|
|
2268
|
|
-simplInVar :: SimplEnv -> InVar -> SimplM OutExpr
|
|
2269
|
|
--- Look up an InVar in the environment
|
|
2270
|
|
-simplInVar env var
|
|
2271
|
|
- -- Why $! ? See Note [Bangs in the Simplifier]
|
|
2272
|
|
- | isTyVar var = return $! Type $! (substTyVar env var)
|
|
2273
|
|
- | isCoVar var = return $! Coercion $! (substCoVar env var)
|
|
2274
|
|
- | otherwise
|
|
2275
|
|
- = case substId env var of
|
|
2276
|
|
- ContEx tvs cvs ids e -> let env' = setSubstEnv env tvs cvs ids
|
|
2277
|
|
- in simplExpr env' e
|
|
2278
|
|
- DoneId var1 -> return (Var var1)
|
|
2279
|
|
- DoneEx e _ -> return e
|
|
2280
|
|
-
|
|
2281
|
2268
|
simplInId :: SimplEnv -> InId -> SimplCont -> SimplM (SimplFloats, OutExpr)
|
|
2282
|
2269
|
simplInId env var cont
|
|
2283
|
2270
|
| Just dc <- isDataConWorkId_maybe var
|
| ... |
... |
@@ -2644,7 +2631,7 @@ See Note [No free join points in arityType] in GHC.Core.Opt.Arity |
|
2644
|
2631
|
|
|
2645
|
2632
|
tryRules :: Bool -- True <=> args are already simplified
|
|
2646
|
2633
|
-> SimplEnv -> [CoreRule]
|
|
2647
|
|
- -> OutId -> [CoreExpr]
|
|
|
2634
|
+ -> OutId -> [OutExpr]
|
|
2648
|
2635
|
-> SimplM (Maybe (FullArgCount, CoreExpr))
|
|
2649
|
2636
|
|
|
2650
|
2637
|
tryRules args_are_simplified env rules fn args
|
| ... |
... |
@@ -3070,25 +3057,6 @@ may be a result of 'seq' so we *definitely* don't want to drop those. |
|
3070
|
3057
|
I don't really know how to improve this situation.
|
|
3071
|
3058
|
|
|
3072
|
3059
|
|
|
3073
|
|
-Note [FloatBinds from constructor wrappers]
|
|
3074
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
3075
|
|
-If we have FloatBinds coming from the constructor wrapper
|
|
3076
|
|
-(as in Note [exprIsConApp_maybe on data constructors with wrappers]),
|
|
3077
|
|
-we cannot float past them. We'd need to float the FloatBind
|
|
3078
|
|
-together with the simplify floats, unfortunately the
|
|
3079
|
|
-simplifier doesn't have case-floats. The simplest thing we can
|
|
3080
|
|
-do is to wrap all the floats here. The next iteration of the
|
|
3081
|
|
-simplifier will take care of all these cases and lets.
|
|
3082
|
|
-
|
|
3083
|
|
-Given data T = MkT !Bool, this allows us to simplify
|
|
3084
|
|
-case $WMkT b of { MkT x -> f x }
|
|
3085
|
|
-to
|
|
3086
|
|
-case b of { b' -> f b' }.
|
|
3087
|
|
-
|
|
3088
|
|
-We could try and be more clever (like maybe wfloats only contain
|
|
3089
|
|
-let binders, so we could float them). But the need for the
|
|
3090
|
|
-extra complication is not clear.
|
|
3091
|
|
-
|
|
3092
|
3060
|
Note [Do not duplicate constructor applications]
|
|
3093
|
3061
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
3094
|
3062
|
Consider this (#20125)
|
| ... |
... |
@@ -3133,7 +3101,7 @@ rebuildCase env scrut case_bndr alts cont |
|
3133
|
3101
|
= do { tick (KnownBranch case_bndr)
|
|
3134
|
3102
|
; case findAlt (LitAlt lit) alts of
|
|
3135
|
3103
|
Nothing -> missingAlt env case_bndr alts cont
|
|
3136
|
|
- Just (Alt _ bs rhs) -> simple_rhs env [] scrut bs rhs }
|
|
|
3104
|
+ Just (Alt _ bs rhs) -> simple_rhs env scrut bs rhs }
|
|
3137
|
3105
|
|
|
3138
|
3106
|
| Just (in_scope', wfloats, con, ty_args, other_args)
|
|
3139
|
3107
|
<- exprIsConApp_maybe (getUnfoldingInRuleMatch env) scrut
|
| ... |
... |
@@ -3141,58 +3109,26 @@ rebuildCase env scrut case_bndr alts cont |
|
3141
|
3109
|
-- as well as when it's an explicit constructor application
|
|
3142
|
3110
|
, let env0 = setInScopeSet env in_scope'
|
|
3143
|
3111
|
= do { tick (KnownBranch case_bndr)
|
|
3144
|
|
- ; let scaled_wfloats = map scale_float wfloats
|
|
3145
|
|
- -- case_bndr_unf: see Note [Do not duplicate constructor applications]
|
|
|
3112
|
+ ; let -- case_bndr_unf: see Note [Do not duplicate constructor applications]
|
|
3146
|
3113
|
case_bndr_rhs | exprIsTrivial scrut = scrut
|
|
3147
|
3114
|
| otherwise = con_app
|
|
3148
|
3115
|
con_app = Var (dataConWorkId con) `mkTyApps` ty_args
|
|
3149
|
3116
|
`mkApps` other_args
|
|
3150
|
|
- ; case findAlt (DataAlt con) alts of
|
|
|
3117
|
+ ; wrapDataConFloats env wfloats case_bndr cont $
|
|
|
3118
|
+ case findAlt (DataAlt con) alts of
|
|
3151
|
3119
|
Nothing -> missingAlt env0 case_bndr alts cont
|
|
3152
|
|
- Just (Alt DEFAULT bs rhs) -> simple_rhs env0 scaled_wfloats case_bndr_rhs bs rhs
|
|
3153
|
|
- Just (Alt _ bs rhs) -> knownCon env0 scrut scaled_wfloats con ty_args
|
|
|
3120
|
+ Just (Alt DEFAULT bs rhs) -> simple_rhs env0 case_bndr_rhs bs rhs
|
|
|
3121
|
+ Just (Alt _ bs rhs) -> knownCon env0 scrut con
|
|
3154
|
3122
|
other_args case_bndr bs rhs cont
|
|
3155
|
3123
|
}
|
|
3156
|
3124
|
where
|
|
3157
|
|
- simple_rhs env wfloats case_bndr_rhs bs rhs =
|
|
|
3125
|
+ simple_rhs env case_bndr_rhs bs rhs =
|
|
3158
|
3126
|
assert (null bs) $
|
|
3159
|
3127
|
do { (floats1, env') <- simplAuxBind "rebuildCase" env case_bndr case_bndr_rhs
|
|
3160
|
3128
|
-- scrut is a constructor application,
|
|
3161
|
3129
|
-- hence satisfies let-can-float invariant
|
|
3162
|
3130
|
; (floats2, expr') <- simplExprF env' rhs cont
|
|
3163
|
|
- ; case wfloats of
|
|
3164
|
|
- [] -> return (floats1 `addFloats` floats2, expr')
|
|
3165
|
|
- _ -> return
|
|
3166
|
|
- -- See Note [FloatBinds from constructor wrappers]
|
|
3167
|
|
- ( emptyFloats env,
|
|
3168
|
|
- GHC.Core.Make.wrapFloats wfloats $
|
|
3169
|
|
- wrapFloats (floats1 `addFloats` floats2) expr' )}
|
|
3170
|
|
-
|
|
3171
|
|
- -- This scales case floats by the multiplicity of the continuation hole (see
|
|
3172
|
|
- -- Note [Scaling in case-of-case]). Let floats are _not_ scaled, because
|
|
3173
|
|
- -- they are aliases anyway.
|
|
3174
|
|
- scale_float (GHC.Core.Make.FloatCase scrut case_bndr con vars) =
|
|
3175
|
|
- let
|
|
3176
|
|
- scale_id id = scaleVarBy holeScaling id
|
|
3177
|
|
- in
|
|
3178
|
|
- GHC.Core.Make.FloatCase scrut (scale_id case_bndr) con (map scale_id vars)
|
|
3179
|
|
- scale_float f = f
|
|
3180
|
|
-
|
|
3181
|
|
- holeScaling = contHoleScaling cont `mkMultMul` idMult case_bndr
|
|
3182
|
|
- -- We are in the following situation
|
|
3183
|
|
- -- case[p] case[q] u of { D x -> C v } of { C x -> w }
|
|
3184
|
|
- -- And we are producing case[??] u of { D x -> w[x\v]}
|
|
3185
|
|
- --
|
|
3186
|
|
- -- What should the multiplicity `??` be? In order to preserve the usage of
|
|
3187
|
|
- -- variables in `u`, it needs to be `pq`.
|
|
3188
|
|
- --
|
|
3189
|
|
- -- As an illustration, consider the following
|
|
3190
|
|
- -- case[Many] case[1] of { C x -> C x } of { C x -> (x, x) }
|
|
3191
|
|
- -- Where C :: A %1 -> T is linear
|
|
3192
|
|
- -- If we were to produce a case[1], like the inner case, we would get
|
|
3193
|
|
- -- case[1] of { C x -> (x, x) }
|
|
3194
|
|
- -- Which is ill-typed with respect to linearity. So it needs to be a
|
|
3195
|
|
- -- case[Many].
|
|
|
3131
|
+ ; return (floats1 `addFloats` floats2, expr') }
|
|
3196
|
3132
|
|
|
3197
|
3133
|
--------------------------------------------------
|
|
3198
|
3134
|
-- 2. Eliminate the case if scrutinee is evaluated
|
| ... |
... |
@@ -3740,29 +3676,81 @@ and then |
|
3740
|
3676
|
f (h v)
|
|
3741
|
3677
|
|
|
3742
|
3678
|
All this should happen in one sweep.
|
|
|
3679
|
+
|
|
|
3680
|
+Note [FloatBinds from constructor wrappers]
|
|
|
3681
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
3682
|
+If we have FloatBinds coming from the constructor wrapper
|
|
|
3683
|
+(as in Note [exprIsConApp_maybe on data constructors with wrappers]),
|
|
|
3684
|
+we cannot float past them. We'd need to float the FloatBind
|
|
|
3685
|
+together with the simplify floats, unfortunately the
|
|
|
3686
|
+simplifier doesn't have case-floats. The simplest thing we can
|
|
|
3687
|
+do is to wrap all the floats here. The next iteration of the
|
|
|
3688
|
+simplifier will take care of all these cases and lets.
|
|
|
3689
|
+
|
|
|
3690
|
+Given data T = MkT !Bool, this allows us to simplify
|
|
|
3691
|
+case $WMkT b of { MkT x -> f x }
|
|
|
3692
|
+to
|
|
|
3693
|
+case b of { b' -> f b' }.
|
|
|
3694
|
+
|
|
|
3695
|
+We could try and be more clever (like maybe wfloats only contain
|
|
|
3696
|
+let binders, so we could float them). But the need for the
|
|
|
3697
|
+extra complication is not clear.
|
|
3743
|
3698
|
-}
|
|
3744
|
3699
|
|
|
|
3700
|
+wrapDataConFloats :: SimplEnv -> [FloatBind] -> InId -> SimplCont
|
|
|
3701
|
+ -> SimplM (SimplFloats, OutExpr)
|
|
|
3702
|
+ -> SimplM (SimplFloats, OutExpr)
|
|
|
3703
|
+-- See Note [FloatBinds from constructor wrappers]
|
|
|
3704
|
+wrapDataConFloats env wfloats case_bndr cont thing_inside
|
|
|
3705
|
+ | null wfloats
|
|
|
3706
|
+ = thing_inside
|
|
|
3707
|
+ | otherwise
|
|
|
3708
|
+ = do { (floats, expr) <- thing_inside
|
|
|
3709
|
+ ; return ( emptyFloats env
|
|
|
3710
|
+ , GHC.Core.Make.wrapFloats (map scale_float wfloats) $
|
|
|
3711
|
+ wrapFloats floats expr ) }
|
|
|
3712
|
+ where
|
|
|
3713
|
+ -- scale_float scales case-floats by the multiplicity of the continuation hole
|
|
|
3714
|
+ -- (see Note [Scaling in case-of-case]).
|
|
|
3715
|
+ -- Let floats are _not_ scaled, because they are aliases anyway.
|
|
|
3716
|
+ scale_float (GHC.Core.Make.FloatCase scrut case_bndr con vars)
|
|
|
3717
|
+ = GHC.Core.Make.FloatCase scrut (scale_id case_bndr) con (map scale_id vars)
|
|
|
3718
|
+ scale_float flt@(GHC.Core.Make.FloatLet {})
|
|
|
3719
|
+ = flt
|
|
|
3720
|
+
|
|
|
3721
|
+ scale_id id = scaleVarBy holeScaling id
|
|
|
3722
|
+
|
|
|
3723
|
+ holeScaling = contHoleScaling cont `mkMultMul` idMult case_bndr
|
|
|
3724
|
+ -- We are in the following situation
|
|
|
3725
|
+ -- case[p] case[q] u of { D x -> C v } of { C x -> w }
|
|
|
3726
|
+ -- And we are producing case[??] u of { D x -> w[x\v]}
|
|
|
3727
|
+ --
|
|
|
3728
|
+ -- What should the multiplicity `??` be? In order to preserve the usage of
|
|
|
3729
|
+ -- variables in `u`, it needs to be `pq`.
|
|
|
3730
|
+ --
|
|
|
3731
|
+ -- As an illustration, consider the following
|
|
|
3732
|
+ -- case[Many] case[1] of { C x -> C x } of { C x -> (x, x) }
|
|
|
3733
|
+ -- Where C :: A %1 -> T is linear
|
|
|
3734
|
+ -- If we were to produce a case[1], like the inner case, we would get
|
|
|
3735
|
+ -- case[1] of { C x -> (x, x) }
|
|
|
3736
|
+ -- Which is ill-typed with respect to linearity. So it needs to be a
|
|
|
3737
|
+ -- case[Many].
|
|
|
3738
|
+
|
|
|
3739
|
+
|
|
3745
|
3740
|
knownCon :: SimplEnv
|
|
3746
|
|
- -> OutExpr -- The scrutinee
|
|
3747
|
|
- -> [FloatBind] -> DataCon -> [OutType] -> [OutExpr] -- The scrutinee (in pieces)
|
|
3748
|
|
- -> InId -> [InBndr] -> InExpr -- The alternative
|
|
|
3741
|
+ -> OutExpr -- The scrutinee
|
|
|
3742
|
+ -> DataCon -> [OutExpr] -- The scrutinee (in pieces)
|
|
|
3743
|
+ -> InId -> [InBndr] -> InExpr -- The alternative
|
|
3749
|
3744
|
-> SimplCont
|
|
3750
|
3745
|
-> SimplM (SimplFloats, OutExpr)
|
|
3751
|
3746
|
|
|
3752
|
|
-knownCon env scrut dc_floats dc dc_ty_args dc_args bndr bs rhs cont
|
|
3753
|
|
- = do { (floats1, env1) <- bind_args env bs dc_args
|
|
|
3747
|
+knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
|
|
|
3748
|
+ = do { (floats1, env1) <- bind_args env alt_bndrs dc_args
|
|
3754
|
3749
|
; (floats2, env2) <- bind_case_bndr env1
|
|
3755
|
3750
|
; (floats3, expr') <- simplExprF env2 rhs cont
|
|
3756
|
|
- ; case dc_floats of
|
|
3757
|
|
- [] ->
|
|
3758
|
|
- return (floats1 `addFloats` floats2 `addFloats` floats3, expr')
|
|
3759
|
|
- _ ->
|
|
3760
|
|
- return ( emptyFloats env
|
|
3761
|
|
- -- See Note [FloatBinds from constructor wrappers]
|
|
3762
|
|
- , GHC.Core.Make.wrapFloats dc_floats $
|
|
3763
|
|
- wrapFloats (floats1 `addFloats` floats2 `addFloats` floats3) expr') }
|
|
|
3751
|
+ ; return (floats1 `addFloats` floats2 `addFloats` floats3, expr') }
|
|
3764
|
3752
|
where
|
|
3765
|
|
- zap_occ = zapBndrOccInfo (isDeadBinder bndr) -- bndr is an InId
|
|
|
3753
|
+ zap_occ = zapBndrOccInfo (isDeadBinder case_bndr) -- case_bndr is an InId
|
|
3766
|
3754
|
|
|
3767
|
3755
|
-- Ugh!
|
|
3768
|
3756
|
bind_args env' [] _ = return (emptyFloats env', env')
|
| ... |
... |
@@ -3787,28 +3775,32 @@ knownCon env scrut dc_floats dc dc_ty_args dc_args bndr bs rhs cont |
|
3787
|
3775
|
; return (floats1 `addFloats` floats2, env3) }
|
|
3788
|
3776
|
|
|
3789
|
3777
|
bind_args _ _ _ =
|
|
3790
|
|
- pprPanic "bind_args" $ ppr dc $$ ppr bs $$ ppr dc_args $$
|
|
|
3778
|
+ pprPanic "bind_args" $ ppr dc $$ ppr alt_bndrs $$ ppr dc_args $$
|
|
3791
|
3779
|
text "scrut:" <+> ppr scrut
|
|
3792
|
3780
|
|
|
3793
|
|
- -- It's useful to bind bndr to scrut, rather than to a fresh
|
|
|
3781
|
+ -- It's useful to bind case_bndr to scrut, rather than to a fresh
|
|
3794
|
3782
|
-- binding x = Con arg1 .. argn
|
|
3795
|
3783
|
-- because very often the scrut is a variable, so we avoid
|
|
3796
|
3784
|
-- creating, and then subsequently eliminating, a let-binding
|
|
3797
|
3785
|
-- BUT, if scrut is a not a variable, we must be careful
|
|
3798
|
3786
|
-- about duplicating the arg redexes; in that case, make
|
|
3799
|
3787
|
-- a new con-app from the args
|
|
|
3788
|
+ con_app :: InExpr
|
|
|
3789
|
+ con_app = mkConApp2 dc (tyConAppArgs (idType case_bndr)) alt_bndrs
|
|
|
3790
|
+
|
|
3800
|
3791
|
bind_case_bndr env
|
|
3801
|
|
- | isDeadBinder bndr = return (emptyFloats env, env)
|
|
3802
|
|
- | exprIsTrivial scrut = return (emptyFloats env
|
|
3803
|
|
- , extendIdSubst env bndr (DoneEx scrut NotJoinPoint))
|
|
3804
|
|
- -- See Note [Do not duplicate constructor applications]
|
|
3805
|
|
- | otherwise = do { dc_args <- mapM (simplInVar env) bs
|
|
3806
|
|
- -- dc_ty_args are already OutTypes,
|
|
3807
|
|
- -- but bs are InBndrs
|
|
3808
|
|
- ; let con_app = Var (dataConWorkId dc)
|
|
3809
|
|
- `mkTyApps` dc_ty_args
|
|
3810
|
|
- `mkApps` dc_args
|
|
3811
|
|
- ; simplAuxBind "case-bndr" env bndr con_app }
|
|
|
3792
|
+ | exprIsTrivial scrut
|
|
|
3793
|
+ = -- See Note [Do not duplicate constructor applications]
|
|
|
3794
|
+ return ( emptyFloats env
|
|
|
3795
|
+ , extendIdSubst env case_bndr (DoneEx scrut NotJoinPoint))
|
|
|
3796
|
+
|
|
|
3797
|
+ | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr con_app env
|
|
|
3798
|
+ = return (emptyFloats env', env')
|
|
|
3799
|
+
|
|
|
3800
|
+ | otherwise
|
|
|
3801
|
+ = do { (env1, case_bndr1) <- simplNonRecBndr env case_bndr
|
|
|
3802
|
+ ; simplLazyBind NotTopLevel NonRecursive
|
|
|
3803
|
+ (case_bndr,env) (case_bndr1,env1) (con_app,env) }
|
|
3812
|
3804
|
|
|
3813
|
3805
|
-------------------
|
|
3814
|
3806
|
missingAlt :: SimplEnv -> Id -> [InAlt] -> SimplCont
|