Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC

Commits:

2 changed files:

Changes:

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -40,7 +40,8 @@ import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe
    40 40
                               , typeArity, arityTypeArity, etaExpandAT )
    
    41 41
     import GHC.Core.SimpleOpt ( exprIsConApp_maybe, joinPointBinding_maybe, joinPointBindings_maybe )
    
    42 42
     import GHC.Core.FVs     ( mkRuleInfo {- exprsFreeIds -} )
    
    43
    -import GHC.Core.Rules   ( lookupRule, getRules )
    
    43
    +import GHC.Core.Rules   ( RuleMatch(..), applyBindWrapper, isEmptyBindWrapper
    
    44
    +                        , lookupRule, getRules )
    
    44 45
     import GHC.Core.Multiplicity
    
    45 46
     
    
    46 47
     import GHC.Hs.Extension
    
    ... ... @@ -2298,7 +2299,7 @@ simplOutExpr env expr cont
    2298 2299
           _                        -> rebuild_go env expr cont
    
    2299 2300
       where
    
    2300 2301
         (fun, args) = collectArgs expr
    
    2301
    -    cont' = pushArgs env Simplified (expType fun) args cont
    
    2302
    +    cont' = pushArgs env Simplified (exprType fun) args cont
    
    2302 2303
         occ_fun = occurAnalyseExpr fun  -- ToDo:explain; c.f. Note [Occurrence-analyse after rule firing]
    
    2303 2304
     
    
    2304 2305
     ---------------------------------------------------------
    
    ... ... @@ -2364,10 +2365,14 @@ simplOutId env fun cont
    2364 2365
                          then tryRules env rules_for_me fun out_args
    
    2365 2366
                          else return Nothing
    
    2366 2367
            ; case mb_match of {
    
    2367
    -             Just (rule_arity, rhs, rhs_args ) -> simplExprF env rhs $
    
    2368
    -                                                  pushArgs env NoDup rhs_args $
    
    2369
    -                                                  dropContArgs rule_arity cont ;
    
    2370
    -             Nothing ->
    
    2368
    +             Just (RM { rm_rule = rule, rm_rhs = rhs
    
    2369
    +                      , rm_args = rhs_args, rm_binds = wrap })
    
    2370
    +                  -> simplExprF env rhs' $
    
    2371
    +                     dropContArgs (ruleArity rule) cont
    
    2372
    +                  where
    
    2373
    +                    rhs' = applyBindWrapper wrap $
    
    2374
    +                           mkApps rhs rhs_args
    
    2375
    +           ; Nothing ->
    
    2371 2376
     
    
    2372 2377
         -- Try inlining
    
    2373 2378
         do { logger <- getLogger
    
    ... ... @@ -2451,18 +2456,15 @@ rebuildCall env fun_info
    2451 2456
             ; rebuildCall env (addValArgTo fun_info  arg' fun_ty) cont }
    
    2452 2457
     
    
    2453 2458
     ---------- No further useful info, revert to generic rebuild ------------
    
    2454
    -rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_rules = rules }) cont
    
    2459
    +rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_arg_specs, ai_rules = rules }) cont
    
    2455 2460
       | null rules
    
    2456
    -  = rebuild env (argInfoExpr fun rev_args) cont
    
    2461
    +  = rebuild env (argInfoExpr fun rev_arg_specs) cont
    
    2457 2462
       | otherwise  -- Try rules again: Plan (AFTER) in Note [When to apply rewrite rules]
    
    2458
    -  = do { let args = reverse rev_args
    
    2459
    -       ; mb_match <- tryRules env rules fun (map argSpecArg args)
    
    2463
    +  = do { let arg_specs = reverse rev_arg_specs
    
    2464
    +       ; mb_match <- tryRules env rules fun (map argSpecArg arg_specs)
    
    2460 2465
            ; case mb_match of
    
    2461
    -           Just (rule_arity, rhs, rhs_args)
    
    2462
    -             -> simplExprF env rhs $
    
    2463
    -                pushArgs env Simplified rhs_args $
    
    2464
    -                pushArgSpecs env (drop rule_arity args) cont
    
    2465
    -           Nothing -> rebuild env (argInfoExpr fun rev_args) cont }
    
    2466
    +           Just rule_match -> fireRuleAFTER env rule_match arg_specs cont
    
    2467
    +           Nothing         -> rebuild env (argInfoExpr fun rev_arg_specs) cont }
    
    2466 2468
     
    
    2467 2469
     -----------------------------------
    
    2468 2470
     tryInlining :: SimplEnv -> Logger -> OutId -> SimplCont -> SimplM (Maybe OutExpr)
    
    ... ... @@ -2644,20 +2646,36 @@ See Note [No free join points in arityType] in GHC.Core.Opt.Arity
    2644 2646
     ************************************************************************
    
    2645 2647
     -}
    
    2646 2648
     
    
    2649
    +fireRuleAFTER :: SimplEnv -> RuleMatch
    
    2650
    +              -> [ArgSpec] -> SimplCont
    
    2651
    +              -> SimplM (SimplFloats, CoreExpr)
    
    2652
    +fireRuleAFTER env rule_match arg_specs cont
    
    2653
    +  | RM { rm_rule = rule, rm_rhs = rhs, rm_args = rhs_args
    
    2654
    +       , rm_binds = wrap, rm_bndrs = bndrs } <- rule_match
    
    2655
    +  = do { let env' = env `addNewInScopeIds` bndrs
    
    2656
    +       ; (floats, e') <- simplExprF env' rhs $
    
    2657
    +                         pushArgs env' Simplified (exprType rhs) rhs_args $
    
    2658
    +                         pushArgSpecs env' (drop (ruleArity rule) arg_specs) cont
    
    2659
    +       ; return $
    
    2660
    +         if isEmptyBindWrapper wrap
    
    2661
    +         then (floats, e')
    
    2662
    +         else (emptyFloats env', applyBindWrapper wrap $
    
    2663
    +                                 wrapFloats floats e') }
    
    2664
    +
    
    2665
    +
    
    2647 2666
     tryRules :: SimplEnv -> [CoreRule]
    
    2648 2667
              -> OutId -> [OutExpr]
    
    2649
    -         -> SimplM (Maybe (FullArgCount, CoreExpr, [CoreExpr]))
    
    2668
    +         -> SimplM (Maybe RuleMatch)
    
    2650 2669
     
    
    2651 2670
     tryRules env rules fn args
    
    2652
    -  | Just (rule, rule_rhs, rule_args) <- lookupRule ropts in_scope_env
    
    2653
    -                                            act_fun fn args rules
    
    2654
    -  -- Fire a rule for the function
    
    2655
    -  = do { logger <- getLogger
    
    2656
    -       ; checkedTick (RuleFired (ruleName rule))
    
    2657
    ---       ; let occ_anald_rhs = occurAnalyseExpr rule_rhs
    
    2658
    ---                 -- See Note [Occurrence-analyse after rule firing]
    
    2659
    -       ; dump logger rule rule_rhs
    
    2660
    -       ; return (Just (ruleArity rule, rhs_rhs, rule_args)) }
    
    2671
    +  | Just rule_match <- lookupRule ropts in_scope_env
    
    2672
    +                                  act_fun fn args rules
    
    2673
    +    -- Fire a rule for the function
    
    2674
    +  = do { let the_rule = rm_rule rule_match
    
    2675
    +       ; logger <- getLogger
    
    2676
    +       ; checkedTick (RuleFired (ruleName the_rule))
    
    2677
    +       ; dump logger the_rule (rm_rhs rule_match)
    
    2678
    +       ; return (Just rule_match) }
    
    2661 2679
     
    
    2662 2680
       | otherwise  -- No rule fires
    
    2663 2681
       = do { logger <- getLogger
    
    ... ... @@ -2723,12 +2741,8 @@ trySeqRules in_env scrut rhs cont
    2723 2741
            ; let seq_rules = getRules rule_base seqId
    
    2724 2742
            ; mb_match <- tryRules in_env seq_rules seqId out_args
    
    2725 2743
            ; case mb_match of
    
    2726
    -            Nothing                          -> return Nothing
    
    2727
    -            Just (rule_arity, rhs, rhs_args) -> return (Just (rhs, cont'))
    
    2728
    -                where
    
    2729
    -                  cont' = pushArgs in_env Simplified rhs_args $
    
    2730
    -                          pushArgSpecs in_env (drop rule_arity out_arg_specs) rule_cont
    
    2731
    -       }
    
    2744
    +            Nothing         -> return Nothing
    
    2745
    +            Just rule_match -> Just <$> fireRuleAFTER in_env rule_match out_arg_specs cont }
    
    2732 2746
       where
    
    2733 2747
         no_cast_scrut = drop_casts scrut
    
    2734 2748
     
    

  • compiler/GHC/Core/Rules.hs
    ... ... @@ -10,6 +10,7 @@
    10 10
     module GHC.Core.Rules (
    
    11 11
             -- ** Looking up rules
    
    12 12
             RuleMatch(..), lookupRule, matchExprs, ruleLhsIsMoreSpecific,
    
    13
    +        BindWrapper, isEmptyBindWrapper, applyBindWrapper,
    
    13 14
     
    
    14 15
             -- ** RuleBase, RuleEnv
    
    15 16
             RuleBase, RuleEnv(..), mkRuleEnv, emptyRuleEnv,
    
    ... ... @@ -88,6 +89,7 @@ import GHC.Types.Basic
    88 89
     import GHC.Data.FastString
    
    89 90
     import GHC.Data.Maybe
    
    90 91
     import GHC.Data.Bag
    
    92
    +import GHC.Data.OrdList
    
    91 93
     import GHC.Data.List.SetOps( hasNoDups )
    
    92 94
     
    
    93 95
     import GHC.Utils.FV( filterFV, fvVarSet )
    
    ... ... @@ -591,7 +593,7 @@ lookupRule opts rule_env@(ISE in_scope _) is_active fn args rules
    591 593
         go ms [] = ms
    
    592 594
         go ms (r:rs)
    
    593 595
           | Just rm <- matchRule opts rule_env is_active fn args' rough_args r
    
    594
    -      = go (rm { rm_binds = mkTicks ticks . rm_binds rm } : ms) rs
    
    596
    +      = go (rm { rm_binds = mkTicks ticks `consOL` rm_binds rm } : ms) rs
    
    595 597
           | otherwise
    
    596 598
           = -- pprTrace "match failed" (ppr r $$ ppr args $$
    
    597 599
             --   ppr [ (arg_id, maybeUnfoldingTemplate unf)
    
    ... ... @@ -746,7 +748,7 @@ matchRule opts rule_env _is_active fn args _rough_args
    746 748
            ; return (RM { rm_rule = rule
    
    747 749
                         , rm_rhs = rhs
    
    748 750
                         , rm_args = []
    
    749
    -                    , rm_binds = id
    
    751
    +                    , rm_binds = emptyBindWrapper
    
    750 752
                         , rm_bndrs = [] }) }
    
    751 753
     
    
    752 754
     matchRule _opts rule_env is_active _fn target_es rough_args
    
    ... ... @@ -968,13 +970,23 @@ data RuleSubst = RS { -- Substitution; applied only to the template, not the tar
    968 970
                         , rs_bndrs    :: [Var]        -- Variables bound by floated lets
    
    969 971
                         }
    
    970 972
     
    
    971
    -type BindWrapper = CoreExpr -> CoreExpr
    
    973
    +type BindWrapper = OrdList (CoreExpr -> CoreExpr)
    
    972 974
       -- See Notes [Matching lets] and [Matching cases]
    
    973 975
       -- we represent the floated bindings as a core-to-core function
    
    976
    +  -- WE use an OrdList so that we can tell the common case of an empty wrapper
    
    977
    +
    
    978
    +emptyBindWrapper :: BindWrapper
    
    979
    +emptyBindWrapper = nilOL
    
    980
    +
    
    981
    +isEmptyBindWrapper :: BindWrapper -> Bool
    
    982
    +isEmptyBindWrapper = isNilOL
    
    983
    +
    
    984
    +applyBindWrapper :: BindWrapper -> CoreExpr -> CoreExpr
    
    985
    +applyBindWrapper bw e = foldrOL ($) e bw
    
    974 986
     
    
    975 987
     emptyRuleSubst :: RuleSubst
    
    976 988
     emptyRuleSubst = RS { rs_tv_subst = emptyVarEnv, rs_id_subst = emptyVarEnv
    
    977
    -                    , rs_binds = \e -> e, rs_bndrs = [] }
    
    989
    +                    , rs_binds = nilOL, rs_bndrs = [] }
    
    978 990
     
    
    979 991
     
    
    980 992
     {- Note [Casts in the target]
    
    ... ... @@ -1110,7 +1122,7 @@ match renv subst e1 (Tick t e2) mco
    1110 1122
       | otherwise
    
    1111 1123
       = Nothing
    
    1112 1124
       where
    
    1113
    -    subst' = subst { rs_binds = rs_binds subst . mkTick t }
    
    1125
    +    subst' = subst { rs_binds = rs_binds subst `snocOL` mkTick t }
    
    1114 1126
     
    
    1115 1127
     match renv subst e@(Tick t e1) e2 mco
    
    1116 1128
       | tickishFloatable t  -- Ignore floatable ticks in rule template.
    
    ... ... @@ -1344,7 +1356,7 @@ match renv subst e1 (Let bind e2) mco
    1344 1356
                     -- We are floating the let-binding out, as if it had enclosed
    
    1345 1357
                     -- the entire target from Day 1.  So we must add its binders to
    
    1346 1358
                     -- the in-scope set (#20200)
    
    1347
    -          (subst { rs_binds = rs_binds subst . Let bind'
    
    1359
    +          (subst { rs_binds = rs_binds subst `snocOL` Let bind'
    
    1348 1360
                      , rs_bndrs = new_bndrs ++ rs_bndrs subst })
    
    1349 1361
               e1 e2 mco
    
    1350 1362
       | otherwise
    
    ... ... @@ -1370,7 +1382,7 @@ match renv subst (Lam x1 e1) e2 mco
    1370 1382
       , Just (x2, e2', ts) <- exprIsLambda_maybe in_scope_env casted_e2
    
    1371 1383
         -- See Note [Lambdas in the template]
    
    1372 1384
       = let renv'  = rnMatchBndr2 renv x1 x2
    
    1373
    -        subst' = subst { rs_binds = rs_binds subst . flip (foldr mkTick) ts }
    
    1385
    +        subst' = subst { rs_binds = rs_binds subst `snocOL` flip (foldr mkTick) ts }
    
    1374 1386
         in  match renv' subst' e1 e2' MRefl
    
    1375 1387
     
    
    1376 1388
     match renv subst e1 e2@(Lam {}) mco
    
    ... ... @@ -1435,11 +1447,11 @@ match _ _ _e1 _e2 _mco = -- pprTrace "Failing at" ((text "e1:" <+> ppr _e1) $$ (
    1435 1447
     eta_reduce :: RuleMatchEnv -> CoreExpr -> Maybe (RuleMatchEnv, CoreExpr)
    
    1436 1448
     -- See Note [Eta reduction in the target]
    
    1437 1449
     eta_reduce renv e@(Lam {})
    
    1438
    -  = go renv id [] e
    
    1450
    +  = go renv emptyBindWrapper [] e
    
    1439 1451
       where
    
    1440 1452
         go :: RuleMatchEnv -> BindWrapper -> [Var] -> CoreExpr
    
    1441 1453
            -> Maybe (RuleMatchEnv, CoreExpr)
    
    1442
    -    go renv bw vs (Let b e) = go renv (bw . Let b) vs e
    
    1454
    +    go renv bw vs (Let b e) = go renv (bw `snocOL` Let b) vs e
    
    1443 1455
     
    
    1444 1456
         go renv bw vs (Lam v e) = go renv' bw (v':vs) e
    
    1445 1457
           where
    
    ... ... @@ -1454,7 +1466,7 @@ eta_reduce renv e@(Lam {})
    1454 1466
           , v == rnOccR (rv_lcl renv) tv
    
    1455 1467
           = go renv bw vs f
    
    1456 1468
     
    
    1457
    -    go renv bw []    e = Just (renv, bw e)
    
    1469
    +    go renv bw []    e = Just (renv, applyBindWrapper bw e)
    
    1458 1470
         go _    _  (_:_) _ = Nothing
    
    1459 1471
     
    
    1460 1472
     eta_reduce _ _ = Nothing