Create a deterministic version of tyVarsOfType
authorBartosz Nitka <niteria@gmail.com>
Sat, 21 Nov 2015 14:57:09 +0000 (15:57 +0100)
committerBen Gamari <ben@smart-cactus.org>
Sat, 21 Nov 2015 16:15:09 +0000 (11:15 -0500)
I've run into situations where I need deterministic `tyVarsOfType` and
this implementation achieves that and also brings an algorithmic
improvement.  Union of two `VarSet`s takes linear time the size of the
sets and in the worst case we can have `n` unions of sets of sizes
`(n-1, 1), (n-2, 1)...` making it quadratic.

One reason why we need deterministic `tyVarsOfType` is in `abstractVars`
in `SetLevels`. When we abstract type variables when floating we want
them to be abstracted in deterministic order.

Test Plan: harbormaster

Reviewers: simonpj, goldfire, austin, hvr, simonmar, bgamari

Reviewed By: simonmar

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D1468

GHC Trac Issues: #4012

27 files changed:
compiler/basicTypes/IdInfo.hs
compiler/coreSyn/CoreFVs.hs
compiler/coreSyn/CoreSeq.hs
compiler/coreSyn/CoreSubst.hs
compiler/deSugar/DsCCall.hs
compiler/deSugar/DsExpr.hs
compiler/ghc.cabal.in
compiler/ghc.mk
compiler/ghci/ByteCodeGen.hs
compiler/ghci/ByteCodeInstr.hs
compiler/ghci/RtClosureInspect.hs
compiler/simplCore/FloatIn.hs
compiler/simplCore/SetLevels.hs
compiler/specialise/Rules.hs
compiler/typecheck/TcDeriv.hs
compiler/typecheck/TcErrors.hs
compiler/typecheck/TcHsType.hs
compiler/typecheck/TcType.hs
compiler/types/Coercion.hs
compiler/types/TypeRep.hs
compiler/types/Unify.hs
compiler/utils/FV.hs [new file with mode: 0644]
compiler/vectorise/Vectorise/Exp.hs
testsuite/tests/partial-sigs/should_compile/T10403.stderr
testsuite/tests/partial-sigs/should_fail/Trac10045.stderr
testsuite/tests/perf/should_run/T10359 [new file with mode: 0755]
testsuite/tests/polykinds/T9222.stderr

index 2dafafc..6f00df5 100644 (file)
@@ -376,21 +376,21 @@ and put in the global list.
 data RuleInfo
   = RuleInfo
         [CoreRule]
-        VarSet          -- Locally-defined free vars of *both* LHS and RHS
+        DVarSet         -- Locally-defined free vars of *both* LHS and RHS
                         -- of rules.  I don't think it needs to include the
                         -- ru_fn though.
                         -- Note [Rule dependency info] in OccurAnal
 
 -- | Assume that no specilizations exist: always safe
 emptyRuleInfo :: RuleInfo
-emptyRuleInfo = RuleInfo [] emptyVarSet
+emptyRuleInfo = RuleInfo [] emptyDVarSet
 
 isEmptyRuleInfo :: RuleInfo -> Bool
 isEmptyRuleInfo (RuleInfo rs _) = null rs
 
 -- | Retrieve the locally-defined free variables of both the left and
 -- right hand sides of the specialization rules
-ruleInfoFreeVars :: RuleInfo -> VarSet
+ruleInfoFreeVars :: RuleInfo -> DVarSet
 ruleInfoFreeVars (RuleInfo _ fvs) = fvs
 
 ruleInfoRules :: RuleInfo -> [CoreRule]
index 0e50277..39a1599 100644 (file)
@@ -11,6 +11,7 @@ Taken quite directly from the Peyton Jones/Lester paper.
 module CoreFVs (
         -- * Free variables of expressions and binding groups
         exprFreeVars,   -- CoreExpr   -> VarSet -- Find all locally-defined free Ids or tyvars
+        exprFreeDVars,  -- CoreExpr   -> DVarSet -- Find all locally-defined free Ids or tyvars
         exprFreeIds,    -- CoreExpr   -> IdSet  -- Find all locally-defined free Ids
         exprsFreeVars,  -- [CoreExpr] -> VarSet
         bindFreeVars,   -- CoreBind   -> VarSet
@@ -22,16 +23,20 @@ module CoreFVs (
         -- * Free variables of Rules, Vars and Ids
         varTypeTyVars,
         idUnfoldingVars, idFreeVars, idRuleAndUnfoldingVars,
+        idFreeVarsAcc,
         idRuleVars, idRuleRhsVars, stableUnfoldingVars,
         ruleRhsFreeVars, ruleFreeVars, rulesFreeVars,
+        rulesFreeDVars,
         ruleLhsFreeIds, exprsOrphNames,
         vectsFreeVars,
 
+        expr_fvs,
+
         -- * Core syntax tree annotation with free variables
-        CoreExprWithFVs,        -- = AnnExpr Id VarSet
-        CoreBindWithFVs,        -- = AnnBind Id VarSet
+        CoreExprWithFVs,        -- = AnnExpr Id DVarSet
+        CoreBindWithFVs,        -- = AnnBind Id DVarSet
         freeVars,               -- CoreExpr -> CoreExprWithFVs
-        freeVarsOf              -- CoreExprWithFVs -> IdSet
+        freeVarsOf              -- CoreExprWithFVs -> DIdSet
     ) where
 
 #include "HsVersions.h"
@@ -45,11 +50,13 @@ import Name
 import VarSet
 import Var
 import TcType
+import TypeRep
 import Coercion
 import Maybes( orElse )
 import Util
 import BasicTypes( Activation )
 import Outputable
+import FV
 
 {-
 ************************************************************************
@@ -69,7 +76,11 @@ but not those that are free in the type of variable occurrence.
 
 -- | Find all locally-defined free Ids or type variables in an expression
 exprFreeVars :: CoreExpr -> VarSet
-exprFreeVars = exprSomeFreeVars isLocalVar
+exprFreeVars = runFVSet . filterFV isLocalVar . expr_fvs
+
+exprFreeDVars :: CoreExpr -> DVarSet
+exprFreeDVars = runFVDSet . filterFV isLocalVar . expr_fvs
+
 
 -- | Find all locally-defined free Ids in an expression
 exprFreeIds :: CoreExpr -> IdSet        -- Find all locally-defined free Ids
@@ -81,44 +92,23 @@ exprsFreeVars = mapUnionVarSet exprFreeVars
 
 -- | Find all locally defined free Ids in a binding group
 bindFreeVars :: CoreBind -> VarSet
-bindFreeVars (NonRec b r) = rhs_fvs (b,r) isLocalVar emptyVarSet
-bindFreeVars (Rec prs)    = addBndrs (map fst prs)
-                                     (foldr (union . rhs_fvs) noVars prs)
-                                     isLocalVar emptyVarSet
+bindFreeVars (NonRec b r) = runFVSet $ filterFV isLocalVar $ rhs_fvs (b,r)
+bindFreeVars (Rec prs)    = runFVSet $ filterFV isLocalVar $
+                                addBndrs (map fst prs)
+                                     (foldr (unionFV . rhs_fvs) noVars prs)
 
 -- | Finds free variables in an expression selected by a predicate
 exprSomeFreeVars :: InterestingVarFun   -- ^ Says which 'Var's are interesting
                  -> CoreExpr
                  -> VarSet
-exprSomeFreeVars fv_cand e = expr_fvs e fv_cand emptyVarSet
+exprSomeFreeVars fv_cand e = runFVSet $ filterFV fv_cand $ expr_fvs e
 
 -- | Finds free variables in several expressions selected by a predicate
 exprsSomeFreeVars :: InterestingVarFun  -- Says which 'Var's are interesting
                   -> [CoreExpr]
                   -> VarSet
-exprsSomeFreeVars fv_cand = mapUnionVarSet (exprSomeFreeVars fv_cand)
-
--- | Predicate on possible free variables: returns @True@ iff the variable is interesting
-type InterestingVarFun = Var -> Bool
-
-type FV = InterestingVarFun
-        -> VarSet               -- Locally bound
-        -> VarSet               -- Free vars
- -- Return the vars that are both (a) interesting
- --                           and (b) not locally bound
- -- See function keep_it
-
-keep_it :: InterestingVarFun -> VarSet -> Var -> Bool
-keep_it fv_cand in_scope var
-  | var `elemVarSet` in_scope = False
-  | fv_cand var               = True
-  | otherwise                 = False
-
-union :: FV -> FV -> FV
-union fv1 fv2 fv_cand in_scope = fv1 fv_cand in_scope `unionVarSet` fv2 fv_cand in_scope
-
-noVars :: FV
-noVars _ _ = emptyVarSet
+exprsSomeFreeVars fv_cand es =
+  runFVSet $ filterFV fv_cand $ foldr (unionFV . expr_fvs) noVars es
 
 --      Comment about obselete code
 -- We used to gather the free variables the RULES at a variable occurrence
@@ -148,63 +138,65 @@ noVars _ _ = emptyVarSet
 --                          | otherwise                    = set
 --      SLPJ Feb06
 
-oneVar :: Id -> FV
-oneVar var fv_cand in_scope
-  = ASSERT( isId var )
-    if keep_it fv_cand in_scope var
-    then unitVarSet var
-    else emptyVarSet
+-- XXX move to FV
+someVars :: [Var] -> FV
+someVars vars = foldr (unionFV . oneVar) noVars vars
 
-someVars :: VarSet -> FV
-someVars vars fv_cand in_scope
-  = filterVarSet (keep_it fv_cand in_scope) vars
 
 addBndr :: CoreBndr -> FV -> FV
-addBndr bndr fv fv_cand in_scope
-  = someVars (varTypeTyVars bndr) fv_cand in_scope
+addBndr bndr fv fv_cand in_scope acc
+  = (varTypeTyVarsAcc bndr `unionFV`
         -- Include type varibles in the binder's type
         --      (not just Ids; coercion variables too!)
-    `unionVarSet`  fv fv_cand (in_scope `extendVarSet` bndr)
+     FV.delFV bndr fv) fv_cand in_scope acc
 
 addBndrs :: [CoreBndr] -> FV -> FV
 addBndrs bndrs fv = foldr addBndr fv bndrs
 
 expr_fvs :: CoreExpr -> FV
 
-expr_fvs (Type ty)       = someVars (tyVarsOfType ty)
-expr_fvs (Coercion co)   = someVars (tyCoVarsOfCo co)
-expr_fvs (Var var)       = oneVar var
-expr_fvs (Lit _)         = noVars
-expr_fvs (Tick t expr)   = tickish_fvs t `union` expr_fvs expr
-expr_fvs (App fun arg)   = expr_fvs fun `union` expr_fvs arg
-expr_fvs (Lam bndr body) = addBndr bndr (expr_fvs body)
-expr_fvs (Cast expr co)  = expr_fvs expr `union` someVars (tyCoVarsOfCo co)
-
-expr_fvs (Case scrut bndr ty alts)
-  = expr_fvs scrut `union` someVars (tyVarsOfType ty) `union` addBndr bndr
-      (foldr (union . alt_fvs) noVars alts)
+expr_fvs (Type ty) fv_cand in_scope acc =
+  tyVarsOfTypeAcc ty fv_cand in_scope acc
+expr_fvs (Coercion co) fv_cand in_scope acc =
+  tyCoVarsOfCoAcc co fv_cand in_scope acc
+expr_fvs (Var var) fv_cand in_scope acc = oneVar var fv_cand in_scope acc
+expr_fvs (Lit _) fv_cand in_scope acc = noVars fv_cand in_scope acc
+expr_fvs (Tick t expr) fv_cand in_scope acc =
+  (tickish_fvs t `unionFV` expr_fvs expr) fv_cand in_scope acc
+expr_fvs (App fun arg) fv_cand in_scope acc =
+  (expr_fvs fun `unionFV` expr_fvs arg) fv_cand in_scope acc
+expr_fvs (Lam bndr body) fv_cand in_scope acc =
+  addBndr bndr (expr_fvs body) fv_cand in_scope acc
+expr_fvs (Cast expr co) fv_cand in_scope acc =
+  (expr_fvs expr `unionFV` tyCoVarsOfCoAcc co) fv_cand in_scope acc
+
+expr_fvs (Case scrut bndr ty alts) fv_cand in_scope acc
+  = (expr_fvs scrut `unionFV` tyVarsOfTypeAcc ty `unionFV` addBndr bndr
+      (foldr (unionFV . alt_fvs) noVars alts)) fv_cand in_scope acc
   where
     alt_fvs (_, bndrs, rhs) = addBndrs bndrs (expr_fvs rhs)
 
-expr_fvs (Let (NonRec bndr rhs) body)
-  = rhs_fvs (bndr, rhs) `union` addBndr bndr (expr_fvs body)
+expr_fvs (Let (NonRec bndr rhs) body) fv_cand in_scope acc
+  = (rhs_fvs (bndr, rhs) `unionFV` addBndr bndr (expr_fvs body))
+      fv_cand in_scope acc
 
-expr_fvs (Let (Rec pairs) body)
+expr_fvs (Let (Rec pairs) body) fv_cand in_scope acc
   = addBndrs (map fst pairs)
-             (foldr (union . rhs_fvs) (expr_fvs body) pairs)
+             (foldr (unionFV . rhs_fvs) (expr_fvs body) pairs)
+               fv_cand in_scope acc
 
 ---------
-rhs_fvs :: (Id,CoreExpr) -> FV
-rhs_fvs (bndr, rhs) = expr_fvs rhs `union`
-                      someVars (bndrRuleAndUnfoldingVars bndr)
+rhs_fvs :: (Id, CoreExpr) -> FV
+rhs_fvs (bndr, rhs) = expr_fvs rhs `unionFV`
+                      bndrRuleAndUnfoldingVarsAcc bndr -- XXX: FIXME
         -- Treat any RULES as extra RHSs of the binding
 
 ---------
 exprs_fvs :: [CoreExpr] -> FV
-exprs_fvs exprs = foldr (union . expr_fvs) noVars exprs
+exprs_fvs exprs = foldr (unionFV . expr_fvs) noVars exprs
 
 tickish_fvs :: Tickish Id -> FV
-tickish_fvs (Breakpoint _ ids) = someVars (mkVarSet ids)
+tickish_fvs (Breakpoint _ ids) = someVars ids
 tickish_fvs _ = noVars
 
 {-
@@ -258,7 +250,7 @@ exprsOrphNames es = foldr (unionNameSet . exprOrphNames) emptyNameSet es
 ruleRhsFreeVars :: CoreRule -> VarSet
 ruleRhsFreeVars (BuiltinRule {}) = noFVs
 ruleRhsFreeVars (Rule { ru_fn = _, ru_bndrs = bndrs, ru_rhs = rhs })
-  = addBndrs bndrs (expr_fvs rhs) isLocalVar emptyVarSet
+  = runFVSet $ filterFV isLocalVar $ addBndrs bndrs (expr_fvs rhs)
       -- See Note [Rule free var hack]
 
 -- | Those variables free in the both the left right hand sides of a rule
@@ -267,7 +259,22 @@ ruleFreeVars (BuiltinRule {}) = noFVs
 ruleFreeVars (Rule { ru_fn = _do_not_include  -- See Note [Rule free var hack]
                    , ru_bndrs = bndrs
                    , ru_rhs = rhs, ru_args = args })
-  = addBndrs bndrs (exprs_fvs (rhs:args)) isLocalVar emptyVarSet
+  = runFVSet $ filterFV isLocalVar $ addBndrs bndrs (exprs_fvs (rhs:args))
+
+ruleFreeVarsAcc :: CoreRule -> FV
+ruleFreeVarsAcc (BuiltinRule {}) =
+  noVars
+ruleFreeVarsAcc (Rule { ru_fn = _do_not_include  -- See Note [Rule free var hack]
+                      , ru_bndrs = bndrs
+                      , ru_rhs = rhs, ru_args = args })
+  = addBndrs bndrs (exprs_fvs (rhs:args))
+
+rulesFreeVarsAcc :: [CoreRule] -> FV
+rulesFreeVarsAcc (rule:rules) = ruleFreeVarsAcc rule `unionFV` rulesFreeVarsAcc rules
+rulesFreeVarsAcc [] = noVars
+
+rulesFreeDVars :: [CoreRule] -> DVarSet
+rulesFreeDVars rules = runFVDSet $ filterFV isLocalVar $ rulesFreeVarsAcc rules
 
 
 idRuleRhsVars :: (Activation -> Bool) -> Id -> VarSet
@@ -281,7 +288,7 @@ idRuleRhsVars is_active id
             -- See Note [Finding rule RHS free vars] in OccAnal.hs
       = delFromUFM fvs fn        -- Note [Rule free var hack]
       where
-        fvs = addBndrs bndrs (expr_fvs rhs) isLocalVar emptyVarSet
+        fvs = runFVSet $ filterFV isLocalVar $ addBndrs bndrs (expr_fvs rhs)
     get_fvs _ = noFVs
 
 -- | Those variables free in the right hand side of several rules
@@ -292,7 +299,7 @@ ruleLhsFreeIds :: CoreRule -> VarSet
 -- ^ This finds all locally-defined free Ids on the left hand side of a rule
 ruleLhsFreeIds (BuiltinRule {}) = noFVs
 ruleLhsFreeIds (Rule { ru_bndrs = bndrs, ru_args = args })
-  = addBndrs bndrs (exprs_fvs args) isLocalId emptyVarSet
+  = runFVSet $ filterFV isLocalId $ addBndrs bndrs (exprs_fvs args)
 
 {-
 Note [Rule free var hack]  (Not a hack any more)
@@ -311,7 +318,7 @@ breaker, which is perfectly inlinable.
 vectsFreeVars :: [CoreVect] -> VarSet
 vectsFreeVars = mapUnionVarSet vectFreeVars
   where
-    vectFreeVars (Vect   _ rhs)   = expr_fvs rhs isLocalId emptyVarSet
+    vectFreeVars (Vect   _ rhs)   = runFVSet $ filterFV isLocalId $ expr_fvs rhs
     vectFreeVars (NoVect _)       = noFVs
     vectFreeVars (VectType _ _ _) = noFVs
     vectFreeVars (VectClass _)    = noFVs
@@ -331,28 +338,28 @@ NON-GLOBAL free variables and type variables.
 
 -- | Every node in a binding group annotated with its
 -- (non-global) free variables, both Ids and TyVars
-type CoreBindWithFVs = AnnBind Id VarSet
+type CoreBindWithFVs = AnnBind Id DVarSet
 -- | Every node in an expression annotated with its
 -- (non-global) free variables, both Ids and TyVars
-type CoreExprWithFVs = AnnExpr Id VarSet
+type CoreExprWithFVs = AnnExpr Id DVarSet
 
-freeVarsOf :: CoreExprWithFVs -> IdSet
+freeVarsOf :: CoreExprWithFVs -> DIdSet
 -- ^ Inverse function to 'freeVars'
 freeVarsOf (free_vars, _) = free_vars
 
 noFVs :: VarSet
-noFVs    = emptyVarSet
+noFVs = emptyVarSet
 
-aFreeVar :: Var -> VarSet
-aFreeVar = unitVarSet
+aFreeVar :: Var -> DVarSet
+aFreeVar = unitDVarSet
 
-unionFVs :: VarSet -> VarSet -> VarSet
-unionFVs = unionVarSet
+unionFVs :: DVarSet -> DVarSet -> DVarSet
+unionFVs = unionDVarSet
 
-delBindersFV :: [Var] -> VarSet -> VarSet
+delBindersFV :: [Var] -> DVarSet -> DVarSet
 delBindersFV bs fvs = foldr delBinderFV fvs bs
 
-delBinderFV :: Var -> VarSet -> VarSet
+delBinderFV :: Var -> DVarSet -> DVarSet
 -- This way round, so we can do it multiple times using foldr
 
 -- (b `delBinderFV` s) removes the binder b from the free variable set s,
@@ -383,32 +390,47 @@ delBinderFV :: Var -> VarSet -> VarSet
 --                        where
 --                          bottom = bottom -- Never evaluated
 
-delBinderFV b s = (s `delVarSet` b) `unionFVs` varTypeTyVars b
+delBinderFV b s = (s `delDVarSet` b) `unionFVs` dVarTypeTyVars b
         -- Include coercion variables too!
 
 varTypeTyVars :: Var -> TyVarSet
 -- Find the type/kind variables free in the type of the id/tyvar
-varTypeTyVars var = tyVarsOfType (varType var)
+varTypeTyVars var = runFVSet $ varTypeTyVarsAcc var
+
+dVarTypeTyVars :: Var -> DTyVarSet
+-- Find the type/kind variables free in the type of the id/tyvar
+dVarTypeTyVars var = runFVDSet $ varTypeTyVarsAcc var
+
+varTypeTyVarsAcc :: Var -> FV
+varTypeTyVarsAcc var = tyVarsOfTypeAcc (varType var)
 
 idFreeVars :: Id -> VarSet
+idFreeVars id = ASSERT( isId id) runFVSet $ idFreeVarsAcc id
+
+idFreeVarsAcc :: Id -> FV
 -- Type variables, rule variables, and inline variables
-idFreeVars id = ASSERT( isId id)
-                varTypeTyVars id `unionVarSet`
-                idRuleAndUnfoldingVars id
+idFreeVarsAcc id = ASSERT( isId id)
+                   varTypeTyVarsAcc id `unionFV`
+                   idRuleAndUnfoldingVarsAcc id
 
-bndrRuleAndUnfoldingVars ::Var -> VarSet
--- A 'let' can bind a type variable, and idRuleVars assumes
--- it's seeing an Id. This function tests first.
-bndrRuleAndUnfoldingVars v | isTyVar v = emptyVarSet
-                           | otherwise = idRuleAndUnfoldingVars v
+bndrRuleAndUnfoldingVarsAcc :: Var -> FV
+bndrRuleAndUnfoldingVarsAcc v | isTyVar v = noVars
+                              | otherwise = idRuleAndUnfoldingVarsAcc v
 
 idRuleAndUnfoldingVars :: Id -> VarSet
-idRuleAndUnfoldingVars id = ASSERT( isId id)
-                            idRuleVars id    `unionVarSet`
-                            idUnfoldingVars id
+idRuleAndUnfoldingVars id = runFVSet $ idRuleAndUnfoldingVarsAcc id
+
+idRuleAndUnfoldingVarsAcc :: Id -> FV
+idRuleAndUnfoldingVarsAcc id = ASSERT( isId id)
+                               idRuleVarsAcc id `unionFV` idUnfoldingVarsAcc id
+
 
 idRuleVars ::Id -> VarSet  -- Does *not* include CoreUnfolding vars
-idRuleVars id = ASSERT( isId id) ruleInfoFreeVars (idSpecialisation id)
+idRuleVars id = runFVSet $ idRuleVarsAcc id
+
+idRuleVarsAcc :: Id -> FV
+idRuleVarsAcc id = ASSERT( isId id)
+  someVars (dVarSetElems $ ruleInfoFreeVars (idSpecialisation id))
 
 idUnfoldingVars :: Id -> VarSet
 -- Produce free vars for an unfolding, but NOT for an ordinary
@@ -416,19 +438,26 @@ idUnfoldingVars :: Id -> VarSet
 -- and we'll get exponential behaviour if we look at both unf and rhs!
 -- But do look at the *real* unfolding, even for loop breakers, else
 -- we might get out-of-scope variables
-idUnfoldingVars id = stableUnfoldingVars (realIdUnfolding id) `orElse` emptyVarSet
+idUnfoldingVars id = runFVSet $ idUnfoldingVarsAcc id
+
+idUnfoldingVarsAcc :: Id -> FV
+idUnfoldingVarsAcc id = stableUnfoldingVarsAcc (realIdUnfolding id) `orElse` noVars
 
 stableUnfoldingVars :: Unfolding -> Maybe VarSet
-stableUnfoldingVars unf
+stableUnfoldingVars unf = runFVSet `fmap` stableUnfoldingVarsAcc unf
+
+stableUnfoldingVarsAcc :: Unfolding -> Maybe FV
+stableUnfoldingVarsAcc unf
   = case unf of
       CoreUnfolding { uf_tmpl = rhs, uf_src = src }
          | isStableSource src
-         -> Just (exprFreeVars rhs)
+         -> Just (filterFV isLocalVar $ expr_fvs rhs)
       DFunUnfolding { df_bndrs = bndrs, df_args = args }
-         -> Just (exprs_fvs args isLocalVar (mkVarSet bndrs))
+         -> Just (filterFV isLocalVar $ FV.delFVs (mkVarSet bndrs) $ exprs_fvs args)
             -- DFuns are top level, so no fvs from types of bndrs
       _other -> Nothing
 
+
 {-
 ************************************************************************
 *                                                                      *
@@ -448,9 +477,9 @@ freeVars (Var v)
         -- fvs = fvs_v `unionVarSet` idSpecVars v
 
     fvs | isLocalVar v = aFreeVar v
-        | otherwise    = noFVs
+        | otherwise    = emptyDVarSet
 
-freeVars (Lit lit) = (noFVs, AnnLit lit)
+freeVars (Lit lit) = (emptyDVarSet, AnnLit lit)
 freeVars (Lam b body)
   = (b `delBinderFV` freeVarsOf body', AnnLam b body')
   where
@@ -463,13 +492,13 @@ freeVars (App fun arg)
     arg2 = freeVars arg
 
 freeVars (Case scrut bndr ty alts)
-  = ((bndr `delBinderFV` alts_fvs) `unionFVs` freeVarsOf scrut2 `unionFVs` tyVarsOfType ty,
+  = ((bndr `delBinderFV` alts_fvs) `unionFVs` freeVarsOf scrut2 `unionFVs` runFVDSet (tyVarsOfTypeAcc ty),
      AnnCase scrut2 bndr ty alts2)
   where
     scrut2 = freeVars scrut
 
     (alts_fvs_s, alts2) = mapAndUnzip fv_alt alts
-    alts_fvs            = foldr unionFVs noFVs alts_fvs_s
+    alts_fvs            = foldr unionFVs emptyDVarSet alts_fvs_s
 
     fv_alt (con,args,rhs) = (delBindersFV args (freeVarsOf rhs2),
                              (con, args, rhs2))
@@ -479,7 +508,7 @@ freeVars (Case scrut bndr ty alts)
 freeVars (Let (NonRec binder rhs) body)
   = (freeVarsOf rhs2
        `unionFVs` body_fvs
-       `unionFVs` bndrRuleAndUnfoldingVars binder,
+       `unionFVs` runFVDSet (bndrRuleAndUnfoldingVarsAcc binder),
                 -- Remember any rules; cf rhs_fvs above
      AnnLet (AnnNonRec binder rhs2) body2)
   where
@@ -495,7 +524,8 @@ freeVars (Let (Rec binds) body)
 
     rhss2     = map freeVars rhss
     rhs_body_fvs = foldr (unionFVs . freeVarsOf) body_fvs rhss2
-    all_fvs      = foldr (unionFVs . idRuleAndUnfoldingVars) rhs_body_fvs binders
+    binders_fvs = runFVDSet $ foldr (unionFV . idRuleAndUnfoldingVarsAcc) noVars binders
+    all_fvs      = rhs_body_fvs `unionFVs` binders_fvs
         -- The "delBinderFV" happens after adding the idSpecVars,
         -- since the latter may add some of the binders as fvs
 
@@ -506,15 +536,15 @@ freeVars (Cast expr co)
   = (freeVarsOf expr2 `unionFVs` cfvs, AnnCast expr2 (cfvs, co))
   where
     expr2 = freeVars expr
-    cfvs  = tyCoVarsOfCo co
+    cfvs  = runFVDSet $ tyCoVarsOfCoAcc co
 
 freeVars (Tick tickish expr)
   = (tickishFVs tickish `unionFVs` freeVarsOf expr2, AnnTick tickish expr2)
   where
     expr2 = freeVars expr
-    tickishFVs (Breakpoint _ ids) = mkVarSet ids
-    tickishFVs _                  = emptyVarSet
+    tickishFVs (Breakpoint _ ids) = mkDVarSet ids
+    tickishFVs _                  = emptyDVarSet
 
-freeVars (Type ty) = (tyVarsOfType ty, AnnType ty)
+freeVars (Type ty) = (runFVDSet $ tyVarsOfTypeAcc ty, AnnType ty)
 
-freeVars (Coercion co) = (tyCoVarsOfCo co, AnnCoercion co)
+freeVars (Coercion co) = (runFVDSet $ tyCoVarsOfCoAcc co, AnnCoercion co)
index e3c7844..d426bd3 100644 (file)
@@ -14,7 +14,7 @@ import CoreSyn
 import IdInfo
 import Demand( seqDemand, seqStrictSig )
 import BasicTypes( seqOccInfo )
-import VarSet( seqVarSet )
+import VarSet( seqDVarSet )
 import Var( varType, tyVarKind )
 import Type( seqType, isTyVar )
 import Coercion( seqCo )
@@ -40,7 +40,7 @@ seqOneShot :: OneShotInfo -> ()
 seqOneShot l = l `seq` ()
 
 seqRuleInfo :: RuleInfo -> ()
-seqRuleInfo (RuleInfo rules fvs) = seqRules rules `seq` seqVarSet fvs
+seqRuleInfo (RuleInfo rules fvs) = seqRules rules `seq` seqDVarSet fvs
 
 seqCaf :: CafInfo -> ()
 seqCaf c = c `seq` ()
index c1de205..697ce4b 100644 (file)
@@ -17,7 +17,7 @@ module CoreSubst (
         substTy, substCo, substExpr, substExprSC, substBind, substBindSC,
         substUnfolding, substUnfoldingSC,
         lookupIdSubst, lookupTvSubst, lookupCvSubst, substIdOcc,
-        substTickish, substVarSet,
+        substTickish, substDVarSet,
 
         -- ** Operations on substitutions
         emptySubst, mkEmptySubst, mkSubst, mkOpenSubst, substInScope, isEmptySubst,
@@ -53,6 +53,7 @@ import qualified Coercion
         -- We are defining local versions
 import Type     hiding ( substTy, extendTvSubst, extendTvSubstList
                        , isInScope, substTyVarBndr, cloneTyVarBndr )
+import TypeRep (tyVarsOfTypeAcc)
 import Coercion hiding ( substTy, substCo, extendTvSubst, substTyVarBndr, substCoVarBndr )
 
 import TyCon       ( tyConArity )
@@ -674,7 +675,7 @@ substSpec subst new_id (RuleInfo rules rhs_fvs)
   where
     subst_ru_fn = const (idName new_id)
     new_spec = RuleInfo (map (substRule subst subst_ru_fn) rules)
-                        (substVarSet subst rhs_fvs)
+                        (substDVarSet subst rhs_fvs)
 
 ------------------
 substRulesForImportedIds :: Subst -> [CoreRule] -> [CoreRule]
@@ -721,13 +722,13 @@ substVect _subst vd@(VectClass _)    = vd
 substVect _subst vd@(VectInst _)     = vd
 
 ------------------
-substVarSet :: Subst -> VarSet -> VarSet
-substVarSet subst fvs
-  = foldVarSet (unionVarSet . subst_fv subst) emptyVarSet fvs
+substDVarSet :: Subst -> DVarSet -> DVarSet
+substDVarSet subst fvs
+  = mkDVarSet $ fst $ foldr (subst_fv subst) ([], emptyVarSet) $ dVarSetElems fvs
   where
-    subst_fv subst fv
-        | isId fv   = exprFreeVars (lookupIdSubst (text "substVarSet") subst fv)
-        | otherwise = Type.tyVarsOfType (lookupTvSubst subst fv)
+  subst_fv subst fv acc
+     | isId fv = expr_fvs (lookupIdSubst (text "substDVarSet") subst fv) isLocalVar emptyVarSet $! acc
+     | otherwise = tyVarsOfTypeAcc (lookupTvSubst subst fv) (const True) emptyVarSet $! acc
 
 ------------------
 substTickish :: Subst -> Tickish Id -> Tickish Id
index 26551b5..f7bfa7b 100644 (file)
@@ -40,7 +40,6 @@ import BasicTypes
 import FastString ( unpackFS )
 import Literal
 import PrelNames
-import VarSet
 import DynFlags
 import Outputable
 import Util
@@ -119,7 +118,7 @@ mkFCall dflags uniq the_fcall val_args res_ty
   where
     arg_tys = map exprType val_args
     body_ty = (mkFunTys arg_tys res_ty)
-    tyvars  = varSetElems (tyVarsOfType body_ty)
+    tyvars  = tyVarsOfTypeList body_ty
     ty      = mkForAllTys tyvars body_ty
     the_fcall_id = mkFCallId dflags uniq the_fcall ty
 
index 44e0aa0..13e7e11 100644 (file)
@@ -445,7 +445,7 @@ dsExpr (HsStatic expr@(L loc _)) = do
                  , moduleNameFS $ moduleName $ nameModule n'
                  , occNameFS    $ nameOccName n'
                  ]
-    let tvars = varSetElems $ tyVarsOfType ty
+    let tvars = tyVarsOfTypeList ty
         speTy = mkForAllTys tvars $ mkTyConApp staticPtrTyCon [ty]
         speId = mkExportedLocalId VanillaId n' speTy
         fp@(Fingerprint w0 w1) = fingerprintName $ idName speId
index b78c2b8..9ea5b66 100644 (file)
@@ -451,6 +451,7 @@ Library
         FastStringEnv
         Fingerprint
         FiniteMap
+        FV
         GraphBase
         GraphColor
         GraphOps
index e3f824e..b75fdc2 100644 (file)
@@ -529,6 +529,7 @@ compiler_stage2_dll0_MODULES = \
        Fingerprint \
        FiniteMap \
        ForeignCall \
+       FV \
        Hooks \
        HsBinds \
        HsDecls \
index 11a8c6d..83b8028 100644 (file)
@@ -152,7 +152,7 @@ mkProtoBCO
    :: DynFlags
    -> name
    -> BCInstrList
-   -> Either  [AnnAlt Id VarSet] (AnnExpr Id VarSet)
+   -> Either  [AnnAlt Id DVarSet] (AnnExpr Id DVarSet)
    -> Int
    -> Word16
    -> [StgWord]
@@ -215,7 +215,7 @@ argBits dflags (rep : args)
 
 -- Compile code for the right-hand side of a top-level binding
 
-schemeTopBind :: (Id, AnnExpr Id VarSet) -> BcM (ProtoBCO Name)
+schemeTopBind :: (Id, AnnExpr Id DVarSet) -> BcM (ProtoBCO Name)
 
 
 schemeTopBind (id, rhs)
@@ -252,7 +252,7 @@ schemeTopBind (id, rhs)
 schemeR :: [Id]                 -- Free vars of the RHS, ordered as they
                                 -- will appear in the thunk.  Empty for
                                 -- top-level things, which have no free vars.
-        -> (Id, AnnExpr Id VarSet)
+        -> (Id, AnnExpr Id DVarSet)
         -> BcM (ProtoBCO Name)
 schemeR fvs (nm, rhs)
 {-
@@ -267,7 +267,7 @@ schemeR fvs (nm, rhs)
 -}
    = schemeR_wrk fvs nm rhs (collect rhs)
 
-collect :: AnnExpr Id VarSet -> ([Var], AnnExpr' Id VarSet)
+collect :: AnnExpr Id DVarSet -> ([Var], AnnExpr' Id DVarSet)
 collect (_, e) = go [] e
   where
     go xs e | Just e' <- bcView e = go xs e'
@@ -278,7 +278,7 @@ collect (_, e) = go [] e
       = go (x:xs) e
     go xs not_lambda = (reverse xs, not_lambda)
 
-schemeR_wrk :: [Id] -> Id -> AnnExpr Id VarSet -> ([Var], AnnExpr' Var VarSet) -> BcM (ProtoBCO Name)
+schemeR_wrk :: [Id] -> Id -> AnnExpr Id DVarSet -> ([Var], AnnExpr' Var DVarSet) -> BcM (ProtoBCO Name)
 schemeR_wrk fvs nm original_body (args, body)
    = do
      dflags <- getDynFlags
@@ -303,7 +303,7 @@ schemeR_wrk fvs nm original_body (args, body)
                  arity bitmap_size bitmap False{-not alts-})
 
 -- introduce break instructions for ticked expressions
-schemeER_wrk :: Word -> BCEnv -> AnnExpr' Id VarSet -> BcM BCInstrList
+schemeER_wrk :: Word -> BCEnv -> AnnExpr' Id DVarSet -> BcM BCInstrList
 schemeER_wrk d p rhs
   | AnnTick (Breakpoint tick_no fvs) (_annot, newRhs) <- rhs
   = do  code <- schemeE (fromIntegral d) 0 p newRhs
@@ -338,7 +338,7 @@ trunc16 w
     | otherwise
     = fromIntegral w
 
-fvsToEnv :: BCEnv -> VarSet -> [Id]
+fvsToEnv :: BCEnv -> DVarSet -> [Id]
 -- Takes the free variables of a right-hand side, and
 -- delivers an ordered list of the local variables that will
 -- be captured in the thunk for the RHS
@@ -347,7 +347,7 @@ fvsToEnv :: BCEnv -> VarSet -> [Id]
 --
 -- The code that constructs the thunk, and the code that executes
 -- it, have to agree about this layout
-fvsToEnv p fvs = [v | v <- varSetElems fvs,
+fvsToEnv p fvs = [v | v <- dVarSetElems fvs,
                       isId v,           -- Could be a type variable
                       v `Map.member` p]
 
@@ -355,7 +355,7 @@ fvsToEnv p fvs = [v | v <- varSetElems fvs,
 -- schemeE
 
 returnUnboxedAtom :: Word -> Sequel -> BCEnv
-                 -> AnnExpr' Id VarSet -> ArgRep
+                 -> AnnExpr' Id DVarSet -> ArgRep
                  -> BcM BCInstrList
 -- Returning an unlifted value.
 -- Heave it on the stack, SLIDE, and RETURN.
@@ -367,7 +367,7 @@ returnUnboxedAtom d s p e e_rep
 
 -- Compile code to apply the given expression to the remaining args
 -- on the stack, returning a HNF.
-schemeE :: Word -> Sequel -> BCEnv -> AnnExpr' Id VarSet -> BcM BCInstrList
+schemeE :: Word -> Sequel -> BCEnv -> AnnExpr' Id DVarSet -> BcM BCInstrList
 
 schemeE d s p e
    | Just e' <- bcView e
@@ -469,17 +469,17 @@ schemeE d s p exp@(AnnTick (Breakpoint _id _fvs) _rhs)
           -- breakpoint will otherwise work fine.
           id <- newId (mkFunTy realWorldStatePrimTy ty)
           st <- newId realWorldStatePrimTy
-          let letExp = AnnLet (AnnNonRec id (fvs, AnnLam st (emptyVarSet, exp)))
-                              (emptyVarSet, (AnnApp (emptyVarSet, AnnVar id)
-                                                    (emptyVarSet, AnnVar realWorldPrimId)))
+          let letExp = AnnLet (AnnNonRec id (fvs, AnnLam st (emptyDVarSet, exp)))
+                              (emptyDVarSet, (AnnApp (emptyDVarSet, AnnVar id)
+                                                    (emptyDVarSet, AnnVar realWorldPrimId)))
           schemeE d s p letExp
         else do
           id <- newId ty
           -- Todo: is emptyVarSet correct on the next line?
-          let letExp = AnnLet (AnnNonRec id (fvs, exp)) (emptyVarSet, AnnVar id)
+          let letExp = AnnLet (AnnNonRec id (fvs, exp)) (emptyDVarSet, AnnVar id)
           schemeE d s p letExp
    where exp' = deAnnotate' exp
-         fvs  = exprFreeVars exp'
+         fvs  = exprFreeDVars exp'
          ty   = exprType exp'
 
 -- ignore other kinds of tick
@@ -581,7 +581,7 @@ schemeE _ _ _ expr
 schemeT :: Word         -- Stack depth
         -> Sequel       -- Sequel depth
         -> BCEnv        -- stack env
-        -> AnnExpr' Id VarSet
+        -> AnnExpr' Id DVarSet
         -> BcM BCInstrList
 
 schemeT d s p app
@@ -644,7 +644,7 @@ schemeT d s p app
 
 mkConAppCode :: Word -> Sequel -> BCEnv
              -> DataCon                 -- The data constructor
-             -> [AnnExpr' Id VarSet]    -- Args, in *reverse* order
+             -> [AnnExpr' Id DVarSet]    -- Args, in *reverse* order
              -> BcM BCInstrList
 
 mkConAppCode _ _ _ con []       -- Nullary constructor
@@ -680,7 +680,7 @@ mkConAppCode orig_d _ p con args_r_to_l
 
 unboxedTupleReturn
         :: Word -> Sequel -> BCEnv
-        -> AnnExpr' Id VarSet -> BcM BCInstrList
+        -> AnnExpr' Id DVarSet -> BcM BCInstrList
 unboxedTupleReturn d s p arg = returnUnboxedAtom d s p arg (atomRep arg)
 
 -- -----------------------------------------------------------------------------
@@ -688,7 +688,7 @@ unboxedTupleReturn d s p arg = returnUnboxedAtom d s p arg (atomRep arg)
 
 doTailCall
         :: Word -> Sequel -> BCEnv
-        -> Id -> [AnnExpr' Id VarSet]
+        -> Id -> [AnnExpr' Id DVarSet]
         -> BcM BCInstrList
 doTailCall init_d s p fn args
   = do_pushes init_d args (map atomRep args)
@@ -745,7 +745,7 @@ findPushSeq _
 -- Case expressions
 
 doCase  :: Word -> Sequel -> BCEnv
-        -> AnnExpr Id VarSet -> Id -> [AnnAlt Id VarSet]
+        -> AnnExpr Id DVarSet -> Id -> [AnnAlt Id DVarSet]
         -> Maybe Id  -- Just x <=> is an unboxed tuple case with scrut binder, don't enter the result
         -> BcM BCInstrList
 doCase d s p (_,scrut) bndr alts is_unboxed_tuple
@@ -900,7 +900,7 @@ generateCCall :: Word -> Sequel         -- stack and sequel depths
               -> BCEnv
               -> CCallSpec              -- where to call
               -> Id                     -- of target, for type info
-              -> [AnnExpr' Id VarSet]   -- args (atoms)
+              -> [AnnExpr' Id DVarSet]   -- args (atoms)
               -> BcM BCInstrList
 
 generateCCall d0 s p (CCallSpec target cconv safety) fn args_r_to_l
@@ -949,7 +949,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) fn args_r_to_l
          -- Do magic for Ptr/Byte arrays.  Push a ptr to the array on
          -- the stack but then advance it over the headers, so as to
          -- point to the payload.
-         parg_ArrayishRep :: Word16 -> Word -> BCEnv -> AnnExpr' Id VarSet
+         parg_ArrayishRep :: Word16 -> Word -> BCEnv -> AnnExpr' Id DVarSet
                           -> BcM BCInstrList
          parg_ArrayishRep hdrSize d p a
             = do (push_fo, _) <- pushAtom d p a
@@ -1142,7 +1142,7 @@ maybe_getCCallReturnRep fn_ty
      --trace (showSDoc (ppr (a_reps, r_reps))) $
      if ok then maybe_r_rep_to_go else blargh
 
-maybe_is_tagToEnum_call :: AnnExpr' Id VarSet -> Maybe (AnnExpr' Id VarSet, [Name])
+maybe_is_tagToEnum_call :: AnnExpr' Id DVarSet -> Maybe (AnnExpr' Id DVarSet, [Name])
 -- Detect and extract relevant info for the tagToEnum kludge.
 maybe_is_tagToEnum_call app
   | AnnApp (_, AnnApp (_, AnnVar v) (_, AnnType t)) arg <- app
@@ -1200,7 +1200,7 @@ a 1-word null. See Trac #8383.
 
 
 implement_tagToId :: Word -> Sequel -> BCEnv
-                  -> AnnExpr' Id VarSet -> [Name] -> BcM BCInstrList
+                  -> AnnExpr' Id DVarSet -> [Name] -> BcM BCInstrList
 -- See Note [Implementing tagToEnum#]
 implement_tagToId d s p arg names
   = ASSERT( notNull names )
@@ -1243,7 +1243,7 @@ implement_tagToId d s p arg names
 -- to 5 and not to 4.  Stack locations are numbered from zero, so a
 -- depth 6 stack has valid words 0 .. 5.
 
-pushAtom :: Word -> BCEnv -> AnnExpr' Id VarSet -> BcM (BCInstrList, Word16)
+pushAtom :: Word -> BCEnv -> AnnExpr' Id DVarSet -> BcM (BCInstrList, Word16)
 
 pushAtom d p e
    | Just e' <- bcView e
index fee15bb..2de4941 100644 (file)
@@ -44,7 +44,7 @@ data ProtoBCO a
         protoBCOBitmapSize :: Word16,
         protoBCOArity      :: Int,
         -- what the BCO came from
-        protoBCOExpr       :: Either  [AnnAlt Id VarSet] (AnnExpr Id VarSet),
+        protoBCOExpr       :: Either  [AnnAlt Id DVarSet] (AnnExpr Id DVarSet),
         -- malloc'd pointers
         protoBCOPtrs       :: [Either ItblPtr (Ptr ())]
    }
index 6853fbb..1ec127e 100644 (file)
@@ -1268,7 +1268,7 @@ quantifyType :: Type -> QuantifiedType
 -- Thus (quantifyType (forall a. a->[b]))
 -- returns ([a,b], a -> [b])
 
-quantifyType ty = (varSetElems (tyVarsOfType rho), rho)
+quantifyType ty = (tyVarsOfTypeList rho, rho)
   where
     (_tvs, rho) = tcSplitForAllTys ty
 
index 8b2a84d..c1147eb 100644 (file)
@@ -28,7 +28,7 @@ import Var
 import Type             ( Type, isUnLiftedType, isFunTy, splitFunTy, applyTy )
 import VarSet
 import Util
-import UniqFM
+import UniqDFM (UniqDFM, udfmToUfm)
 import DynFlags
 import Outputable
 import Data.List( mapAccumL )
@@ -143,7 +143,7 @@ fiExpr dflags to_drop (_, AnnCast expr (fvs_co, co))
   = wrapFloats (drop_here ++ co_drop) $
     Cast (fiExpr dflags e_drop expr) co
   where
-    [drop_here, e_drop, co_drop] = sepBindsByDropPoint dflags False [freeVarsOf expr, fvs_co] to_drop
+    [drop_here, e_drop, co_drop] = sepBindsByDropPoint dflags False [udfmToUfm $ freeVarsOf expr, udfmToUfm fvs_co] to_drop
 
 {-
 Applications: we do float inside applications, mainly because we
@@ -167,16 +167,17 @@ fiExpr dflags to_drop ann_expr@(_,AnnApp {})
     mk_arg_fvs (fun_ty, extra_fvs) (_, AnnType ty)
       = ((applyTy fun_ty ty, extra_fvs), emptyVarSet)
 
-    mk_arg_fvs (fun_ty, extra_fvs) (arg_fvs, ann_arg)
+    mk_arg_fvs (fun_ty, extra_fvs) (arg_dfvs, ann_arg)
       | ASSERT( isFunTy fun_ty ) noFloatIntoRhs ann_arg arg_ty
       = ((res_ty, extra_fvs `unionVarSet` arg_fvs), emptyVarSet)
       | otherwise
       = ((res_ty, extra_fvs), arg_fvs)
       where
+       arg_fvs = udfmToUfm arg_dfvs
        (arg_ty, res_ty) = splitFunTy fun_ty
 
     drop_here : extra_drop : fun_drop : arg_drops
-      = sepBindsByDropPoint dflags False (extra_fvs : fun_fvs : arg_fvs) to_drop
+      = sepBindsByDropPoint dflags False (extra_fvs : udfmToUfm fun_fvs : arg_fvs) to_drop
 
 {-
 Note [Do not destroy the let/app invariant]
@@ -303,12 +304,12 @@ idRuleAndUnfoldingVars of x.  No need for type variables, hence not using
 idFreeVars.
 -}
 
-fiExpr dflags to_drop (_,AnnLet (AnnNonRec id rhs@(rhs_fvs, ann_rhs)) body)
+fiExpr dflags to_drop (_,AnnLet (AnnNonRec id rhs@(rhs_dfvs, ann_rhs)) body)
   = fiExpr dflags new_to_drop body
   where
-    body_fvs = freeVarsOf body `delVarSet` id
+    body_fvs = udfmToUfm (freeVarsOf body) `delVarSet` id
     rhs_ty = idType id
-
+    rhs_fvs = udfmToUfm rhs_dfvs
     rule_fvs = idRuleAndUnfoldingVars id        -- See Note [extra_fvs (2): free variables of rules]
     extra_fvs | noFloatIntoRhs ann_rhs rhs_ty = rule_fvs `unionVarSet` rhs_fvs
               | otherwise                     = rule_fvs
@@ -334,13 +335,13 @@ fiExpr dflags to_drop (_,AnnLet (AnnRec bindings) body)
   = fiExpr dflags new_to_drop body
   where
     (ids, rhss) = unzip bindings
-    rhss_fvs = map freeVarsOf rhss
-    body_fvs = freeVarsOf body
+    rhss_fvs = map (udfmToUfm . freeVarsOf) rhss
+    body_fvs = udfmToUfm $ freeVarsOf body
 
         -- See Note [extra_fvs (1,2)]
     rule_fvs = mapUnionVarSet idRuleAndUnfoldingVars ids
     extra_fvs = rule_fvs `unionVarSet`
-                unionVarSets [ fvs | (fvs, rhs) <- rhss
+                unionVarSets [ udfmToUfm fvs | (fvs, rhs) <- rhss
                              , noFloatIntoExpr rhs ]
 
     (shared_binds:extra_binds:body_binds:rhss_binds)
@@ -392,8 +393,8 @@ fiExpr dflags to_drop (_, AnnCase scrut case_bndr _ [(con,alt_bndrs,rhs)])
     scrut' = fiExpr dflags scrut_binds scrut
     [shared_binds, scrut_binds, rhs_binds]
        = sepBindsByDropPoint dflags False [scrut_fvs, rhs_fvs] to_drop
-    rhs_fvs   = freeVarsOf rhs `delVarSetList` (case_bndr : alt_bndrs)
-    scrut_fvs = freeVarsOf scrut
+    rhs_fvs   = udfmToUfm (freeVarsOf rhs) `delVarSetList` (case_bndr : alt_bndrs)
+    scrut_fvs = udfmToUfm $ freeVarsOf scrut
 
 fiExpr dflags to_drop (_, AnnCase scrut case_bndr ty alts)
   = wrapFloats drop_here1 $
@@ -408,10 +409,10 @@ fiExpr dflags to_drop (_, AnnCase scrut case_bndr ty alts)
         -- Float into the alts with the is_case flag set
     (drop_here2 : alts_drops_s) = sepBindsByDropPoint dflags True alts_fvs alts_drops
 
-    scrut_fvs    = freeVarsOf scrut
+    scrut_fvs    = udfmToUfm $ freeVarsOf scrut
     alts_fvs     = map alt_fvs alts
     all_alts_fvs = unionVarSets alts_fvs
-    alt_fvs (_con, args, rhs) = foldl delVarSet (freeVarsOf rhs) (case_bndr:args)
+    alt_fvs (_con, args, rhs) = foldl delVarSet (udfmToUfm $ freeVarsOf rhs) (case_bndr:args)
                                 -- Delete case_bndr and args from free vars of rhs
                                 -- to get free vars of alt
 
@@ -423,14 +424,14 @@ okToFloatInside bndrs = all ok bndrs
     ok b = not (isId b) || isOneShotBndr b
     -- Push the floats inside there are no non-one-shot value binders
 
-noFloatIntoRhs :: AnnExpr' Var (UniqFM Var) -> Type -> Bool
+noFloatIntoRhs :: AnnExpr' Var (UniqDFM Var) -> Type -> Bool
 -- ^ True if it's a bad idea to float bindings into this RHS
 -- Preconditio:  rhs :: rhs_ty
 noFloatIntoRhs rhs rhs_ty
   =  isUnLiftedType rhs_ty   -- See Note [Do not destroy the let/app invariant]
   || noFloatIntoExpr rhs
 
-noFloatIntoExpr :: AnnExpr' Var (UniqFM Var) -> Bool
+noFloatIntoExpr :: AnnExpr' Var (UniqDFM Var) -> Bool
 noFloatIntoExpr (AnnLam bndr e)
    = not (okToFloatInside (bndr:bndrs))
      -- NB: Must line up with fiExpr (AnnLam...); see Trac #7088
index d873cc5..d37a62d 100644 (file)
@@ -63,7 +63,7 @@ import CoreFVs          -- all of it
 import Coercion         ( isCoVar )
 import CoreSubst        ( Subst, emptySubst, substBndrs, substRecBndrs,
                           extendIdSubst, extendSubstWithVar, cloneBndrs,
-                          cloneRecIdBndrs, substTy, substCo, substVarSet )
+                          cloneRecIdBndrs, substTy, substCo, substDVarSet )
 import MkCore           ( sortQuantVars )
 import Id
 import IdInfo
@@ -80,6 +80,8 @@ import UniqSupply
 import Util
 import Outputable
 import FastString
+import UniqDFM (udfmToUfm)
+import FV
 
 {-
 ************************************************************************
@@ -362,10 +364,10 @@ lvlExpr env (_, AnnCase scrut@(scrut_fvs,_) case_bndr ty alts)
 
 -------------------------------------------
 lvlCase :: LevelEnv             -- Level of in-scope names/tyvars
-        -> VarSet               -- Free vars of input scrutinee
+        -> DVarSet              -- Free vars of input scrutinee
         -> LevelledExpr         -- Processed scrutinee
         -> Id -> Type           -- Case binder and result type
-        -> [AnnAlt Id VarSet]   -- Input alternatives
+        -> [AnnAlt Id DVarSet]  -- Input alternatives
         -> LvlM LevelledExpr    -- Result expression
 lvlCase env scrut_fvs scrut' case_bndr ty alts
   | [(con@(DataAlt {}), bs, body)] <- alts
@@ -707,7 +709,7 @@ lvlBind env (AnnNonRec bndr rhs@(rhs_fvs,_))
        ; return (NonRec (TB bndr' (FloatMe dest_lvl)) rhs', env') }
 
   where
-    bind_fvs   = rhs_fvs `unionVarSet` idFreeVars bndr
+    bind_fvs   = rhs_fvs `unionDVarSet` runFVDSet (idFreeVarsAcc bndr)
     abs_vars   = abstractVars dest_lvl env bind_fvs
     dest_lvl   = destLevel env bind_fvs (isFunction rhs) is_bot
     is_bot     = exprIsBottom (deAnnotate rhs)
@@ -767,10 +769,12 @@ lvlBind env (AnnRec pairs)
     (bndrs,rhss) = unzip pairs
 
         -- Finding the free vars of the binding group is annoying
-    bind_fvs = (unionVarSets [ idFreeVars bndr `unionVarSet` rhs_fvs
-                            | (bndr, (rhs_fvs,_)) <- pairs])
-               `minusVarSet`
-               mkVarSet bndrs
+    bind_fvs = ((unionDVarSets [ rhs_fvs | (_, (rhs_fvs,_)) <- pairs])
+                `unionDVarSet`
+                (runFVDSet $ foldr unionFV noVars [ idFreeVarsAcc bndr
+                                                  | (bndr, (_,_)) <- pairs]))
+               `minusDVarSet`
+                mkDVarSet bndrs -- XXX: it's a waste to create a set here
 
     dest_lvl = destLevel env bind_fvs (all isFunction rhss) False
     abs_vars = abstractVars dest_lvl env bind_fvs
@@ -850,7 +854,7 @@ lvlBndrs env@(LE { le_lvl_env = lvl_env }) new_lvl bndrs
 
   -- Destination level is the max Id level of the expression
   -- (We'll abstract the type variables, if any.)
-destLevel :: LevelEnv -> VarSet
+destLevel :: LevelEnv -> DVarSet
           -> Bool   -- True <=> is function
           -> Bool   -- True <=> is bottom
           -> Level
@@ -887,8 +891,8 @@ isFunction (_, AnnLam b e) | isId b    = True
 -- isFunction (_, AnnTick _ e)          = isFunction e  -- dubious
 isFunction _                           = False
 
-countFreeIds :: VarSet -> Int
-countFreeIds = foldVarSet add 0
+countFreeIds :: DVarSet -> Int
+countFreeIds = foldVarSet add 0 . udfmToUfm
   where
     add :: Var -> Int -> Int
     add v n | isId v    = n+1
@@ -970,9 +974,9 @@ extendCaseBndrEnv le@(LE { le_subst = subst, le_env = id_env })
        , le_env     = add_id id_env (case_bndr, scrut_var) }
 extendCaseBndrEnv env _ _ = env
 
-maxFvLevel :: (Var -> Bool) -> LevelEnv -> VarSet -> Level
+maxFvLevel :: (Var -> Bool) -> LevelEnv -> DVarSet -> Level
 maxFvLevel max_me (LE { le_lvl_env = lvl_env, le_env = id_env }) var_set
-  = foldVarSet max_in tOP_LEVEL var_set
+  = foldDVarSet max_in tOP_LEVEL var_set
   where
     max_in in_var lvl
        = foldr max_out lvl (case lookupVarEnv id_env in_var of
@@ -990,17 +994,17 @@ lookupVar le v = case lookupVarEnv (le_env le) v of
                     Just (_, expr) -> expr
                     _              -> Var v
 
-abstractVars :: Level -> LevelEnv -> VarSet -> [OutVar]
+abstractVars :: Level -> LevelEnv -> DVarSet -> [OutVar]
         -- Find the variables in fvs, free vars of the target expresion,
         -- whose level is greater than the destination level
         -- These are the ones we are going to abstract out
 abstractVars dest_lvl (LE { le_subst = subst, le_lvl_env = lvl_env }) in_fvs
   = map zap $ uniq $ sortQuantVars
-    [out_var | out_fv  <- varSetElems (substVarSet subst in_fvs)
+    [out_var | out_fv  <- dVarSetElems (substDVarSet subst in_fvs)
              , out_var <- varSetElems (close out_fv)
              , abstract_me out_var ]
         -- NB: it's important to call abstract_me only on the OutIds the
-        -- come from substVarSet (not on fv, which is an InId)
+        -- come from substDVarSet (not on fv, which is an InId)
   where
     uniq :: [Var] -> [Var]
         -- Remove adjacent duplicates; the sort will have brought them together
index 9b5d3cf..1aa472b 100644 (file)
@@ -33,7 +33,7 @@ import Module           ( Module, ModuleSet, elemModuleSet )
 import CoreSubst
 import OccurAnal        ( occurAnalyseExpr )
 import CoreFVs          ( exprFreeVars, exprsFreeVars, bindFreeVars
-                        , rulesFreeVars, exprsOrphNames )
+                        , rulesFreeDVars, exprsOrphNames )
 import CoreUtils        ( exprType, eqExpr, mkTick, mkTicks,
                           stripTicksTopT, stripTicksTopE )
 import PprCore          ( pprRules )
@@ -275,15 +275,15 @@ pprRulesForUser rules
 -- | Make a 'RuleInfo' containing a number of 'CoreRule's, suitable
 -- for putting into an 'IdInfo'
 mkRuleInfo :: [CoreRule] -> RuleInfo
-mkRuleInfo rules = RuleInfo rules (rulesFreeVars rules)
+mkRuleInfo rules = RuleInfo rules (rulesFreeDVars rules)
 
 extendRuleInfo :: RuleInfo -> [CoreRule] -> RuleInfo
 extendRuleInfo (RuleInfo rs1 fvs1) rs2
-  = RuleInfo (rs2 ++ rs1) (rulesFreeVars rs2 `unionVarSet` fvs1)
+  = RuleInfo (rs2 ++ rs1) (rulesFreeDVars rs2 `unionDVarSet` fvs1)
 
 addRuleInfo :: RuleInfo -> RuleInfo -> RuleInfo
 addRuleInfo (RuleInfo rs1 fvs1) (RuleInfo rs2 fvs2)
-  = RuleInfo (rs1 ++ rs2) (fvs1 `unionVarSet` fvs2)
+  = RuleInfo (rs1 ++ rs2) (fvs1 `unionDVarSet` fvs2)
 
 addIdSpecialisations :: Id -> [CoreRule] -> Id
 addIdSpecialisations id []
index 28502b6..8631bd3 100644 (file)
@@ -691,7 +691,7 @@ deriveTyData tvs tc tc_args (L loc deriv_pred)
               final_cls_tys       = substTys subst' cls_tys
 
         ; traceTc "derivTyData1" (vcat [ pprTvBndrs tvs, ppr tc, ppr tc_args, ppr deriv_pred
-                                       , pprTvBndrs (varSetElems $ tyVarsOfTypes tc_args)
+                                       , pprTvBndrs (tyVarsOfTypesList tc_args)
                                        , ppr n_args_to_keep, ppr n_args_to_drop
                                        , ppr inst_ty_kind, ppr cls_arg_kind, ppr mb_match
                                        , ppr final_tc_args, ppr final_cls_tys ])
index e1550be..3827363 100644 (file)
@@ -738,7 +738,7 @@ mkHoleError ctxt ct@(CHoleCan { cc_occ = occ, cc_hole = hole_sort })
     ct_loc      = ctLoc ct
     lcl_env     = ctLocEnv ct_loc
     hole_ty     = ctEvPred (ctEvidence ct)
-    tyvars      = varSetElems (tyVarsOfType hole_ty)
+    tyvars      = tyVarsOfTypeList hole_ty
     boring_type = isTyVarTy hole_ty
 
     out_of_scope_msg -- Print v :: ty only if the type has structure
@@ -1655,7 +1655,7 @@ mk_dict_err ctxt (ct, (matches, unifiers, unsafe_overlapped))
 
              ,  ppWhen (isSingleton matches) $
                 parens (vcat [ ptext (sLit "The choice depends on the instantiation of") <+>
-                                  quotes (pprWithCommas ppr (varSetElems (tyVarsOfTypes tys)))
+                                  quotes (pprWithCommas ppr (tyVarsOfTypesList tys))
                              , ppWhen (null (matching_givens)) $
                                vcat [ ptext (sLit "To pick the first instance above, use IncoherentInstances")
                                     , ptext (sLit "when compiling the other instance declarations")]
index 191756a..318d7d8 100644 (file)
@@ -972,7 +972,7 @@ kcHsTyVarBndrs cusk (HsQTvs { hsq_kvs = kv_ns, hsq_tvs = hs_tvs }) thing_inside
        ; (res_kind, stuff) <- tcExtendKindEnv nks thing_inside
        ; let full_kind = mkArrowKinds (map snd nks) res_kind
              kvs       = filter (not . isMetaTyVar) $
-                         varSetElems $ tyVarsOfType full_kind
+                         tyVarsOfTypeList full_kind
              gen_kind  = if cusk
                          then mkForAllTys kvs full_kind
                          else full_kind
index 13422d9..78a0fbc 100644 (file)
@@ -143,6 +143,7 @@ module TcType (
   isPrimitiveType,
 
   tyVarsOfType, tyVarsOfTypes, closeOverKinds,
+  tyVarsOfTypeList, tyVarsOfTypesList,
   tcTyVarsOfType, tcTyVarsOfTypes,
 
   pprKind, pprParendKind, pprSigmaType,
index af05d5c..fee8c34 100644 (file)
@@ -47,6 +47,7 @@ module Coercion (
 
         -- ** Free variables
         tyCoVarsOfCo, tyCoVarsOfCos, coVarsOfCo, coercionSize,
+        tyCoVarsOfCoAcc, tyCoVarsOfCosAcc,
 
         -- ** Substitution
         CvSubstEnv, emptyCvSubstEnv,
@@ -107,6 +108,7 @@ import Data.Traversable (traverse, sequenceA)
 #endif
 import FastString
 import ListSetOps
+import FV
 
 import qualified Data.Data as Data hiding ( TyCon )
 import Control.Arrow ( first )
@@ -554,24 +556,45 @@ isCoVarType ty      -- Tests for t1 ~# t2, the unboxed equality
       Nothing       -> False
 
 tyCoVarsOfCo :: Coercion -> VarSet
+tyCoVarsOfCo co = runFVSet $ tyCoVarsOfCoAcc co
 -- Extracts type and coercion variables from a coercion
-tyCoVarsOfCo (Refl _ ty)           = tyVarsOfType ty
-tyCoVarsOfCo (TyConAppCo _ _ cos)  = tyCoVarsOfCos cos
-tyCoVarsOfCo (AppCo co1 co2)       = tyCoVarsOfCo co1 `unionVarSet` tyCoVarsOfCo co2
-tyCoVarsOfCo (ForAllCo tv co)      = tyCoVarsOfCo co `delVarSet` tv
-tyCoVarsOfCo (CoVarCo v)           = unitVarSet v
-tyCoVarsOfCo (AxiomInstCo _ _ cos) = tyCoVarsOfCos cos
-tyCoVarsOfCo (UnivCo _ _ ty1 ty2)  = tyVarsOfType ty1 `unionVarSet` tyVarsOfType ty2
-tyCoVarsOfCo (SymCo co)            = tyCoVarsOfCo co
-tyCoVarsOfCo (TransCo co1 co2)     = tyCoVarsOfCo co1 `unionVarSet` tyCoVarsOfCo co2
-tyCoVarsOfCo (NthCo _ co)          = tyCoVarsOfCo co
-tyCoVarsOfCo (LRCo _ co)           = tyCoVarsOfCo co
-tyCoVarsOfCo (InstCo co ty)        = tyCoVarsOfCo co `unionVarSet` tyVarsOfType ty
-tyCoVarsOfCo (SubCo co)            = tyCoVarsOfCo co
-tyCoVarsOfCo (AxiomRuleCo _ ts cs) = tyVarsOfTypes ts `unionVarSet` tyCoVarsOfCos cs
 
 tyCoVarsOfCos :: [Coercion] -> VarSet
-tyCoVarsOfCos = mapUnionVarSet tyCoVarsOfCo
+tyCoVarsOfCos cos = runFVSet $ tyCoVarsOfCosAcc cos
+
+tyCoVarsOfCoAcc :: Coercion -> FV
+tyCoVarsOfCoAcc (Refl _ ty) fv_cand in_scope acc =
+  tyVarsOfTypeAcc ty fv_cand in_scope acc
+tyCoVarsOfCoAcc (TyConAppCo _ _ cos) fv_cand in_scope acc =
+  tyCoVarsOfCosAcc cos fv_cand in_scope acc
+tyCoVarsOfCoAcc (AppCo co1 co2) fv_cand in_scope acc =
+  (tyCoVarsOfCoAcc co1 `unionFV` tyCoVarsOfCoAcc co2) fv_cand in_scope acc
+tyCoVarsOfCoAcc (ForAllCo tv co) fv_cand in_scope acc =
+  delFV tv (tyCoVarsOfCoAcc co) fv_cand in_scope acc
+tyCoVarsOfCoAcc (CoVarCo v) fv_cand in_scope acc = oneVar v fv_cand in_scope acc
+tyCoVarsOfCoAcc (AxiomInstCo _ _ cos) fv_cand in_scope acc =
+  tyCoVarsOfCosAcc cos fv_cand in_scope acc
+tyCoVarsOfCoAcc (UnivCo _ _ ty1 ty2) fv_cand in_scope acc =
+  (tyVarsOfTypeAcc ty1 `unionFV` tyVarsOfTypeAcc ty2) fv_cand in_scope acc
+tyCoVarsOfCoAcc (SymCo co) fv_cand in_scope acc =
+  tyCoVarsOfCoAcc co fv_cand in_scope acc
+tyCoVarsOfCoAcc (TransCo co1 co2) fv_cand in_scope acc =
+  (tyCoVarsOfCoAcc co1 `unionFV` tyCoVarsOfCoAcc co2) fv_cand in_scope acc
+tyCoVarsOfCoAcc (NthCo _ co) fv_cand in_scope acc =
+  tyCoVarsOfCoAcc co fv_cand in_scope acc
+tyCoVarsOfCoAcc (LRCo _ co) fv_cand in_scope acc =
+  tyCoVarsOfCoAcc co fv_cand in_scope acc
+tyCoVarsOfCoAcc (InstCo co ty) fv_cand in_scope acc =
+  (tyCoVarsOfCoAcc co `unionFV` tyVarsOfTypeAcc ty) fv_cand in_scope acc
+tyCoVarsOfCoAcc (SubCo co) fv_cand in_scope acc =
+  tyCoVarsOfCoAcc co fv_cand in_scope acc
+tyCoVarsOfCoAcc (AxiomRuleCo _ ts cs) fv_cand in_scope acc =
+  (tyVarsOfTypesAcc ts `unionFV` tyCoVarsOfCosAcc cs) fv_cand in_scope acc
+
+tyCoVarsOfCosAcc :: [Coercion] -> FV
+tyCoVarsOfCosAcc (co:cos) fv_cand in_scope acc =
+  (tyCoVarsOfCoAcc co `unionFV` tyCoVarsOfCosAcc cos) fv_cand in_scope acc
+tyCoVarsOfCosAcc [] fv_cand in_scope acc = noVars fv_cand in_scope acc
 
 coVarsOfCo :: Coercion -> VarSet
 -- Extract *coerction* variables only.  Tiresome to repeat the code, but easy.
index 574e153..3eac8b5 100644 (file)
@@ -43,6 +43,7 @@ module TypeRep (
 
         -- Free variables
         tyVarsOfType, tyVarsOfTypes, closeOverKinds, varSetElemsKvsFirst,
+        tyVarsOfTypeAcc, tyVarsOfTypeList, tyVarsOfTypesAcc, tyVarsOfTypesList,
 
         -- * Tidying type related things up for printing
         tidyType,      tidyTypes,
@@ -73,6 +74,7 @@ import BasicTypes
 import TyCon
 import Class
 import CoAxiom
+import FV
 
 -- others
 import PrelNames
@@ -309,16 +311,43 @@ isKindVar v = isTKVar v && isSuperKind (varType v)
 tyVarsOfType :: Type -> VarSet
 -- ^ NB: for type synonyms tyVarsOfType does /not/ expand the synonym
 -- tyVarsOfType returns free variables of a type, including kind variables.
-tyVarsOfType (TyVarTy v)         = unitVarSet v
-tyVarsOfType (TyConApp _ tys)    = tyVarsOfTypes tys
-tyVarsOfType (LitTy {})          = emptyVarSet
-tyVarsOfType (FunTy arg res)     = tyVarsOfType arg `unionVarSet` tyVarsOfType res
-tyVarsOfType (AppTy fun arg)     = tyVarsOfType fun `unionVarSet` tyVarsOfType arg
-tyVarsOfType (ForAllTy tyvar ty) = delVarSet (tyVarsOfType ty) tyvar
-                                   `unionVarSet` tyVarsOfType (tyVarKind tyvar)
+tyVarsOfType ty = runFVSet $ tyVarsOfTypeAcc ty
+
+-- | `tyVarsOfType` that returns free variables of a type in deterministic
+-- order. For explanation of why using `VarSet` is not deterministic see
+-- Note [Deterministic UniqFM] in UniqDFM.
+tyVarsOfTypeList :: Type -> [Var]
+tyVarsOfTypeList ty = runFVList $ tyVarsOfTypeAcc ty
 
 tyVarsOfTypes :: [Type] -> TyVarSet
-tyVarsOfTypes = mapUnionVarSet tyVarsOfType
+tyVarsOfTypes tys = runFVSet $ tyVarsOfTypesAcc tys
+
+tyVarsOfTypesList :: [Type] -> [Var]
+tyVarsOfTypesList tys = runFVList $ tyVarsOfTypesAcc tys
+
+
+-- | The worker for `tyVarsOfType` and `tyVarsOfTypeList`.
+-- The previous implementation used `unionVarSet` which is O(n+m) and can
+-- make the function quadratic.
+-- It's exported, so that it can be composed with other functions that compute
+-- free variables.
+tyVarsOfTypeAcc :: Type -> FV
+tyVarsOfTypeAcc (TyVarTy v) fv_cand in_scope acc = oneVar v fv_cand in_scope acc
+tyVarsOfTypeAcc (TyConApp _ tys) fv_cand in_scope acc =
+  tyVarsOfTypesAcc tys fv_cand in_scope acc
+tyVarsOfTypeAcc (LitTy {}) fv_cand in_scope acc = noVars fv_cand in_scope acc
+tyVarsOfTypeAcc (FunTy arg res) fv_cand in_scope acc =
+  (tyVarsOfTypeAcc arg `unionFV` tyVarsOfTypeAcc res) fv_cand in_scope acc
+tyVarsOfTypeAcc (AppTy fun arg) fv_cand in_scope acc =
+  (tyVarsOfTypeAcc fun `unionFV` tyVarsOfTypeAcc arg) fv_cand in_scope acc
+tyVarsOfTypeAcc (ForAllTy tyvar ty) fv_cand in_scope acc =
+  (delFV tyvar (tyVarsOfTypeAcc ty) `unionFV`
+    tyVarsOfTypeAcc (tyVarKind tyvar)) fv_cand in_scope acc
+
+tyVarsOfTypesAcc :: [Type] -> FV
+tyVarsOfTypesAcc (ty:tys) fv_cand in_scope acc =
+  (tyVarsOfTypeAcc ty `unionFV` tyVarsOfTypesAcc tys) fv_cand in_scope acc
+tyVarsOfTypesAcc [] fv_cand in_scope acc = noVars fv_cand in_scope acc
 
 closeOverKinds :: TyVarSet -> TyVarSet
 -- Add the kind variables free in the kinds
@@ -934,7 +963,7 @@ tidyOpenType :: TidyEnv -> Type -> (TidyEnv, Type)
 tidyOpenType env ty
   = (env', tidyType (trimmed_occ_env, var_env) ty)
   where
-    (env'@(_, var_env), tvs') = tidyOpenTyVars env (varSetElems (tyVarsOfType ty))
+    (env'@(_, var_env), tvs') = tidyOpenTyVars env (tyVarsOfTypeList ty)
     trimmed_occ_env = initTidyOccEnv (map getOccName tvs')
       -- The idea here was that we restrict the new TidyEnv to the
       -- _free_ vars of the type, so that we don't gratuitously rename
index a29c85f..e876b2e 100644 (file)
@@ -176,7 +176,7 @@ match menv subst (TyVarTy tv1) ty2
     else Nothing        -- ty2 doesn't match
 
   | tv1' `elemVarSet` me_tmpls menv
-  = if any (inRnEnvR rn_env) (varSetElems (tyVarsOfType ty2))
+  = if any (inRnEnvR rn_env) (tyVarsOfTypeList ty2)
     then Nothing        -- Occurs check
                         -- ezyang: Is this really an occurs check?  It seems
                         -- to just reject matching \x. A against \x. x (maintaining
diff --git a/compiler/utils/FV.hs b/compiler/utils/FV.hs
new file mode 100644 (file)
index 0000000..907a20f
--- /dev/null
@@ -0,0 +1,87 @@
+{-
+(c) Bartosz Nitka, Facebook 2015
+
+Utilities for efficiently and deterministically computing free variables.
+
+-}
+
+{-# LANGUAGE BangPatterns #-}
+
+module FV (
+        -- * Deterministic free vars computations
+        FV, InterestingVarFun,
+
+        -- * Running the computations
+        runFV, runFVList, runFVSet, runFVDSet,
+
+        -- ** Manipulating those computations
+        oneVar,
+        noVars,
+        unionFV,
+        delFV,
+        delFVs,
+        filterFV,
+    ) where
+
+import Var
+import VarSet
+
+-- | Predicate on possible free variables: returns @True@ iff the variable is
+-- interesting
+type InterestingVarFun = Var -> Bool
+
+type FV = InterestingVarFun
+          -> VarSet
+             -- Locally bound variables
+          -> ([Var], VarSet)
+             -- List to preserve ordering and set to check for membership,
+             -- so that the list doesn't have duplicates
+             -- For explanation of why using `VarSet` is not deterministic see
+             -- Note [Deterministic UniqFM] in UniqDFM.
+          -> ([Var], VarSet)
+
+runFV :: FV ->  ([Var], VarSet)
+runFV fv = fv (const True) emptyVarSet ([], emptyVarSet)
+
+runFVList :: FV -> [Var]
+runFVList = fst . runFV
+
+runFVDSet :: FV -> DVarSet
+runFVDSet = mkDVarSet . fst . runFV
+
+runFVSet :: FV -> VarSet
+runFVSet = snd . runFV
+
+{-# INLINE oneVar #-}
+oneVar :: Id -> FV
+oneVar var fv_cand in_scope acc@(have, haveSet)
+  = {- ASSERT( isId var ) probably not going to work -} fvs
+  where
+  fvs | var `elemVarSet` in_scope = acc
+      | var `elemVarSet` haveSet = acc
+      | fv_cand var = (var:have, extendVarSet haveSet var)
+      | otherwise = acc
+
+{-# INLINE noVars #-}
+noVars :: FV
+noVars _ _ acc = acc
+
+{-# INLINE unionFV #-}
+unionFV :: FV -> FV -> FV
+unionFV fv1 fv2 fv_cand in_scope acc =
+  fv1 fv_cand in_scope $! fv2 fv_cand in_scope $! acc
+
+{-# INLINE delFV #-}
+delFV :: Var -> FV -> FV
+delFV var fv fv_cand !in_scope acc =
+  fv fv_cand (extendVarSet in_scope var) acc
+
+{-# INLINE delFVs #-}
+delFVs :: VarSet -> FV -> FV
+delFVs vars fv fv_cand !in_scope acc =
+  fv fv_cand (in_scope `unionVarSet` vars) acc
+
+{-# INLINE filterFV #-}
+filterFV :: InterestingVarFun -> FV -> FV
+filterFV fv_cand2 fv fv_cand1 in_scope acc =
+  fv (\v -> fv_cand1 v && fv_cand2 v) in_scope acc
index ae7483a..83c8710 100644 (file)
@@ -8,7 +8,7 @@ module Vectorise.Exp
   , vectTopExprs
   , vectScalarFun
   , vectScalarDFun
-  ) 
+  )
 where
 
 #include "HsVersions.h"
@@ -44,6 +44,7 @@ import Outputable
 import FastString
 import DynFlags
 import Util
+import UniqDFM (udfmToUfm)
 #if __GLASGOW_HASKELL__ < 709
 import MonadUtils
 #endif
@@ -118,9 +119,9 @@ vectTopExprs binds
     }
   where
     (vars, exprs) = unzip binds
-    
+
     vectAvoidAndEncapsulate pvs = encapsulateScalars <=< vectAvoidInfo pvs . freeVars
-    
+
     vect var exprVI
       = do
         { vExpr  <- closedV $
@@ -180,17 +181,17 @@ encapsulateScalars ((fvs, vi), AnnTick tck expr)
     { encExpr <- encapsulateScalars expr
     ; return ((fvs, vi), AnnTick tck encExpr)
     }
-encapsulateScalars ce@((fvs, vi), AnnLam bndr expr) 
-  = do 
+encapsulateScalars ce@((fvs, vi), AnnLam bndr expr)
+  = do
     { vectAvoid <- isVectAvoidanceAggressive
-    ; varsS     <- allScalarVarTypeSet fvs 
+    ; varsS     <- allScalarVarTypeSet fvs
         -- NB: diverts from the paper: we need to check the scalarness of bound variables as well,
         --     as 'vectScalarFun' will handle them just the same as those introduced for the 'fvs'
         --     by encapsulation.
     ; bndrsS    <- allScalarVarType bndrs
     ; case (vi, vectAvoid && varsS && bndrsS) of
         (VISimple, True) -> liftSimpleAndCase ce
-        _                -> do 
+        _                -> do
                             { encExpr <- encapsulateScalars expr
                             ; return ((fvs, vi), AnnLam bndr encExpr)
                             }
@@ -203,7 +204,7 @@ encapsulateScalars ce@((fvs, vi), AnnApp ce1 ce2)
     ; varsS     <- allScalarVarTypeSet fvs
     ; case (vi, (vectAvoid || isSimpleApplication ce) && varsS) of
         (VISimple, True) -> liftSimpleAndCase ce
-        _                -> do 
+        _                -> do
                             { encCe1 <- encapsulateScalars ce1
                             ; encCe2 <- encapsulateScalars ce2
                             ; return ((fvs, vi), AnnApp encCe1 encCe2)
@@ -224,13 +225,13 @@ encapsulateScalars ce@((fvs, vi), AnnApp ce1 ce2)
     isSimple (_, AnnTick _ ce) = isSimple ce
     isSimple (_, AnnCast ce _) = isSimple ce
     isSimple _                 = False
-encapsulateScalars ce@((fvs, vi), AnnCase scrut bndr ty alts) 
-  = do 
+encapsulateScalars ce@((fvs, vi), AnnCase scrut bndr ty alts)
+  = do
     { vectAvoid <- isVectAvoidanceAggressive
-    ; varsS     <- allScalarVarTypeSet fvs 
+    ; varsS     <- allScalarVarTypeSet fvs
     ; case (vi, vectAvoid && varsS) of
         (VISimple, True) -> liftSimpleAndCase ce
-        _                -> do 
+        _                -> do
                             { encScrut <- encapsulateScalars scrut
                             ; encAlts  <- mapM encAlt alts
                             ; return ((fvs, vi), AnnCase encScrut bndr ty encAlts)
@@ -238,34 +239,34 @@ encapsulateScalars ce@((fvs, vi), AnnCase scrut bndr ty alts)
     }
   where
     encAlt (con, bndrs, expr) = (con, bndrs,) <$> encapsulateScalars expr
-encapsulateScalars ce@((fvs, vi), AnnLet (AnnNonRec bndr expr1) expr2) 
-  = do 
+encapsulateScalars ce@((fvs, vi), AnnLet (AnnNonRec bndr expr1) expr2)
+  = do
     { vectAvoid <- isVectAvoidanceAggressive
-    ; varsS     <- allScalarVarTypeSet fvs 
+    ; varsS     <- allScalarVarTypeSet fvs
     ; case (vi, vectAvoid && varsS) of
         (VISimple, True) -> liftSimpleAndCase ce
-        _                -> do 
+        _                -> do
                             { encExpr1 <- encapsulateScalars expr1
                             ; encExpr2 <- encapsulateScalars expr2
                             ; return ((fvs, vi), AnnLet (AnnNonRec bndr encExpr1) encExpr2)
                             }
     }
-encapsulateScalars ce@((fvs, vi), AnnLet (AnnRec binds) expr) 
-  = do 
+encapsulateScalars ce@((fvs, vi), AnnLet (AnnRec binds) expr)
+  = do
     { vectAvoid <- isVectAvoidanceAggressive
-    ; varsS     <- allScalarVarTypeSet fvs 
-    ; case (vi, vectAvoid && varsS) of 
+    ; varsS     <- allScalarVarTypeSet fvs
+    ; case (vi, vectAvoid && varsS) of
         (VISimple, True) -> liftSimpleAndCase ce
-        _                -> do 
+        _                -> do
                             { encBinds <- mapM encBind binds
                             ; encExpr  <- encapsulateScalars expr
                             ; return ((fvs, vi), AnnLet (AnnRec encBinds) encExpr)
                             }
-    }                            
+    }
  where
    encBind (bndr, expr) = (bndr,) <$> encapsulateScalars expr
 encapsulateScalars ((fvs, vi), AnnCast expr coercion)
-  = do 
+  = do
     { encExpr <- encapsulateScalars expr
     ; return ((fvs, vi), AnnCast encExpr coercion)
     }
@@ -296,8 +297,8 @@ liftSimple ((fvs, vi), AnnVar v)
   | v `elemVarSet` fvs                -- special case to avoid producing: (\v -> v) v
   && not (isToplevel v)               --   NB: if 'v' not free or is toplevel, we must get the 'VIEncaps'
   = return $ ((fvs, vi), AnnVar v)
-liftSimple aexpr@((fvs_orig, VISimple), expr) 
-  = do 
+liftSimple aexpr@((fvs_orig, VISimple), expr)
+  = do
     { let liftedExpr = mkAnnApps (mkAnnLams (reverse vars) fvs expr) vars
 
     ; traceVt "encapsulate:" $ ppr (deAnnotate aexpr) $$ text "==>" $$ ppr (deAnnotate liftedExpr)
@@ -307,18 +308,18 @@ liftSimple aexpr@((fvs_orig, VISimple), expr)
   where
     vars = varSetElems fvs
     fvs  = filterVarSet (not . isToplevel) fvs_orig -- only include 'Id's that are not toplevel
-    
+
     mkAnnLams :: [Var] -> VarSet -> AnnExpr' Var (VarSet, VectAvoidInfo) -> CoreExprWithVectInfo
     mkAnnLams []     fvs expr = ASSERT(isEmptyVarSet fvs)
                                 ((emptyVarSet, VIEncaps), expr)
     mkAnnLams (v:vs) fvs expr = mkAnnLams vs (fvs `delVarSet` v) (AnnLam v ((fvs, VIEncaps), expr))
-      
+
     mkAnnApps :: CoreExprWithVectInfo -> [Var] -> CoreExprWithVectInfo
     mkAnnApps aexpr []     = aexpr
     mkAnnApps aexpr (v:vs) = mkAnnApps (mkAnnApp aexpr v) vs
 
     mkAnnApp :: CoreExprWithVectInfo -> Var -> CoreExprWithVectInfo
-    mkAnnApp aexpr@((fvs, _vi), _expr) v 
+    mkAnnApp aexpr@((fvs, _vi), _expr) v
       = ((fvs `extendVarSet` v, VISimple), AnnApp aexpr ((unitVarSet v, VISimple), AnnVar v))
 liftSimple aexpr
   = pprPanic "Vectorise.Exp.liftSimple: not simple" $ ppr (deAnnotate aexpr)
@@ -327,8 +328,8 @@ isToplevel :: Var -> Bool
 isToplevel v | isId v    = case realIdUnfolding v of
                              NoUnfolding                     -> False
                              OtherCon      {}                -> True
-                             DFunUnfolding {}                -> True 
-                             CoreUnfolding {uf_is_top = top} -> top 
+                             DFunUnfolding {}                -> True
+                             CoreUnfolding {uf_is_top = top} -> top
              | otherwise = False
 
 -- |Vectorise an expression.
@@ -341,7 +342,7 @@ vectExpr aexpr
   = vectFnExpr True False aexpr
     -- encapsulated constant => vectorise as a scalar constant
   | isVIEncaps aexpr
-  = traceVt "vectExpr (encapsulated constant):" (ppr . deAnnotate $ aexpr) >> 
+  = traceVt "vectExpr (encapsulated constant):" (ppr . deAnnotate $ aexpr) >>
     vectConst (deAnnotate aexpr)
 
 vectExpr (_, AnnVar v)
@@ -351,7 +352,7 @@ vectExpr (_, AnnLit lit)
   = vectConst $ Lit lit
 
 vectExpr aexpr@(_, AnnLam _ _)
-  = traceVt "vectExpr [AnnLam]:" (ppr . deAnnotate $ aexpr) >> 
+  = traceVt "vectExpr [AnnLam]:" (ppr . deAnnotate $ aexpr) >>
     vectFnExpr True False aexpr
 
   -- SPECIAL CASE: Vectorise/lift 'patError @ ty err' by only vectorising/lifting the type 'ty';
@@ -360,7 +361,7 @@ vectExpr aexpr@(_, AnnLam _ _)
 -- FIXME: can't be do this with a VECTORISE pragma on 'pAT_ERROR_ID' now?
 vectExpr (_, AnnApp (_, AnnApp (_, AnnVar v) (_, AnnType ty)) err)
   | v == pAT_ERROR_ID
-  = do 
+  = do
     { (vty, lty) <- vectAndLiftType ty
     ; return (mkCoreApps (Var v) [Type vty, err'], mkCoreApps (Var v) [Type lty, err'])
     }
@@ -387,9 +388,9 @@ vectExpr e@(_, AnnApp fn arg)
   | isPredTy arg_ty   -- dictionary application (whose result is not a dictionary)
   = vectPolyApp e
   | otherwise         -- user value
-  = do 
+  = do
     {   -- vectorise the types
-    ; varg_ty <- vectType arg_ty 
+    ; varg_ty <- vectType arg_ty
     ; vres_ty <- vectType res_ty
 
         -- vectorise the function and argument expression
@@ -406,10 +407,10 @@ vectExpr (_, AnnCase scrut bndr ty alts)
   | Just (tycon, ty_args) <- splitTyConApp_maybe scrut_ty
   , isAlgTyCon tycon
   = vectAlgCase tycon ty_args scrut bndr ty alts
-  | otherwise 
-  = do 
+  | otherwise
+  = do
     { dflags <- getDynFlags
-    ; cantVectorise dflags "Can't vectorise expression (no algebraic type constructor)" $ 
+    ; cantVectorise dflags "Can't vectorise expression (no algebraic type constructor)" $
         ppr scrut_ty
     }
   where
@@ -418,8 +419,8 @@ vectExpr (_, AnnCase scrut bndr ty alts)
 vectExpr (_, AnnLet (AnnNonRec bndr rhs) body)
   = do
     { traceVt "let binding (non-recursive)" Outputable.empty
-    ; vrhs <- localV $ 
-                inBind bndr $ 
+    ; vrhs <- localV $
+                inBind bndr $
                   vectAnnPolyExpr False rhs
     ; traceVt "let body (non-recursive)" Outputable.empty
     ; (vbndr, vbody) <- vectBndrIn bndr (vectExpr body)
@@ -433,7 +434,7 @@ vectExpr (_, AnnLet (AnnRec bs) body)
                                   ; vrhss <- zipWithM vect_rhs bndrs rhss
                                   ; traceVt "let body (recursive)" Outputable.empty
                                   ; vbody <- vectExpr body
-                                  ; return (vrhss, vbody) 
+                                  ; return (vrhss, vbody)
                                   }
     ; return $ vLet (vRec vbndrs vrhss) vbody
     }
@@ -451,7 +452,7 @@ vectExpr (_, AnnType ty)
   = vType <$> vectType ty
 
 vectExpr e
-  = do 
+  = do
     { dflags <- getDynFlags
     ; cantVectorise dflags "Can't vectorise expression (vectExpr)" $ ppr (deAnnotate e)
     }
@@ -473,7 +474,7 @@ vectFnExpr inline loop_breaker aexpr@(_ann, AnnLam bndr body)
     -- predicate abstraction: leave as a normal abstraction, but vectorise the predicate type
   | isId bndr
     && isPredTy (idType bndr)
-  = do 
+  = do
     { vBndr <- vectBndr bndr
     ; vbody <- vectFnExpr inline loop_breaker body
     ; return $ mapVect (mkLams [vectorised vBndr]) vbody
@@ -484,10 +485,10 @@ vectFnExpr inline loop_breaker aexpr@(_ann, AnnLam bndr body)
     -- non-predicate abstraction: vectorise as a non-scalar computation
   | isId bndr
   = vectLam inline loop_breaker aexpr
-  | otherwise 
-  = do 
+  | otherwise
+  = do
     { dflags <- getDynFlags
-    ; cantVectorise dflags "Vectorise.Exp.vectFnExpr: Unexpected type lambda" $ 
+    ; cantVectorise dflags "Vectorise.Exp.vectFnExpr: Unexpected type lambda" $
         ppr (deAnnotate aexpr)
     }
 vectFnExpr _ _ aexpr
@@ -522,7 +523,7 @@ vectPolyApp e0
               ; vDictsInner <- mapM vectDictExpr (map deAnnotate dictsInner)
               ; vTysOuter   <- mapM vectType     tysOuter
               ; vTysInner   <- mapM vectType     tysInner
-              
+
               ; let reconstructOuter v = (`mkApps` vDictsOuter) <$> polyApply v vTysOuter
 
               ; case vVar of
@@ -537,10 +538,10 @@ vectPolyApp e0
                               -- arguments are non-vectorised arguments, where no 'PA'dictionaries
                               -- are needed for the type variables
                           ; ve <- if null dictsInner
-                                  then 
+                                  then
                                     return $ Var vv `mkTyApps` vTysOuter `mkApps` vDictsOuter
-                                  else 
-                                    reconstructOuter 
+                                  else
+                                    reconstructOuter
                                       (Var vv `mkTyApps` vTysInner `mkApps` vDictsInner)
                           ; traceVt "  GLOBAL (dict):" (ppr ve)
                           ; vectConst ve
@@ -561,8 +562,8 @@ vectPolyApp e0
     (e4, tysInner)   = collectAnnTypeArgs e3
     --
     isDictComp var = (isJust . isClassOpId_maybe $ var) || isDFunId var
-    
--- |Vectorise the body of a dfun.  
+
+-- |Vectorise the body of a dfun.
 --
 -- Dictionary computations are special for the following reasons.  The application of dictionary
 -- functions are always saturated, so there is no need to create closures.  Dictionary computations
@@ -622,16 +623,16 @@ vectDictExpr (Coercion coe)
 -- "Note [Scalar dfuns]" in 'Vectorise'.
 --
 vectScalarFun :: CoreExpr -> VM VExpr
-vectScalarFun expr 
-  = do 
-    { traceVt "vectScalarFun:" (ppr expr) 
+vectScalarFun expr
+  = do
+    { traceVt "vectScalarFun:" (ppr expr)
     ; let (arg_tys, res_ty) = splitFunTys (exprType expr)
     ; mkScalarFun arg_tys res_ty expr
     }
 
 -- Generate code for a scalar function by generating a scalar closure.  If the function is a
 -- dictionary function, vectorise it as dictionary code.
--- 
+--
 mkScalarFun :: [Type] -> Type -> CoreExpr -> VM VExpr
 mkScalarFun arg_tys res_ty expr
   | isPredTy res_ty
@@ -652,7 +653,7 @@ mkScalarFun arg_tys res_ty expr
     unused = error "Vectorise.Exp.mkScalarFun: we don't lift dictionary expressions"
 
 -- |Vectorise a dictionary function that has a 'VECTORISE SCALAR instance' pragma.
--- 
+--
 -- In other words, all methods in that dictionary are scalar functions — to be vectorised with
 -- 'vectScalarFun'.  The dictionary "function" itself may be a constant, though.
 --
@@ -675,7 +676,7 @@ mkScalarFun arg_tys res_ty expr
 --
 -- > $v$dEqPair :: forall a b. V:Eq a -> V:Eq b -> V:Eq (a, b)
 -- > $v$dEqPair = /\a b -> \dEqa :: V:Eq a -> \dEqb :: V:Eq b ->
--- >                D:V:Eq $(vectScalarFun True recFns 
+-- >                D:V:Eq $(vectScalarFun True recFns
 -- >                         [| (==) @(a, b) ($dEqPair @a @b $(unVect dEqa) $(unVect dEqb)) |])
 --
 -- NB:
@@ -693,7 +694,7 @@ vectScalarDFun var
        ; vTheta     <- mapM vectType theta
        ; vThetaBndr <- mapM (newLocalVar (fsLit "vd")) vTheta
        ; let vThetaVars = varsToCoreExprs vThetaBndr
-       
+
            -- vectorise superclass dictionaries and methods as scalar expressions
        ; thetaVars  <- mapM (newLocalVar (fsLit "d")) theta
        ; thetaExprs <- zipWithM unVectDict theta vThetaVars
@@ -730,7 +731,7 @@ vectScalarDFun var
 -- where 'opTyi' is the type of the i-th superclass or op of the unvectorised dictionary.
 --
 unVectDict :: Type -> CoreExpr -> VM CoreExpr
-unVectDict ty e 
+unVectDict ty e
   = do { vTys <- mapM vectType tys
        ; let meths = map (\sel -> Var sel `mkTyApps` vTys `mkApps` [e]) selIds
        ; scOps <- zipWithM fromVect methTys meths
@@ -755,7 +756,7 @@ vectLam :: Bool                 -- ^ Should the RHS of a binding be inlined?
         -> VM VExpr
 vectLam inline loop_breaker expr@((fvs, _vi), AnnLam _ _)
  = do { traceVt "fully vectorise a lambda expression" (ppr . deAnnotate $ expr)
+
       ; let (bndrs, body) = collectAnnValBinders expr
 
           -- grab the in-scope type variables
@@ -763,7 +764,7 @@ vectLam inline loop_breaker expr@((fvs, _vi), AnnLam _ _)
 
           -- collect and vectorise all /local/ free variables
       ; vfvs <- readLEnv $ \env ->
-                  [ (var, fromJust mb_vv) 
+                  [ (var, fromJust mb_vv)
                   | var <- varSetElems fvs
                   , let mb_vv = lookupVarEnv (local_vars env) var
                   , isJust mb_vv         -- its local == is in local var env
@@ -827,7 +828,7 @@ vectLam _ _ _ = panic "Vectorise.Exp.vectLam: not a lambda"
 --
 
 -- FIXME: this is too lazy...is it?
-vectAlgCase :: TyCon -> [Type] -> CoreExprWithVectInfo -> Var -> Type  
+vectAlgCase :: TyCon -> [Type] -> CoreExprWithVectInfo -> Var -> Type
             -> [(AltCon, [Var], CoreExprWithVectInfo)]
             -> VM VExpr
 vectAlgCase _tycon _ty_args scrut bndr ty [(DEFAULT, [], body)]
@@ -873,7 +874,7 @@ vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt dc, bndrs, body)]
 
     mk_wild_case expr ty dc bndrs body
       = mkWildCase expr (exprType expr) ty [(DataAlt dc, bndrs, body)]
-      
+
     dataConErr = (text "vectAlgCase: data constructor not vectorised" <+> ppr dc)
 
 vectAlgCase tycon _ty_args scrut bndr ty alts
@@ -977,7 +978,7 @@ vectAlgCase tycon _ty_args scrut bndr ty alts
               }
             _ -> return []
         }
-   
+
 
 -- Support to compute information for vectorisation avoidance ------------------
 
@@ -1039,7 +1040,7 @@ unlessVIParrExpr e1 e2 = e1 `unlessVIParr` vectAvoidInfoOf e2
 --
 vectAvoidInfo :: VarSet -> CoreExprWithFVs -> VM CoreExprWithVectInfo
 vectAvoidInfo pvs ce@(fvs, AnnVar v)
-  = do 
+  = do
     { gpvs <- globalParallelVars
     ; vi <- if v `elemVarSet` pvs || v `elemVarSet` gpvs
             then return VIParr
@@ -1049,37 +1050,37 @@ vectAvoidInfo pvs ce@(fvs, AnnVar v)
         traceVt "  reason:" $ if v `elemVarSet` pvs  then text "local"  else
                               if v `elemVarSet` gpvs then text "global" else text "parallel type"
 
-    ; return ((fvs, vi), AnnVar v)
+    ; return ((udfmToUfm fvs, vi), AnnVar v)
     }
 
 vectAvoidInfo _pvs ce@(fvs, AnnLit lit)
-  = do 
-    { vi <- vectAvoidInfoTypeOf ce  
-    ; viTrace ce vi [] 
-    ; return ((fvs, vi), AnnLit lit)
+  = do
+    { vi <- vectAvoidInfoTypeOf ce
+    ; viTrace ce vi []
+    ; return ((udfmToUfm fvs, vi), AnnLit lit)
     }
 
 vectAvoidInfo pvs ce@(fvs, AnnApp e1 e2)
-  = do 
+  = do
     { ceVI <- vectAvoidInfoTypeOf ce
-    ; eVI1 <- vectAvoidInfo pvs e1  
+    ; eVI1 <- vectAvoidInfo pvs e1
     ; eVI2 <- vectAvoidInfo pvs e2
     ; let vi = ceVI `unlessVIParrExpr` eVI1 `unlessVIParrExpr` eVI2
-    -- ; viTrace ce vi [eVI1, eVI2]                     
-    ; return ((fvs, vi), AnnApp eVI1 eVI2)
+    -- ; viTrace ce vi [eVI1, eVI2]
+    ; return ((udfmToUfm fvs, vi), AnnApp eVI1 eVI2)
     }
 
 vectAvoidInfo pvs (fvs, AnnLam var body)
-  = do 
-    { bodyVI <- vectAvoidInfo pvs body 
+  = do
+    { bodyVI <- vectAvoidInfo pvs body
     ; varVI  <- vectAvoidInfoType $ varType var
     ; let vi = vectAvoidInfoOf bodyVI `unlessVIParr` varVI
     -- ; viTrace ce vi [bodyVI]
-    ; return ((fvs, vi), AnnLam var bodyVI)
+    ; return ((udfmToUfm fvs, vi), AnnLam var bodyVI)
     }
 
-vectAvoidInfo pvs ce@(fvs, AnnLet (AnnNonRec var e) body)  
-  = do 
+vectAvoidInfo pvs ce@(fvs, AnnLet (AnnNonRec var e) body)
+  = do
     { ceVI       <- vectAvoidInfoTypeOf ce
     ; eVI        <- vectAvoidInfo pvs e
     ; isScalarTy <- isScalar $ varType var
@@ -1093,11 +1094,11 @@ vectAvoidInfo pvs ce@(fvs, AnnLet (AnnNonRec var e) body)
         ; return (bodyVI, ceVI `unlessVIParrExpr` bodyVI)
         }
     -- ; viTrace ce vi [eVI, bodyVI]
-    ; return ((fvs, vi), AnnLet (AnnNonRec var eVI) bodyVI)
+    ; return ((udfmToUfm fvs, vi), AnnLet (AnnNonRec var eVI) bodyVI)
     }
 
-vectAvoidInfo pvs ce@(fvs, AnnLet (AnnRec bnds) body)  
-  = do 
+vectAvoidInfo pvs ce@(fvs, AnnLet (AnnRec bnds) body)
+  = do
     { ceVI         <- vectAvoidInfoTypeOf ce
     ; bndsVI       <- mapM (vectAvoidInfoBnd pvs) bnds
     ; parrBndrs    <- map fst <$> filterM isVIParrBnd bndsVI
@@ -1108,36 +1109,36 @@ vectAvoidInfo pvs ce@(fvs, AnnLet (AnnRec bnds) body)
         ; bndsVI <- mapM (vectAvoidInfoBnd extendedPvs) bnds
         ; bodyVI <- vectAvoidInfo extendedPvs body
         -- ; viTrace ce VIParr (map snd bndsVI ++ [bodyVI])
-        ; return ((fvs, VIParr), AnnLet (AnnRec bndsVI) bodyVI)
+        ; return ((udfmToUfm fvs, VIParr), AnnLet (AnnRec bndsVI) bodyVI)
         }
       else do         -- demanded bindings cannot trigger parallelism
         { bodyVI <- vectAvoidInfo pvs body
         ; let vi = ceVI `unlessVIParrExpr` bodyVI
         -- ; viTrace ce vi (map snd bndsVI ++ [bodyVI])
-        ; return ((fvs, vi), AnnLet (AnnRec bndsVI) bodyVI)          
+        ; return ((udfmToUfm fvs, vi), AnnLet (AnnRec bndsVI) bodyVI)
         }
     }
   where
     vectAvoidInfoBnd pvs (var, e) = (var,) <$> vectAvoidInfo pvs e
 
-    isVIParrBnd (var, eVI) 
-      = do 
+    isVIParrBnd (var, eVI)
+      = do
         { isScalarTy <- isScalar (varType var)
         ; return $ isVIParr eVI && not isScalarTy
         }
 
-vectAvoidInfo pvs ce@(fvs, AnnCase e var ty alts) 
-  = do 
+vectAvoidInfo pvs ce@(fvs, AnnCase e var ty alts)
+  = do
     { ceVI           <- vectAvoidInfoTypeOf ce
     ; eVI            <- vectAvoidInfo pvs e
     ; altsVI         <- mapM (vectAvoidInfoAlt (isVIParr eVI)) alts
     ; let alteVIs = [eVI | (_, _, eVI) <- altsVI]
           vi      =  foldl unlessVIParrExpr ceVI (eVI:alteVIs)  -- NB: same effect as in the paper
     -- ; viTrace ce vi (eVI : alteVIs)
-    ; return ((fvs, vi), AnnCase eVI var ty altsVI)
+    ; return ((udfmToUfm fvs, vi), AnnCase eVI var ty altsVI)
     }
   where
-    vectAvoidInfoAlt scrutIsPar (con, bndrs, e) 
+    vectAvoidInfoAlt scrutIsPar (con, bndrs, e)
       = do
         { allScalar <- allScalarVarType bndrs
         ; let altPvs | scrutIsPar && not allScalar = pvs `extendVarSetList` bndrs
@@ -1146,26 +1147,27 @@ vectAvoidInfo pvs ce@(fvs, AnnCase e var ty alts)
         }
 
 vectAvoidInfo pvs (fvs, AnnCast e (fvs_ann, ann))
-  = do 
+  = do
     { eVI <- vectAvoidInfo pvs e
-    ; return ((fvs, vectAvoidInfoOf eVI), AnnCast eVI ((fvs_ann, VISimple), ann))
+    ; return ((udfmToUfm fvs, vectAvoidInfoOf eVI)
+             , AnnCast eVI ((udfmToUfm fvs_ann, VISimple), ann))
     }
 
 vectAvoidInfo pvs (fvs, AnnTick tick e)
-  = do 
+  = do
     { eVI <- vectAvoidInfo pvs e
-    ; return ((fvs, vectAvoidInfoOf eVI), AnnTick tick eVI)
+    ; return ((udfmToUfm fvs, vectAvoidInfoOf eVI), AnnTick tick eVI)
     }
 
 vectAvoidInfo _pvs (fvs, AnnType ty)
-  = return ((fvs, VISimple), AnnType ty)
+  = return ((udfmToUfm fvs, VISimple), AnnType ty)
 
-vectAvoidInfo _pvs (fvs, AnnCoercion coe) 
-  = return ((fvs, VISimple), AnnCoercion coe)
+vectAvoidInfo _pvs (fvs, AnnCoercion coe)
+  = return ((udfmToUfm fvs, VISimple), AnnCoercion coe)
 
 -- Compute vectorisation avoidance information for a type.
 --
-vectAvoidInfoType :: Type -> VM VectAvoidInfo   
+vectAvoidInfoType :: Type -> VM VectAvoidInfo
 vectAvoidInfoType ty
   | isPredTy ty
   = return VIDict
@@ -1183,9 +1185,9 @@ vectAvoidInfoType ty
     { parr <- maybeParrTy ty
     ; if parr
       then return VIParr
-      else do 
+      else do
     { scalar <- isScalar ty
-    ; if scalar 
+    ; if scalar
       then return VISimple
       else return VIComplex
     } }
@@ -1198,16 +1200,16 @@ vectAvoidInfoTypeOf = vectAvoidInfoType . annExprType
 -- Checks whether the type might be a parallel array type.
 --
 maybeParrTy :: Type -> VM Bool
-maybeParrTy ty 
+maybeParrTy ty
     -- looking through newtypes
   | Just ty'      <- coreView ty
   = (== VIParr) <$> vectAvoidInfoType ty'
     -- decompose constructor applications
-  | Just (tc, ts) <- splitTyConApp_maybe ty 
+  | Just (tc, ts) <- splitTyConApp_maybe ty
   = do
     { isParallel <- (tyConName tc `elemNameSet`) <$> globalParallelTyCons
     ; if isParallel
-      then return True 
+      then return True
       else or <$> mapM maybeParrTy ts
     }
 maybeParrTy (ForAllTy _ ty) = maybeParrTy ty
@@ -1232,6 +1234,6 @@ allScalarVarTypeSet = allScalarVarType . varSetElems
 --
 viTrace :: CoreExprWithFVs -> VectAvoidInfo -> [CoreExprWithVectInfo] -> VM ()
 viTrace ce vi vTs
-  = traceVt ("vect info: " ++ show vi ++ "[" ++ 
+  = traceVt ("vect info: " ++ show vi ++ "[" ++
              (concat $ map ((++ " ") . show . vectAvoidInfoOf) vTs) ++ "]")
             (ppr $ deAnnotate ce)
index 8af7da3..bfd5367 100644 (file)
@@ -1,39 +1,39 @@
-\r
-T10403.hs:15:7: warning:\r
-    Found hole ‘_’ with inferred constraints: Functor f\r
-    In the type signature for:\r
-      h1 :: _ => _\r
-\r
-T10403.hs:15:12: warning:\r
-    Found type wildcard ‘_’ standing for ‘(a -> b) -> f a -> H f’\r
-    Where: ‘f’ is a rigid type variable bound by\r
-               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:17:1\r
-           ‘b’ is a rigid type variable bound by\r
-               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:17:1\r
-           ‘a’ is a rigid type variable bound by\r
-               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:17:1\r
-    In the type signature for:\r
-      h1 :: _ => _\r
-\r
-T10403.hs:19:7: warning:\r
-    Found type wildcard ‘_’ standing for ‘(a -> b) -> f a -> H f’\r
-    Where: ‘f’ is a rigid type variable bound by\r
-               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:21:1\r
-           ‘b’ is a rigid type variable bound by\r
-               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:21:1\r
-           ‘a’ is a rigid type variable bound by\r
-               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f\r
-               at T10403.hs:21:1\r
-    In the type signature for:\r
-      h2 :: _\r
-\r
-T10403.hs:21:1: warning:\r
-    No instance for (Functor f)\r
-    When checking that ‘h2’ has the inferred type\r
-      h2 :: forall (f :: * -> *) b a. (a -> b) -> f a -> H f\r
-    Probable cause: the inferred type is ambiguous\r
+
+T10403.hs:15:7: warning:
+    Found hole ‘_’ with inferred constraints: Functor f
+    In the type signature for:
+      h1 :: _ => _
+
+T10403.hs:15:12: warning:
+    Found type wildcard ‘_’ standing for ‘(a -> b) -> f a -> H f’
+    Where: ‘b’ is a rigid type variable bound by
+               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:17:1
+           ‘a’ is a rigid type variable bound by
+               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:17:1
+           ‘f’ is a rigid type variable bound by
+               the inferred type of h1 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:17:1
+    In the type signature for:
+      h1 :: _ => _
+
+T10403.hs:19:7: warning:
+    Found type wildcard ‘_’ standing for ‘(a -> b) -> f a -> H f’
+    Where: ‘b’ is a rigid type variable bound by
+               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:21:1
+           ‘a’ is a rigid type variable bound by
+               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:21:1
+           ‘f’ is a rigid type variable bound by
+               the inferred type of h2 :: Functor f => (a -> b) -> f a -> H f
+               at T10403.hs:21:1
+    In the type signature for:
+      h2 :: _
+
+T10403.hs:21:1: warning:
+    No instance for (Functor f)
+    When checking that ‘h2’ has the inferred type
+      h2 :: forall (f :: * -> *) b a. (a -> b) -> f a -> H f
+    Probable cause: the inferred type is ambiguous
index da0f8c7..7eb8b3e 100644 (file)
@@ -1,46 +1,46 @@
-\r
-Trac10045.hs:6:17: error:\r
-    Found type wildcard ‘_’ standing for ‘t1 -> a -> t2’\r
-    Where: ‘t1’ is a rigid type variable bound by\r
-                the inferred type of copy :: Num a => t1 -> a -> t2\r
-                at Trac10045.hs:7:9\r
-           ‘t2’ is a rigid type variable bound by\r
-                the inferred type of copy :: Num a => t1 -> a -> t2\r
-                at Trac10045.hs:7:9\r
-           ‘a’ is a rigid type variable bound by\r
-               the inferred type of copy :: Num a => t1 -> a -> t2\r
-               at Trac10045.hs:7:9\r
-    To use the inferred type, enable PartialTypeSignatures\r
-    Relevant bindings include\r
-      ws1 :: () (bound at Trac10045.hs:5:11)\r
-      foo :: Meta -> t (bound at Trac10045.hs:5:1)\r
-    In the type signature for:\r
-      copy :: _\r
-    In the expression:\r
-      let\r
-        copy :: _\r
-        copy w from = copy w 1\r
-      in copy ws1 1\r
-    In an equation for ‘foo’:\r
-        foo (Meta ws1)\r
-          = let\r
-              copy :: _\r
-              copy w from = copy w 1\r
-            in copy ws1 1\r
-\r
-Trac10045.hs:7:9: error:\r
-    No instance for (Num a)\r
-    When checking that ‘copy’ has the inferred type\r
-      copy :: forall t t1 a. t -> a -> t1\r
-    Probable cause: the inferred type is ambiguous\r
-    In the expression:\r
-      let\r
-        copy :: _\r
-        copy w from = copy w 1\r
-      in copy ws1 1\r
-    In an equation for ‘foo’:\r
-        foo (Meta ws1)\r
-          = let\r
-              copy :: _\r
-              copy w from = copy w 1\r
-            in copy ws1 1\r
+
+Trac10045.hs:6:17: error:
+    Found type wildcard ‘_’ standing for ‘t1 -> a -> t2’
+    Where: ‘t1’ is a rigid type variable bound by
+                the inferred type of copy :: Num a => t1 -> a -> t2
+                at Trac10045.hs:7:9
+           ‘a’ is a rigid type variable bound by
+               the inferred type of copy :: Num a => t1 -> a -> t2
+               at Trac10045.hs:7:9
+           ‘t2’ is a rigid type variable bound by
+                the inferred type of copy :: Num a => t1 -> a -> t2
+                at Trac10045.hs:7:9
+    To use the inferred type, enable PartialTypeSignatures
+    Relevant bindings include
+      ws1 :: () (bound at Trac10045.hs:5:11)
+      foo :: Meta -> t (bound at Trac10045.hs:5:1)
+    In the type signature for:
+      copy :: _
+    In the expression:
+      let
+        copy :: _
+        copy w from = copy w 1
+      in copy ws1 1
+    In an equation for ‘foo’:
+        foo (Meta ws1)
+          = let
+              copy :: _
+              copy w from = copy w 1
+            in copy ws1 1
+
+Trac10045.hs:7:9: error:
+    No instance for (Num a)
+    When checking that ‘copy’ has the inferred type
+      copy :: forall t t1 a. t -> a -> t1
+    Probable cause: the inferred type is ambiguous
+    In the expression:
+      let
+        copy :: _
+        copy w from = copy w 1
+      in copy ws1 1
+    In an equation for ‘foo’:
+        foo (Meta ws1)
+          = let
+              copy :: _
+              copy w from = copy w 1
+            in copy ws1 1
diff --git a/testsuite/tests/perf/should_run/T10359 b/testsuite/tests/perf/should_run/T10359
new file mode 100755 (executable)
index 0000000..4968e1b
Binary files /dev/null and b/testsuite/tests/perf/should_run/T10359 differ
index 1d1a1df..a5b35ee 100644 (file)
@@ -1,24 +1,24 @@
-\r
-T9222.hs:13:3: error:\r
-    Couldn't match type ‘b0’ with ‘b’\r
-      ‘b0’ is untouchable\r
-        inside the constraints: a ~ '(b0, c0)\r
-        bound by the type of the constructor ‘Want’:\r
-                   (a ~ '(b0, c0)) => Proxy b0\r
-        at T9222.hs:13:3\r
-      ‘b’ is a rigid type variable bound by\r
-          the type of the constructor ‘Want’:\r
-            ((a ~ '(b, c)) => Proxy b) -> Want a\r
-          at T9222.hs:13:3\r
-    Expected type: '(b, c)\r
-      Actual type: a\r
-    In the ambiguity check for the type of the constructor ‘Want’:\r
-      Want :: forall (k :: BOX)\r
-                     (k1 :: BOX)\r
-                     (a :: (,) k k1)\r
-                     (b :: k)\r
-                     (c :: k1).\r
-              ((a ~ '(b, c)) => Proxy b) -> Want a\r
-    To defer the ambiguity check to use sites, enable AllowAmbiguousTypes\r
-    In the definition of data constructor ‘Want’\r
-    In the data type declaration for ‘Want’\r
+
+T9222.hs:13:3: error:
+    Couldn't match type ‘b0’ with ‘b’
+      ‘b0’ is untouchable
+        inside the constraints: a ~ '(b0, c0)
+        bound by the type of the constructor ‘Want’:
+                   (a ~ '(b0, c0)) => Proxy b0
+        at T9222.hs:13:3
+    ‘b’ is a rigid type variable bound by
+        the type of the constructor ‘Want’:
+          ((a ~ '(b, c)) => Proxy b) -> Want a
+        at T9222.hs:13:3
+    Expected type: '(b, c)
+      Actual type: a
+    In the ambiguity check for the type of the constructor ‘Want’:
+      Want :: forall (k :: BOX)
+                     (k1 :: BOX)
+                     (a :: (,) k k1)
+                     (b :: k)
+                     (c :: k1).
+              ((a ~ '(b, c)) => Proxy b) -> Want a
+    To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
+    In the definition of data constructor ‘Want’
+    In the data type declaration for ‘Want’