summaryrefslogtreecommitdiff
path: root/compiler/coreSyn/CoreUtils.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/coreSyn/CoreUtils.hs')
-rw-r--r--compiler/coreSyn/CoreUtils.hs125
1 files changed, 1 insertions, 124 deletions
diff --git a/compiler/coreSyn/CoreUtils.hs b/compiler/coreSyn/CoreUtils.hs
index 679360f3de..e073078766 100644
--- a/compiler/coreSyn/CoreUtils.hs
+++ b/compiler/coreSyn/CoreUtils.hs
@@ -28,7 +28,7 @@ module CoreUtils (
exprIsCheap, exprIsExpandable, exprIsCheapX, CheapAppFun,
exprIsHNF, exprOkForSpeculation, exprOkForSideEffects, exprIsWorkFree,
exprIsBig, exprIsConLike,
- rhsIsStatic, isCheapApp, isExpandableApp,
+ isCheapApp, isExpandableApp,
exprIsTickedString, exprIsTickedString_maybe,
exprIsTopLevelBindable,
altsAreExhaustive,
@@ -89,7 +89,6 @@ import FastString
import Maybes
import ListSetOps ( minusList )
import BasicTypes ( Arity, isConLike )
-import GHC.Platform
import Util
import Pair
import Data.ByteString ( ByteString )
@@ -2494,128 +2493,6 @@ If this happens we simply make the RHS into an updatable thunk,
and 'execute' it rather than allocating it statically.
-}
--- | This function is called only on *top-level* right-hand sides.
--- Returns @True@ if the RHS can be allocated statically in the output,
--- with no thunks involved at all.
-rhsIsStatic
- :: Platform
- -> (Name -> Bool) -- Which names are dynamic
- -> (LitNumType -> Integer -> Maybe CoreExpr)
- -- Desugaring for some literals (disgusting)
- -- C.f. Note [Disgusting computation of CafRefs] in GHC.Iface.Tidy
- -> CoreExpr -> Bool
--- It's called (i) in GHC.Iface.Tidy.hasCafRefs to decide if the rhs is, or
--- refers to, CAFs; (ii) in CoreToStg to decide whether to put an
--- update flag on it and (iii) in DsExpr to decide how to expand
--- list literals
---
--- The basic idea is that rhsIsStatic returns True only if the RHS is
--- (a) a value lambda
--- (b) a saturated constructor application with static args
---
--- BUT watch out for
--- (i) Any cross-DLL references kill static-ness completely
--- because they must be 'executed' not statically allocated
--- ("DLL" here really only refers to Windows DLLs, on other platforms,
--- this is not necessary)
---
--- (ii) We treat partial applications as redexes, because in fact we
--- make a thunk for them that runs and builds a PAP
--- at run-time. The only applications that are treated as
--- static are *saturated* applications of constructors.
-
--- We used to try to be clever with nested structures like this:
--- ys = (:) w ((:) w [])
--- on the grounds that CorePrep will flatten ANF-ise it later.
--- But supporting this special case made the function much more
--- complicated, because the special case only applies if there are no
--- enclosing type lambdas:
--- ys = /\ a -> Foo (Baz ([] a))
--- Here the nested (Baz []) won't float out to top level in CorePrep.
---
--- But in fact, even without -O, nested structures at top level are
--- flattened by the simplifier, so we don't need to be super-clever here.
---
--- Examples
---
--- f = \x::Int. x+7 TRUE
--- p = (True,False) TRUE
---
--- d = (fst p, False) FALSE because there's a redex inside
--- (this particular one doesn't happen but...)
---
--- h = D# (1.0## /## 2.0##) FALSE (redex again)
--- n = /\a. Nil a TRUE
---
--- t = /\a. (:) (case w a of ...) (Nil a) FALSE (redex)
---
---
--- This is a bit like CoreUtils.exprIsHNF, with the following differences:
--- a) scc "foo" (\x -> ...) is updatable (so we catch the right SCC)
---
--- b) (C x xs), where C is a constructor is updatable if the application is
--- dynamic
---
--- c) don't look through unfolding of f in (f x).
-
-rhsIsStatic platform is_dynamic_name cvt_literal rhs = is_static False rhs
- where
- is_static :: Bool -- True <=> in a constructor argument; must be atomic
- -> CoreExpr -> Bool
-
- is_static False (Lam b e) = isRuntimeVar b || is_static False e
- is_static in_arg (Tick n e) = not (tickishIsCode n)
- && is_static in_arg e
- is_static in_arg (Cast e _) = is_static in_arg e
- is_static _ (Coercion {}) = True -- Behaves just like a literal
- is_static in_arg (Lit (LitNumber nt i _)) = case cvt_literal nt i of
- Just e -> is_static in_arg e
- Nothing -> True
- is_static _ (Lit (LitLabel {})) = False
- is_static _ (Lit _) = True
- -- A LitLabel (foreign import "&foo") in an argument
- -- prevents a constructor application from being static. The
- -- reason is that it might give rise to unresolvable symbols
- -- in the object file: under Linux, references to "weak"
- -- symbols from the data segment give rise to "unresolvable
- -- relocation" errors at link time This might be due to a bug
- -- in the linker, but we'll work around it here anyway.
- -- SDM 24/2/2004
-
- is_static in_arg other_expr = go other_expr 0
- where
- go (Var f) n_val_args
- | (platformOS platform /= OSMinGW32) ||
- not (is_dynamic_name (idName f))
- = saturated_data_con f n_val_args
- || (in_arg && n_val_args == 0)
- -- A naked un-applied variable is *not* deemed a static RHS
- -- E.g. f = g
- -- Reason: better to update so that the indirection gets shorted
- -- out, and the true value will be seen
- -- NB: if you change this, you'll break the invariant that THUNK_STATICs
- -- are always updatable. If you do so, make sure that non-updatable
- -- ones have enough space for their static link field!
-
- go (App f a) n_val_args
- | isTypeArg a = go f n_val_args
- | not in_arg && is_static True a = go f (n_val_args + 1)
- -- The (not in_arg) checks that we aren't in a constructor argument;
- -- if we are, we don't allow (value) applications of any sort
- --
- -- NB. In case you wonder, args are sometimes not atomic. eg.
- -- x = D# (1.0## /## 2.0##)
- -- can't float because /## can fail.
-
- go (Tick n f) n_val_args = not (tickishIsCode n) && go f n_val_args
- go (Cast e _) n_val_args = go e n_val_args
- go _ _ = False
-
- saturated_data_con f n_val_args
- = case isDataConWorkId_maybe f of
- Just dc -> n_val_args == dataConRepArity dc
- Nothing -> False
-
{-
************************************************************************
* *