Adam Gundry pushed to branch wip/amg/castz at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/Core.hs
    ... ... @@ -18,8 +18,7 @@ module GHC.Core (
    18 18
                    InCastCoercion,
    
    19 19
             OutId, OutBind, OutExpr, OutAlt, OutArg, OutType, OutKind,
    
    20 20
                    OutBndr, OutVar, OutCoercion, OutCoercionR, OutTyVar, OutCoVar,
    
    21
    -               OutTyCoVar, MOutCoercion,
    
    22
    -               OutCastCoercion,
    
    21
    +               OutTyCoVar, OutCastCoercion,
    
    23 22
     
    
    24 23
             -- ** 'Expr' construction
    
    25 24
             mkLet, mkLets, mkLetNonRec, mkLetRec, mkLams,
    
    ... ... @@ -1133,7 +1132,6 @@ type OutBind = CoreBind
    1133 1132
     type OutExpr      = CoreExpr
    
    1134 1133
     type OutAlt       = CoreAlt
    
    1135 1134
     type OutArg       = CoreArg
    
    1136
    -type MOutCoercion = MCoercion
    
    1137 1135
     type OutCastCoercion = CastCoercion
    
    1138 1136
     
    
    1139 1137
     
    

  • compiler/GHC/Core/Coercion.hs
    ... ... @@ -65,6 +65,7 @@ module GHC.Core.Coercion (
    65 65
             mkFunResCastCo,
    
    66 66
             mkFunCastCoNoFTF,
    
    67 67
             applyForAllTy,
    
    68
    +        decomposeFunCastCo,
    
    68 69
     
    
    69 70
             -- ** Decomposition
    
    70 71
             instNewTyCon_maybe,
    
    ... ... @@ -459,6 +460,14 @@ decomposeFunCo co
    459 460
         Pair s1t1 s2t2 = coercionKind co
    
    460 461
         all_ok = isFunTy s1t1 && isFunTy s2t2
    
    461 462
     
    
    463
    +
    
    464
    +decomposeFunCastCo :: HasDebugCallStack => CastCoercion -> (CastCoercion, CastCoercion)
    
    465
    +decomposeFunCastCo (CCoercion co)      = let (_, arg_co, res_co) = decomposeFunCo co
    
    466
    +                                         in (CCoercion arg_co, CCoercion res_co)
    
    467
    +decomposeFunCastCo ReflCastCo          = (ReflCastCo, ReflCastCo)
    
    468
    +decomposeFunCastCo (ZCoercion tyR cos) = (ZCoercion (funArgTy tyR) cos, ZCoercion (funResultTy tyR) cos)
    
    469
    +
    
    470
    +
    
    462 471
     {- Note [Pushing a coercion into a pi-type]
    
    463 472
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    464 473
     Suppose we have this:
    

  • compiler/GHC/Core/Opt/Arity.hs
    ... ... @@ -3010,18 +3010,18 @@ pushCoValArg co
    3010 3010
         Pair tyL tyR = coercionKind co
    
    3011 3011
     
    
    3012 3012
     pushCoercionIntoLambda
    
    3013
    -    :: HasDebugCallStack => Subst -> InVar -> InExpr -> OutCastCoercion -> Maybe (OutVar, OutExpr)
    
    3013
    +    :: HasDebugCallStack => Subst -> InVar -> InExpr -> Type -> OutCastCoercion -> Maybe (OutVar, OutExpr)
    
    3014 3014
     -- This implements the Push rule from the paper on coercions
    
    3015 3015
     --    (\x. e) |> co
    
    3016 3016
     -- ===>
    
    3017 3017
     --    (\x'. e |> co')
    
    3018
    -pushCoercionIntoLambda subst x e cco
    
    3018
    +pushCoercionIntoLambda subst x e ty co
    
    3019 3019
         | assert (not (isTyVar x) && not (isCoVar x)) True
    
    3020
    -    , CCoercion co <- cco -- AMG TODO: support for other CastCoercions
    
    3021
    -    , Pair s1s2 t1t2 <- coercionKind co
    
    3022
    -    , Just {}              <- splitFunTy_maybe s1s2
    
    3020
    +    , let s1s2 = castCoercionLKind ty co
    
    3021
    +    , let t1t2 = castCoercionRKind ty co
    
    3022
    +    , Just (_, _, s1, _)   <- splitFunTy_maybe s1s2
    
    3023 3023
         , Just (_, w1, t1,_t2) <- splitFunTy_maybe t1t2
    
    3024
    -    , (_, co1, co2)  <- decomposeFunCo co
    
    3024
    +    , (co1, co2)  <- decomposeFunCastCo co
    
    3025 3025
         , typeHasFixedRuntimeRep t1
    
    3026 3026
           -- We can't push the coercion into the lambda if it would create
    
    3027 3027
           -- a representation-polymorphic binder.
    
    ... ... @@ -3033,12 +3033,12 @@ pushCoercionIntoLambda subst x e cco
    3033 3033
               subst' =
    
    3034 3034
                 extendIdSubst (setInScope subst in_scope')
    
    3035 3035
                   x
    
    3036
    -              (mkCast (Var x') (mkSymCo co1))
    
    3036
    +              (mkCastCo (Var x') (mkSymCastCo s1 co1))
    
    3037 3037
                 -- We substitute x' for x, except we need to preserve types.
    
    3038 3038
                 -- The types are as follows:
    
    3039 3039
                 --   x :: s1,  x' :: t1,  co1 :: s1 ~# t1,
    
    3040 3040
                 -- so we extend the substitution with x |-> (x' |> sym co1).
    
    3041
    -      in Just (x', substExpr subst' e `mkCast` co2)
    
    3041
    +      in Just (x', substExpr subst' e `mkCastCo` co2)
    
    3042 3042
         | otherwise
    
    3043 3043
         = Nothing
    
    3044 3044
     
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -1691,20 +1691,18 @@ simplCast :: SimplEnv -> InExpr -> InCastCoercion -> SimplCont
    1691 1691
     simplCast env body co0 cont0
    
    1692 1692
       = do  { (tyL, co1) <- {-#SCC "simplCast-simplCoercion" #-} simplCastCoercion env (exprType body) co0
    
    1693 1693
             ; cont1 <- {-#SCC "simplCast-addCoerce" #-}
    
    1694
    -                   if isReflCastCo co1
    
    1695
    -                   then return cont0  -- See Note [Optimising reflexivity]
    
    1696
    -                   else addCoerce tyL co1 True cont0
    
    1694
    +                     addCoerceMaybeRefl tyL co1 True cont0
    
    1697 1695
                             -- True <=> co1 is optimised
    
    1698 1696
             ; {-#SCC "simplCast-simplExprF" #-} simplExprF env body cont1 }
    
    1699 1697
       where
    
    1700
    -
    
    1701
    -        -- If the first parameter is MRefl, then simplifying revealed a
    
    1702
    -        -- reflexive coercion. Omit.
    
    1703
    -        -- TODO: probably can simplify this further now?
    
    1704
    -        addCoerceM :: OutType -> OutCastCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1705
    -        addCoerceM _ ReflCastCo _   cont = return cont
    
    1706
    -        addCoerceM tyL co opt cont = addCoerce tyL co opt cont
    
    1707
    -
    
    1698
    +        -- If simplifying revealed an obviously reflexive coercion, omit it.
    
    1699
    +        -- See Note [Optimising reflexivity].
    
    1700
    +        addCoerceMaybeRefl :: OutType -> OutCastCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1701
    +        addCoerceMaybeRefl tyL co opt cont
    
    1702
    +          | isReflCastCo co = return cont
    
    1703
    +          | otherwise       = addCoerce tyL co opt cont
    
    1704
    +
    
    1705
    +        -- Here the coercion is known not to satisfy isReflCastCo.
    
    1708 1706
             -- Type tyL is the coercionLKind of the coercion
    
    1709 1707
             addCoerce :: OutType -> OutCastCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1710 1708
             addCoerce tyL co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity]
    
    ... ... @@ -1715,7 +1713,7 @@ simplCast env body co0 cont0
    1715 1713
             addCoerce tyL co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
    
    1716 1714
               | Just (arg_ty', res_ty, m_co') <- pushCastCoTyArg tyL co arg_ty
    
    1717 1715
               = {-#SCC "addCoerce-pushCoTyArg" #-}
    
    1718
    -            do { tail' <- addCoerceM res_ty m_co' co_is_opt tail
    
    1716
    +            do { tail' <- addCoerceMaybeRefl res_ty m_co' co_is_opt tail
    
    1719 1717
                    ; return (ApplyToTy { sc_arg_ty  = arg_ty'
    
    1720 1718
                                        , sc_cont    = tail'
    
    1721 1719
                                        , sc_hole_ty = tyL }) }
    
    ... ... @@ -1729,11 +1727,11 @@ simplCast env body co0 cont0
    1729 1727
                                                     , sc_dup = dup, sc_cont = tail
    
    1730 1728
                                                     , sc_hole_ty = fun_ty })
    
    1731 1729
               | not co_is_opt  -- pushCoValArg duplicates the coercion, so optimise first
    
    1732
    -          = addCoerce tyL (optOutCoercion (zapSubstEnv env) tyL co co_is_opt) True cont
    
    1730
    +          = addCoerceMaybeRefl tyL (optOutCoercion (zapSubstEnv env) tyL co co_is_opt) True cont
    
    1733 1731
     
    
    1734 1732
               | Just (_, m_co1, res_ty, m_co2) <- pushCastCoValArg tyL co
    
    1735 1733
               = {-#SCC "addCoerce-pushCoValArg" #-}
    
    1736
    -            do { tail' <- addCoerceM res_ty m_co2 co_is_opt tail
    
    1734
    +            do { tail' <- addCoerceMaybeRefl res_ty m_co2 co_is_opt tail
    
    1737 1735
                    ; if isReflCastCo m_co1
    
    1738 1736
                        then return (cont { sc_cont = tail'
    
    1739 1737
                                              , sc_hole_ty = tyL }) ;
    
    ... ... @@ -1753,10 +1751,7 @@ simplCast env body co0 cont0
    1753 1751
                                         , sc_hole_ty = tyL }) } }
    
    1754 1752
     
    
    1755 1753
             addCoerce tyL co co_is_opt cont
    
    1756
    -          | isReflCastCo co = return cont  -- Having this at the end makes a huge
    
    1757
    -                                       -- difference in T12227, for some reason
    
    1758
    -                                       -- See Note [Optimising reflexivity]
    
    1759
    -          | otherwise = return (CastIt { sc_co = co, sc_hole_ty = tyL, sc_opt = co_is_opt, sc_cont = cont })
    
    1754
    +          = return (CastIt { sc_co = co, sc_hole_ty = tyL, sc_opt = co_is_opt, sc_cont = cont })
    
    1760 1755
     
    
    1761 1756
     simplLazyArg :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1762 1757
                  -> DupFlag
    

  • compiler/GHC/Core/SimpleOpt.hs
    ... ... @@ -213,11 +213,11 @@ simpleOptPgm opts this_mod binds rules =
    213 213
     ----------------------
    
    214 214
     type SimpleClo = (SimpleOptEnv, InExpr)
    
    215 215
     
    
    216
    -data SimpleContItem = ApplyToArg SimpleClo | CastIt OutCastCoercion
    
    216
    +data SimpleContItem = ApplyToArg SimpleClo | CastIt OutType OutCastCoercion
    
    217 217
     
    
    218 218
     instance Outputable SimpleContItem where
    
    219 219
       ppr (ApplyToArg (_, arg)) = text "ARG" <+> ppr arg
    
    220
    -  ppr (CastIt co) = text "CAST" <+> ppr co
    
    220
    +  ppr (CastIt _ co) = text "CAST" <+> ppr co
    
    221 221
     
    
    222 222
     data SimpleOptEnv
    
    223 223
       = SOE { soe_opts :: {-# UNPACK #-} !SimpleOpts
    
    ... ... @@ -392,10 +392,10 @@ simple_app env e0@(Lam {}) as0@(_:_)
    392 392
           = wrapLet mb_pr $ do_beta env'' body as
    
    393 393
           where (env', b') = subst_opt_bndr env b
    
    394 394
     
    
    395
    -    do_beta env e@(Lam b body) as@(CastIt co:rest)
    
    395
    +    do_beta env e@(Lam b body) as@(CastIt ty co:rest)
    
    396 396
           -- See Note [Desugaring unlifted newtypes]
    
    397 397
           | isNonCoVarId b
    
    398
    -      , Just (b', body') <- pushCoercionIntoLambda (soe_subst env) b body co
    
    398
    +      , Just (b', body') <- pushCoercionIntoLambda (soe_subst env) b body ty co
    
    399 399
           = do_beta (soeZapSubst env) (Lam b' body') rest
    
    400 400
             -- soeZapSubst: pushCoercionIntoLambda applies the substitution
    
    401 401
           | otherwise
    
    ... ... @@ -461,10 +461,10 @@ add_cast env tyL co1 as
    461 461
       = as
    
    462 462
       | otherwise
    
    463 463
       = case as of
    
    464
    -      CastIt co2:rest -> CastIt (co1' `mkTransCastCo` co2):rest
    
    465
    -      _               -> CastIt co1':as
    
    464
    +      CastIt _ co2:rest -> CastIt ty (co1' `mkTransCastCo` co2):rest
    
    465
    +      _                 -> CastIt ty co1':as
    
    466 466
       where
    
    467
    -    (_, co1') = optCastCoercion (so_co_opts (soe_opts env)) (soe_subst env) tyL co1
    
    467
    +    (ty, co1') = optCastCoercion (so_co_opts (soe_opts env)) (soe_subst env) tyL co1
    
    468 468
     
    
    469 469
     rebuild_app :: HasDebugCallStack
    
    470 470
                 => SimpleOptEnv -> OutExpr -> [SimpleContItem] -> OutExpr
    
    ... ... @@ -473,7 +473,7 @@ rebuild_app env fun args = foldl mk_app fun args
    473 473
         in_scope = soeInScope env
    
    474 474
         mk_app out_fun = \case
    
    475 475
           ApplyToArg arg -> App out_fun (simple_opt_clo in_scope arg)
    
    476
    -      CastIt co      -> mk_cast out_fun co
    
    476
    +      CastIt _ co    -> mk_cast out_fun co
    
    477 477
     
    
    478 478
     {- Note [Desugaring unlifted newtypes]
    
    479 479
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1675,7 +1675,7 @@ exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e co)
    1675 1675
         -- this implies that x is not in scope in gamma (makes this code simpler)
    
    1676 1676
         , not (isTyVar x) && not (isCoVar x)
    
    1677 1677
         , assert (not $ x `elemVarSet` tyCoVarsOfCastCo co) True
    
    1678
    -    , Just (x',e') <- pushCoercionIntoLambda (mkEmptySubst in_scope_set) x e co
    
    1678
    +    , Just (x',e') <- pushCoercionIntoLambda (mkEmptySubst in_scope_set) x e (exprType casted_e) co
    
    1679 1679
         , let res = Just (x',e',ts)
    
    1680 1680
         = --pprTrace "exprIsLambda_maybe:Cast" (vcat [ppr casted_e,ppr co,ppr res)])
    
    1681 1681
           res
    

  • compiler/GHC/HsToCore/Binds.hs
    ... ... @@ -1166,9 +1166,9 @@ getRenamings orig_bndrs binds rule_bndrs
    1166 1166
         go [] = init_renamings
    
    1167 1167
         go (bind : binds)
    
    1168 1168
            | NonRec b rhs <- bind
    
    1169
    -       , Just (v, mco) <- getCastedVar rhs
    
    1169
    +       , Just (v, co) <- getCastedVar rhs
    
    1170 1170
            , Just e <- lookupVarEnv renamings b
    
    1171
    -       = extendVarEnv renamings v (mkCastMCo e (mkSymMCo mco))
    
    1171
    +       = extendVarEnv renamings v (mkCastCo e co)
    
    1172 1172
            | otherwise
    
    1173 1173
            = renamings
    
    1174 1174
            where
    
    ... ... @@ -1186,9 +1186,9 @@ pickSpecBinds is_local known_bndrs (bind:binds)
    1186 1186
             keep_me rhs = isEmptyVarSet (exprSomeFreeVars bad_var rhs)
    
    1187 1187
             bad_var v = is_local v && not (v `elemVarSet` known_bndrs)
    
    1188 1188
     
    
    1189
    -getCastedVar :: CoreExpr -> Maybe (Var, MCoercionR)
    
    1190
    -getCastedVar (Var v)           = Just (v, MRefl)
    
    1191
    -getCastedVar (Cast (Var v) (CCoercion co)) = Just (v, MCo co) -- TODO what about ZCoercion case?
    
    1189
    +getCastedVar :: CoreExpr -> Maybe (Var, CastCoercion)
    
    1190
    +getCastedVar (Var v)           = Just (v, ReflCastCo)
    
    1191
    +getCastedVar (Cast (Var v) co) = Just (v, mkSymCastCo (varType v) co)
    
    1192 1192
     getCastedVar _                 = Nothing
    
    1193 1193
     
    
    1194 1194
     specFunInlinePrag :: Id -> InlinePragma