The issue here is what happens when we have
(f |> co) x
where f is itself marked INLINE. We want callSiteInline to "see"
the fact that the function is applied, and hence have some incentive
to inline. I've done this by extending CoreUnfold.CallCtxt with
ValAppCtxt. I think that should catch this case without messing up
any of the others.
-- => be keener to inline
-- INVARIANT: ArgCtxt False 0 ==> BoringCtxt
-- => be keener to inline
-- INVARIANT: ArgCtxt False 0 ==> BoringCtxt
+ | ValAppCtxt -- We're applied to at least one value arg
+ -- This arises when we have ((f x |> co) y)
+ -- Then the (f x) has argument 'x' but in a ValAppCtxt
+
| CaseCtxt -- We're the scrutinee of a case
-- that decomposes its scrutinee
| CaseCtxt -- We're the scrutinee of a case
-- that decomposes its scrutinee
ppr BoringCtxt = ptext (sLit "BoringCtxt")
ppr (ArgCtxt _ _) = ptext (sLit "ArgCtxt")
ppr CaseCtxt = ptext (sLit "CaseCtxt")
ppr BoringCtxt = ptext (sLit "BoringCtxt")
ppr (ArgCtxt _ _) = ptext (sLit "ArgCtxt")
ppr CaseCtxt = ptext (sLit "CaseCtxt")
+ ppr ValAppCtxt = ptext (sLit "ValAppCtxt")
callSiteInline dflags active_inline id lone_variable arg_infos cont_info
= case idUnfolding id of {
callSiteInline dflags active_inline id lone_variable arg_infos cont_info
= case idUnfolding id of {
= case cont_info of
BoringCtxt -> not is_top && n_vals_wanted > 0 -- Note [Nested functions]
CaseCtxt -> not lone_variable || not is_value -- Note [Lone variables]
= case cont_info of
BoringCtxt -> not is_top && n_vals_wanted > 0 -- Note [Nested functions]
CaseCtxt -> not lone_variable || not is_value -- Note [Lone variables]
- ArgCtxt {} -> n_vals_wanted > 0
- -- See Note [Inlining in ArgCtxt]
+ ArgCtxt {} -> n_vals_wanted > 0 -- Note [Inlining in ArgCtxt]
+ ValAppCtxt -> True -- Note [Cast then apply]
small_enough = (size - discount) <= opt_UF_UseThreshold
discount = computeDiscount n_vals_wanted arg_discounts
small_enough = (size - discount) <= opt_UF_UseThreshold
discount = computeDiscount n_vals_wanted arg_discounts
res_discount' = case cont_info of
BoringCtxt -> 0
CaseCtxt -> res_discount
res_discount' = case cont_info of
BoringCtxt -> 0
CaseCtxt -> res_discount
- ArgCtxt _ _ -> 4 `min` res_discount
+ _other -> 4 `min` res_discount
-- res_discount can be very large when a function returns
-- construtors; but we only want to invoke that large discount
-- when there's a case continuation.
-- res_discount can be very large when a function returns
-- construtors; but we only want to invoke that large discount
-- when there's a case continuation.
increase the chance that the constructor won't be allocated at all in
the branches that don't use it.
increase the chance that the constructor won't be allocated at all in
the branches that don't use it.
+Note [Cast then apply]
+~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ myIndex = __inline_me ( (/\a. <blah>) |> co )
+ co :: (forall a. a -> a) ~ (forall a. T a)
+ ... /\a.\x. case ((myIndex a) |> sym co) x of { ... } ...
+
+We need to inline myIndex to unravel this; but the actual call (myIndex a) has
+no value arguments. The ValAppCtxt gives it enough incentive to inline.
+
Note [Inlining in ArgCtxt]
~~~~~~~~~~~~~~~~~~~~~~~~~~
The condition (n_vals_wanted > 0) here is very important, because otherwise
Note [Inlining in ArgCtxt]
~~~~~~~~~~~~~~~~~~~~~~~~~~
The condition (n_vals_wanted > 0) here is very important, because otherwise
interestingCallContext cont
= interesting cont
where
interestingCallContext cont
= interesting cont
where
- interestingCtxt = ArgCtxt False 2 -- Give *some* incentive!
-
interesting (Select _ bndr _ _ _)
interesting (Select _ bndr _ _ _)
- | isDeadBinder bndr = CaseCtxt
- | otherwise = interestingCtxt
+ | isDeadBinder bndr = CaseCtxt
+ | otherwise = ArgCtxt False 2 -- If the binder is used, this
+ -- is like a strict let
- interesting (ApplyTo {}) = interestingCtxt
- -- Can happen if we have (coerce t (f x)) y
- -- Perhaps interestingCtxt is a bit over-keen, but I've
- -- seen (coerce f) x, where f has an INLINE prag,
- -- So we have to give some motivation for inlining it
+ interesting (ApplyTo _ arg _ cont)
+ | isTypeArg arg = interesting cont
+ | otherwise = ValAppCtxt -- Can happen if we have (f Int |> co) y
+ -- If f has an INLINE prag we need to give it some
+ -- motivation to inline. See Note [Cast then apply]
+ -- in CoreUnfold
interesting (StrictArg _ cci _ _) = cci
interesting (StrictBind {}) = BoringCtxt
interesting (StrictArg _ cci _ _) = cci
interesting (StrictBind {}) = BoringCtxt