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

Commits:

6 changed files:

Changes:

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -2294,11 +2294,12 @@ simplOutExpr :: SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutEx
    2294 2294
     simplOutExpr env expr cont
    
    2295 2295
       = case fun of
    
    2296 2296
           Var v                    -> simplOutId env v cont'
    
    2297
    -      Lam {} | not (null args) -> simplLam env fun cont'  -- We have a beta-redex
    
    2297
    +      Lam {} | not (null args) -> simplLam env occ_fun cont'  -- We have a beta-redex
    
    2298 2298
           _                        -> rebuild_go env expr cont
    
    2299 2299
       where
    
    2300
    -    (fun, args) <- collectArgs expr
    
    2300
    +    (fun, args) = collectArgs expr
    
    2301 2301
         cont' = pushArgs env Simplified (expType fun) args cont
    
    2302
    +    occ_fun = occurAnalyseExpr fun  -- ToDo:explain; c.f. Note [Occurrence-analyse after rule firing]
    
    2302 2303
     
    
    2303 2304
     ---------------------------------------------------------
    
    2304 2305
     simplOutId :: SimplEnvIS -> OutId -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    ... ... @@ -2645,18 +2646,18 @@ See Note [No free join points in arityType] in GHC.Core.Opt.Arity
    2645 2646
     
    
    2646 2647
     tryRules :: SimplEnv -> [CoreRule]
    
    2647 2648
              -> OutId -> [OutExpr]
    
    2648
    -         -> SimplM (Maybe (FullArgCount, CoreExpr))
    
    2649
    +         -> SimplM (Maybe (FullArgCount, CoreExpr, [CoreExpr]))
    
    2649 2650
     
    
    2650 2651
     tryRules env rules fn args
    
    2651
    -  | Just (rule, rule_rhs) <- lookupRule ropts in_scope_env
    
    2652
    -                                        act_fun fn args rules
    
    2652
    +  | Just (rule, rule_rhs, rule_args) <- lookupRule ropts in_scope_env
    
    2653
    +                                            act_fun fn args rules
    
    2653 2654
       -- Fire a rule for the function
    
    2654 2655
       = do { logger <- getLogger
    
    2655 2656
            ; checkedTick (RuleFired (ruleName rule))
    
    2656
    -       ; let occ_anald_rhs = occurAnalyseExpr rule_rhs
    
    2657
    -                 -- See Note [Occurrence-analyse after rule firing]
    
    2657
    +--       ; let occ_anald_rhs = occurAnalyseExpr rule_rhs
    
    2658
    +--                 -- See Note [Occurrence-analyse after rule firing]
    
    2658 2659
            ; dump logger rule rule_rhs
    
    2659
    -       ; return (Just (ruleArity rule, occ_anald_rhs)) }
    
    2660
    +       ; return (Just (ruleArity rule, rhs_rhs, rule_args)) }
    
    2660 2661
     
    
    2661 2662
       | otherwise  -- No rule fires
    
    2662 2663
       = do { logger <- getLogger
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -22,7 +22,7 @@ module GHC.Core.Opt.Simplify.Utils (
    22 22
     
    
    23 23
             -- The continuation type
    
    24 24
             SimplCont(..), DupFlag(..), FromWhat(..), StaticEnv,
    
    25
    -        isSimplified, contIsStop, contHasArgs,
    
    25
    +        isSimplified, contIsStop,
    
    26 26
             contIsDupable, contResultType, contHoleType, contHoleScaling,
    
    27 27
             contIsTrivial, contArgs, contIsRhs,
    
    28 28
             countArgs, contOutArgs, dropContArgs,
    
    ... ... @@ -33,7 +33,7 @@ module GHC.Core.Opt.Simplify.Utils (
    33 33
             ArgInfo(..), ArgSpec(..), mkArgInfo,
    
    34 34
             addValArgTo, addTyArgTo,
    
    35 35
             argInfoExpr, argSpecArg,
    
    36
    -        pushSimplifiedArgs, pushArgSpecs,
    
    36
    +        pushArgs, pushArgSpecs,
    
    37 37
             isStrictArgInfo, lazyArgContext,
    
    38 38
     
    
    39 39
             abstractFloats,
    
    ... ... @@ -389,13 +389,12 @@ pushArgs _env _dup _fun_ty [] cont
    389 389
       = cont
    
    390 390
     pushArgs env dup fun_ty (arg:args) cont
    
    391 391
       | Type ty <- arg
    
    392
    -  = ApplyToType { sc_hole_ty = fun_ty
    
    393
    -                , sc_arg_ty = ty, sc_env = env
    
    394
    -                , sc_cont = pushArgs env dup (piResultTy fun_ty ty) args }
    
    392
    +  = ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
    
    393
    +              , sc_cont = pushArgs env dup (piResultTy fun_ty ty) args cont }
    
    395 394
       | otherwise
    
    396 395
       = ApplyToVal { sc_dup = dup, sc_hole_ty = fun_ty
    
    397 396
                    , sc_arg = arg, sc_env = env
    
    398
    -               , sc_cont = pushArgs env dup (funResultTy fun_ty) args }
    
    397
    +               , sc_cont = pushArgs env dup (funResultTy fun_ty) args  cont}
    
    399 398
     
    
    400 399
     pushArgSpecs :: SimplEnvIS  -- Barely needed, since sc_dup = Simplified
    
    401 400
                  -> [ArgSpec]   -- In normal, forward order
    
    ... ... @@ -451,11 +450,6 @@ contIsRhs (Stop _ (RhsCtxt is_rec) _) = Just is_rec
    451 450
     contIsRhs (CastIt { sc_cont = k })    = contIsRhs k   -- For f = e |> co, treat e as Rhs context
    
    452 451
     contIsRhs _                           = Nothing
    
    453 452
     
    
    454
    --------------------
    
    455
    -contHasArgs (ApplyToTy {})  = True
    
    456
    -contHasArgs (ApplyToVal {}) = True
    
    457
    -contHasArgs _               = False
    
    458
    -
    
    459 453
     -------------------
    
    460 454
     contIsStop :: SimplCont -> Bool
    
    461 455
     contIsStop (Stop {}) = True
    

  • compiler/GHC/Core/Opt/SpecConstr.hs
    ... ... @@ -2906,8 +2906,8 @@ betterPat is (CP { cp_qvars = vs1, cp_args = as1 })
    2906 2906
                  (CP { cp_qvars = vs2, cp_args = as2 })
    
    2907 2907
       | equalLength as1 as2
    
    2908 2908
       = case matchExprs ise vs1 as1 as2 of
    
    2909
    -      Just (_, ms) -> all exprIsTrivial ms
    
    2910
    -      Nothing      -> False
    
    2909
    +      Just (ms,_,_) -> all exprIsTrivial ms
    
    2910
    +      Nothing       -> False
    
    2911 2911
     
    
    2912 2912
       | otherwise -- We must handle patterns of unequal length separately (#24282)
    
    2913 2913
       = False  -- For the pattern with more args, the last arg is "interesting"
    

  • compiler/GHC/Core/Opt/Specialise.hs
    ... ... @@ -1801,7 +1801,7 @@ alreadyCovered :: SpecEnv
    1801 1801
     alreadyCovered env bndrs fn args is_active rules
    
    1802 1802
       = case specLookupRule env fn args is_active rules of
    
    1803 1803
           Nothing             -> False
    
    1804
    -      Just (rule, _)
    
    1804
    +      Just (rule, _,_)
    
    1805 1805
             | isAutoRule rule -> -- Discard identical rules
    
    1806 1806
                                  -- We know that (fn args) is an instance of RULE
    
    1807 1807
                                  -- Check if RULE is an instance of (fn args)
    
    ... ... @@ -1820,7 +1820,8 @@ specLookupRule env fn args is_active rules
    1820 1820
       | null rules
    
    1821 1821
       = Nothing    -- Saves building a few thunks in the common case
    
    1822 1822
       | otherwise
    
    1823
    -  = lookupRule ropts in_scope_env is_active fn args rules
    
    1823
    +  = case lookupRule ropts in_scope_env is_active fn args rules of
    
    1824
    +      Just (rule, rule_rhs, rule_args) -> Just (rule, mkApps rule_rhs rule_args)
    
    1824 1825
       where
    
    1825 1826
         dflags       = se_dflags env
    
    1826 1827
         in_scope     = substInScopeSet (se_subst env)
    

  • compiler/GHC/Core/Rules.hs
    ... ... @@ -9,7 +9,7 @@
    9 9
     -- The 'CoreRule' datatype itself is declared elsewhere.
    
    10 10
     module GHC.Core.Rules (
    
    11 11
             -- ** Looking up rules
    
    12
    -        lookupRule, matchExprs, ruleLhsIsMoreSpecific,
    
    12
    +        RuleMatch(..), lookupRule, matchExprs, ruleLhsIsMoreSpecific,
    
    13 13
     
    
    14 14
             -- ** RuleBase, RuleEnv
    
    15 15
             RuleBase, RuleEnv(..), mkRuleEnv, emptyRuleEnv,
    
    ... ... @@ -542,6 +542,23 @@ map.
    542 542
     ************************************************************************
    
    543 543
     -}
    
    544 544
     
    
    545
    +data RuleMatch
    
    546
    +  = RM { rm_rule  :: CoreRule
    
    547
    +       , rm_rhs   :: CoreExpr
    
    548
    +       , rm_args  :: [CoreExpr]
    
    549
    +       , rm_binds :: BindWrapper   -- Floated let-bindings
    
    550
    +                                   -- See Note [Matching lets]
    
    551
    +       , rm_bndrs :: [Var]         -- Binders of rm_binds
    
    552
    +       }
    
    553
    +  -- E.g. match  r = RULE forall x,y. f (Just (y,x)) = g x y True
    
    554
    +  --      target f (let v = ev in Just (ey, ex)) ez
    
    555
    +  -- We get the RuleMatch
    
    556
    +  --    RMM { rm_rule = r, rm_rhs = \xy. g x y True
    
    557
    +  --        , rm_args = [ex, ey]
    
    558
    +  --        , rm_binds = Let v=ev, rm_bndrs = [v] )
    
    559
    +  -- The leftover `ez` is not returned; the caller is responsible for
    
    560
    +  -- counting (ruleArity r) arguments
    
    561
    +
    
    545 562
     -- | The main rule matching function. Attempts to apply all (active)
    
    546 563
     -- supplied rules to this instance of an application in a given
    
    547 564
     -- context, returning the rule applied and the resulting expression if
    
    ... ... @@ -552,7 +569,7 @@ lookupRule :: HasDebugCallStack
    552 569
                -> Id -- Function head
    
    553 570
                -> [CoreExpr] -- Args
    
    554 571
                -> [CoreRule] -- Rules
    
    555
    -           -> Maybe (CoreRule, CoreExpr)
    
    572
    +           -> Maybe RuleMatch
    
    556 573
     
    
    557 574
     -- See Note [Extra args in the target]
    
    558 575
     -- See comments on matchRule
    
    ... ... @@ -564,17 +581,17 @@ lookupRule opts rule_env@(ISE in_scope _) is_active fn args rules
    564 581
       where
    
    565 582
         rough_args = map roughTopName args
    
    566 583
     
    
    567
    -    -- Strip ticks from arguments, see Note [Tick annotations in RULE
    
    568
    -    -- matching]. We only collect ticks if a rule actually matches -
    
    584
    +    -- Strip ticks from arguments, see Note [Tick annotations in RULE matching]
    
    585
    +    -- We only collect ticks if a rule actually matches -
    
    569 586
         -- this matters for performance tests.
    
    570 587
         args' = map (stripTicksTopE tickishFloatable) args
    
    571 588
         ticks = concatMap (stripTicksTopT tickishFloatable) args
    
    572 589
     
    
    573
    -    go :: [(CoreRule,CoreExpr)] -> [CoreRule] -> [(CoreRule,CoreExpr)]
    
    590
    +    go :: [RuleMatch] -> [CoreRule] -> [RuleMatch]
    
    574 591
         go ms [] = ms
    
    575 592
         go ms (r:rs)
    
    576
    -      | Just e <- matchRule opts rule_env is_active fn args' rough_args r
    
    577
    -      = go ((r,mkTicks ticks e):ms) rs
    
    593
    +      | 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
    
    578 595
           | otherwise
    
    579 596
           = -- pprTrace "match failed" (ppr r $$ ppr args $$
    
    580 597
             --   ppr [ (arg_id, maybeUnfoldingTemplate unf)
    
    ... ... @@ -583,35 +600,38 @@ lookupRule opts rule_env@(ISE in_scope _) is_active fn args rules
    583 600
             --       , isCheapUnfolding unf] )
    
    584 601
             go ms rs
    
    585 602
     
    
    586
    -findBest :: InScopeSet -> (Id, [CoreExpr])
    
    587
    -         -> (CoreRule,CoreExpr) -> [(CoreRule,CoreExpr)] -> (CoreRule,CoreExpr)
    
    603
    +findBest :: InScopeSet
    
    604
    +         -> (Id, [CoreExpr])   -- Target, just for overlap reporting
    
    605
    +         -> RuleMatch          -- Most specific so far
    
    606
    +         -> [RuleMatch]
    
    607
    +         -> RuleMatch
    
    588 608
     -- All these pairs matched the expression
    
    589 609
     -- Return the pair the most specific rule
    
    590 610
     -- The (fn,args) is just for overlap reporting
    
    591 611
     
    
    592
    -findBest _        _      (rule,ans)   [] = (rule,ans)
    
    593
    -findBest in_scope target (rule1,ans1) ((rule2,ans2):prs)
    
    594
    -  | ruleIsMoreSpecific in_scope rule1 rule2 = findBest in_scope target (rule1,ans1) prs
    
    595
    -  | ruleIsMoreSpecific in_scope rule2 rule1 = findBest in_scope target (rule2,ans2) prs
    
    596
    -  | debugIsOn = let pp_rule rule
    
    612
    +findBest _        _      rm   [] = rm
    
    613
    +findBest in_scope target rm1 (rm2: rms)
    
    614
    +  | ruleIsMoreSpecific in_scope rm1 rm2 = findBest in_scope target rm1 rms
    
    615
    +  | ruleIsMoreSpecific in_scope rm2 rm1 = findBest in_scope target rm2 rms
    
    616
    +  | debugIsOn = let pp_rule (RM { rm_rule = rule })
    
    597 617
                           = ifPprDebug (ppr rule)
    
    598 618
                                        (doubleQuotes (ftext (ruleName rule)))
    
    599 619
                     in pprTrace "Rules.findBest: rule overlap (Rule 1 wins)"
    
    600 620
                              (vcat [ whenPprDebug $
    
    601 621
                                      text "Expression to match:" <+> ppr fn
    
    602 622
                                      <+> sep (map ppr args)
    
    603
    -                               , text "Rule 1:" <+> pp_rule rule1
    
    604
    -                               , text "Rule 2:" <+> pp_rule rule2]) $
    
    605
    -                findBest in_scope target (rule1,ans1) prs
    
    606
    -  | otherwise = findBest in_scope target (rule1,ans1) prs
    
    623
    +                               , text "Rule 1:" <+> pp_rule rm1
    
    624
    +                               , text "Rule 2:" <+> pp_rule rm2]) $
    
    625
    +                findBest in_scope target rm1 rms
    
    626
    +  | otherwise = findBest in_scope target rm1 rms
    
    607 627
       where
    
    608 628
         (fn,args) = target
    
    609 629
     
    
    610
    -ruleIsMoreSpecific :: InScopeSet -> CoreRule -> CoreRule -> Bool
    
    630
    +ruleIsMoreSpecific :: InScopeSet -> RuleMatch -> RuleMatch -> Bool
    
    611 631
     -- The call (rule1 `ruleIsMoreSpecific` rule2)
    
    612 632
     -- sees if rule2 can be instantiated to look like rule1
    
    613 633
     -- See Note [ruleIsMoreSpecific]
    
    614
    -ruleIsMoreSpecific in_scope rule1 rule2
    
    634
    +ruleIsMoreSpecific in_scope (RM { rm_rule = rule1 }) (RM { rm_rule = rule2 })
    
    615 635
       = case rule1 of
    
    616 636
            BuiltinRule {} -> False
    
    617 637
            Rule { ru_bndrs = bndrs1, ru_args = args1 }
    
    ... ... @@ -682,7 +702,7 @@ start, in general eta expansion wastes work. SLPJ July 99
    682 702
     matchRule :: HasDebugCallStack
    
    683 703
               => RuleOpts -> InScopeEnv -> (ActivationGhc -> Bool)
    
    684 704
               -> Id -> [CoreExpr] -> [Maybe Name]
    
    685
    -          -> CoreRule -> Maybe CoreExpr
    
    705
    +          -> CoreRule -> Maybe RuleMatch
    
    686 706
     
    
    687 707
     -- If (matchRule rule args) returns Just (name,rhs)
    
    688 708
     -- then (f args) matches the rule, and the corresponding
    
    ... ... @@ -708,26 +728,7 @@ matchRule :: HasDebugCallStack
    708 728
     --
    
    709 729
     -- NB: The 'surplus' argument e4 in the input is simply dropped.
    
    710 730
     -- See Note [Extra args in the target]
    
    711
    -
    
    712
    -matchRule opts rule_env _is_active fn args _rough_args
    
    713
    -          (BuiltinRule { ru_try = match_fn })
    
    714
    -  | not (roBuiltinRules opts) = Nothing
    
    715
    -  | otherwise                 = match_fn opts rule_env fn args
    
    716
    -
    
    717
    -matchRule _ rule_env is_active _ args rough_args
    
    718
    -          (Rule { ru_name = rule_name, ru_act = act, ru_rough = tpl_tops
    
    719
    -                , ru_bndrs = tpl_vars, ru_args = tpl_args, ru_rhs = rhs })
    
    720
    -  | not (is_active act) = Nothing
    
    721
    -  | ruleCantMatch tpl_tops rough_args      = Nothing
    
    722
    -  | otherwise = matchN rule_env rule_name tpl_vars tpl_args args rhs
    
    723
    -
    
    724
    -
    
    725
    ----------------------------------------
    
    726
    -matchN  :: HasDebugCallStack
    
    727
    -        => InScopeEnv
    
    728
    -        -> RuleName -> [Var] -> [CoreExpr]
    
    729
    -        -> [CoreExpr] -> CoreExpr           -- ^ Target; can have more elements than the template
    
    730
    -        -> Maybe CoreExpr
    
    731
    +--
    
    731 732
     -- For a given match template and context, find bindings to wrap around
    
    732 733
     -- the entire result and what should be substituted for each template variable.
    
    733 734
     --
    
    ... ... @@ -738,24 +739,43 @@ matchN :: HasDebugCallStack
    738 739
     -- trailing ones, returning the result of applying the rule to a prefix
    
    739 740
     -- of the actual arguments.
    
    740 741
     
    
    741
    -matchN ise _rule_name tmpl_vars tmpl_es target_es rhs
    
    742
    -  = do { (bind_wrapper, matched_es) <- matchExprs ise tmpl_vars tmpl_es target_es
    
    743
    -       ; return (bind_wrapper $
    
    744
    -                 mkLams tmpl_vars rhs `mkApps` matched_es) }
    
    742
    +matchRule opts rule_env _is_active fn args _rough_args
    
    743
    +          rule@(BuiltinRule { ru_try = match_fn })
    
    744
    +  = do { guard (roBuiltinRules opts)
    
    745
    +       ; rhs <- match_fn opts rule_env fn args
    
    746
    +       ; return (RM { rm_rule = rule
    
    747
    +                    , rm_rhs = rhs
    
    748
    +                    , rm_args = []
    
    749
    +                    , rm_binds = id
    
    750
    +                    , rm_bndrs = [] }) }
    
    751
    +
    
    752
    +matchRule _opts rule_env is_active _fn target_es rough_args
    
    753
    +          rule@(Rule { ru_act = act, ru_rough = tpl_tops
    
    754
    +                     , ru_bndrs = tpl_vars, ru_args = tpl_args, ru_rhs = rhs })
    
    755
    +  | not (is_active act)
    
    756
    +  = Nothing
    
    757
    +  | ruleCantMatch tpl_tops rough_args
    
    758
    +  = Nothing
    
    759
    +  | otherwise
    
    760
    +  = do { (matched_es, bind_wrapper, wrap_bndrs)
    
    761
    +            <- matchExprs rule_env tpl_vars tpl_args target_es
    
    762
    +
    
    763
    +        ; return (RM { rm_rule  = rule
    
    764
    +                     , rm_rhs   = mkLams tpl_vars rhs
    
    765
    +                     , rm_args  = matched_es
    
    766
    +                     , rm_binds = bind_wrapper
    
    767
    +                     , rm_bndrs = wrap_bndrs }) }
    
    745 768
     
    
    746 769
     matchExprs :: HasDebugCallStack
    
    747 770
                => InScopeEnv -> [Var] -> [CoreExpr] -> [CoreExpr]
    
    748
    -           -> Maybe (BindWrapper, [CoreExpr])  -- 1-1 with the [Var]
    
    771
    +           -> Maybe ( [CoreExpr]  -- 1-1 with the incoming [Var]
    
    772
    +                    , BindWrapper, [Var])  -- Floated binds
    
    749 773
     matchExprs (ISE in_scope id_unf) tmpl_vars tmpl_es target_es
    
    750 774
       = do  { rule_subst <- match_exprs init_menv emptyRuleSubst tmpl_es target_es
    
    751 775
             ; let (_, matched_es) = mapAccumL (lookup_tmpl rule_subst)
    
    752 776
                                               (mkEmptySubst in_scope) $
    
    753 777
                                     tmpl_vars `zip` tmpl_vars1
    
    754
    -
    
    755
    -        ; let bind_wrapper = rs_binds rule_subst
    
    756
    -                             -- Floated bindings; see Note [Matching lets]
    
    757
    -
    
    758
    -        ; return (bind_wrapper, matched_es) }
    
    778
    +        ; return (matched_es, rs_binds rule_subst, rs_bndrs rule_subst) }
    
    759 779
       where
    
    760 780
         (init_rn_env, tmpl_vars1) = mapAccumL rnBndrL (mkRnEnv2 in_scope) tmpl_vars
    
    761 781
                       -- See Note [Cloning the template binders]
    

  • utils/check-exact/Utils.hs
    ... ... @@ -556,7 +556,7 @@ isSymbolRdrName n = isSymOcc $ rdrNameOcc n
    556 556
     
    
    557 557
     rdrName2String :: RdrName -> String
    
    558 558
     rdrName2String r =
    
    559
    -  case isExact_maybe r of
    
    559
    +  case rdrNameExactName_maybe r of
    
    560 560
         Just n  -> name2String n
    
    561 561
         Nothing ->
    
    562 562
           case r of