| ... |
... |
@@ -1631,7 +1631,6 @@ rebuild_go env expr cont |
|
1631
|
1631
|
|
|
1632
|
1632
|
ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
|
|
1633
|
1633
|
, sc_cont = cont, sc_hole_ty = fun_ty }
|
|
1634
|
|
- -- See Note [Avoid redundant simplification]
|
|
1635
|
1634
|
-> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
|
|
1636
|
1635
|
; rebuild_go env (App expr arg') cont }
|
|
1637
|
1636
|
|
| ... |
... |
@@ -1825,7 +1824,10 @@ simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet |
|
1825
|
1824
|
-> MOutCoercion -- Wrap this around the result
|
|
1826
|
1825
|
-> SimplM OutExpr
|
|
1827
|
1826
|
simplArg _ _ _ (Simplified {}) arg mco
|
|
1828
|
|
- = return (mkCastMCo arg mco)
|
|
|
1827
|
+ = -- See Note [Avoiding simplifying repeatedly]
|
|
|
1828
|
+ case mco of
|
|
|
1829
|
+ MRefl -> return arg -- Vastly common case
|
|
|
1830
|
+ MCo co -> return (mkCast arg co)
|
|
1829
|
1831
|
simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco
|
|
1830
|
1832
|
= do { let arg_env' = arg_se `setInScopeFromE` env
|
|
1831
|
1833
|
arg_ty = funArgTy fun_ty
|
| ... |
... |
@@ -2047,94 +2049,6 @@ Simplifier without first calling SimpleOpt, so anything involving |
|
2047
|
2049
|
GHCi or TH and operator sections will fall over if we don't take
|
|
2048
|
2050
|
care here.
|
|
2049
|
2051
|
|
|
2050
|
|
-Note [Avoiding simplifying repeatedly]
|
|
2051
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
2052
|
|
-One way in which we can get exponential behaviour is if we simplify a
|
|
2053
|
|
-big expression, and then re-simplify it -- and then this happens in a
|
|
2054
|
|
-deeply-nested way. So we must be jolly careful about re-simplifying
|
|
2055
|
|
-an expression (#26989).
|
|
2056
|
|
-
|
|
2057
|
|
-Example:
|
|
2058
|
|
- f BIG, where f has a RULE
|
|
2059
|
|
-Then
|
|
2060
|
|
- * We simplify BIG before trying the rule; but the rule does not fire
|
|
2061
|
|
- (forcing this simplification is why we have the RULE in this example)
|
|
2062
|
|
- * We inline f = \x. g x, in `simpl_lam`
|
|
2063
|
|
- * So if `simpl_lam` did preInlineUnconditionally we get (g BIG)
|
|
2064
|
|
- * Now if g has a RULE we'll simplify BIG again, and this whole thing can
|
|
2065
|
|
- iterate.
|
|
2066
|
|
- * However, if `f` did not have a RULE, so that BIG has /not/ already been
|
|
2067
|
|
- simplified, we /want/ to do preInlineUnconditionally in simpl_lam.
|
|
2068
|
|
-
|
|
2069
|
|
-So we go to some effort to avoid repeatedly simplifying the same thing.
|
|
2070
|
|
-Suppose we are in the Plan (AFTER) case of rule application, for a rule
|
|
2071
|
|
- RULE forall x,y. f (x,y) = ...x...
|
|
2072
|
|
-and a call
|
|
2073
|
|
- f (e1,e2)
|
|
2074
|
|
-Then:
|
|
2075
|
|
-
|
|
2076
|
|
-* The (sc_env :: StaticEnv) field of ApplyToVal records if the argument
|
|
2077
|
|
- has been evaluated. See Note [StaticEnv] in GHC.Core.Opt.Simplify.Utils.
|
|
2078
|
|
-
|
|
2079
|
|
-* The rule fires returning
|
|
2080
|
|
- RuleMatch { rm_rhs = (\x y. ...x..), rm_args = [ e1, e2 ] }
|
|
2081
|
|
- We assume that `rm_rhs` has been occ-anal'd by whoever generates
|
|
2082
|
|
- the `RuleMatch`. (We do this once and for all when the rule is born;
|
|
2083
|
|
- see Note [OccInfo in unfoldings and rules].)
|
|
2084
|
|
-
|
|
2085
|
|
-* `fireRuleAFTER` uses `pushOutArgs` to push [ e1, e2 ] back onto the
|
|
2086
|
|
- continuation with sc_env=Simplified NoDup.
|
|
2087
|
|
-
|
|
2088
|
|
-* Beta-reduction fires (in `simpl_lam`) for the \x.
|
|
2089
|
|
-
|
|
2090
|
|
-* Suppose `x occurs many times. Then we want to behave like `let x=e1 in ..`,
|
|
2091
|
|
- but we use `simplArg`, which in turn uses that `sc_env` flag to avoid
|
|
2092
|
|
- re-simplifying `e1`.
|
|
2093
|
|
-
|
|
2094
|
|
-* Suppose `x` occurs just once or not at all; then the call to
|
|
2095
|
|
- `preInlineUnconditionally` in `simpl_lam` will fire, and extend the
|
|
2096
|
|
- substitution with
|
|
2097
|
|
- x :-> DoneEx e1
|
|
2098
|
|
-
|
|
2099
|
|
-* At the /occurrence/ of `x`, the function `simplInId` calls `simplOutExpr`
|
|
2100
|
|
- on `e1`. Calling `simplOutExpr` is critical: it knowns that we have already
|
|
2101
|
|
- simplified `e1` so we must be cautious about doing so again.
|
|
2102
|
|
-
|
|
2103
|
|
- The conservative case for `simplOutExpr` is just to call `rebuild_go`, which
|
|
2104
|
|
- avoids re-simplifying `e1`. But if `e1` turns out to be a lambda, and there
|
|
2105
|
|
- are some arguments, we have a new beta redex so we occurrence-analyse and
|
|
2106
|
|
- zoom off to `simplLam`.
|
|
2107
|
|
-
|
|
2108
|
|
-* We go to some efforts to avoid unnecessarily simplifying ApplyToVal,
|
|
2109
|
|
- in at least two places
|
|
2110
|
|
- - In simplCast/addCoerce, where we check for isReflCo
|
|
2111
|
|
- - We sometimes try rewrite RULES befoe simplifying arguments;
|
|
2112
|
|
- see Note [tryRules: plan (BEFORE)]
|
|
2113
|
|
-
|
|
2114
|
|
-You might wonder (#13379) if the same thing can happen for a deeply-nested
|
|
2115
|
|
-application like
|
|
2116
|
|
- f (f (f ....) ) )
|
|
2117
|
|
-
|
|
2118
|
|
-The danger is that we may
|
|
2119
|
|
-o - Simplify the (big) function argument
|
|
2120
|
|
- - Decide to inline the function
|
|
2121
|
|
- - Then preInilneUnconditionally the argument
|
|
2122
|
|
- - And then re-simplified the big argument
|
|
2123
|
|
-
|
|
2124
|
|
-But in fact we try inlining /before/ simplifying arguments at all, so this can't
|
|
2125
|
|
-really arise. The main way that we get /simplified/ argument on the stack is
|
|
2126
|
|
-through rule application. Once they are there then the above scenario can
|
|
2127
|
|
-happen. But then the mechanism above prevents gratuitous re-simplification.
|
|
2128
|
|
-
|
|
2129
|
|
-
|
|
2130
|
|
-Wrinkles:
|
|
2131
|
|
-
|
|
2132
|
|
-(SR1) All that said /postInlineUnconditionally/ (called in `completeBind`) does
|
|
2133
|
|
- fire in the above (f BIG) situation. See Note [Post-inline for single-use
|
|
2134
|
|
- things] in Simplify.Utils. This certainly risks repeated simplification,
|
|
2135
|
|
- but in practice seems to be a small win.
|
|
2136
|
|
-
|
|
2137
|
|
-
|
|
2138
|
2052
|
************************************************************************
|
|
2139
|
2053
|
* *
|
|
2140
|
2054
|
Join points
|
| ... |
... |
@@ -2702,17 +2616,92 @@ makes a particularly big difference for |
|
2702
|
2616
|
+# 3# (+# 4# 5#)
|
|
2703
|
2617
|
We want this to happen in one pass
|
|
2704
|
2618
|
|
|
2705
|
|
-Note [Avoid redundant simplification]
|
|
2706
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
2707
|
|
-Because RULES often apply to simplified arguments (see Note [Plan (AFTER)]),
|
|
2708
|
|
-there's a danger of simplifying already-simplified arguments. For example,
|
|
2709
|
|
-suppose we have
|
|
2710
|
|
- RULE f (x,y) = $sf x y
|
|
2711
|
|
-and the expression
|
|
2712
|
|
- f (p,q) e1 e2
|
|
2713
|
|
-With Plan (AFTER) by the time the rule fires, we will have already simplified e1, e2,
|
|
2714
|
|
-and we want to avoid doing so a second time. So ApplyToVal records if the argument
|
|
2715
|
|
-is already Simplified.
|
|
|
2619
|
+
|
|
|
2620
|
+Note [Avoiding simplifying repeatedly]
|
|
|
2621
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
2622
|
+One way in which we can get exponential behaviour is if we simplify a
|
|
|
2623
|
+big expression, and then re-simplify it -- and then this happens in a
|
|
|
2624
|
+deeply-nested way. So we must be jolly careful about re-simplifying
|
|
|
2625
|
+an expression (#26989).
|
|
|
2626
|
+
|
|
|
2627
|
+Example:
|
|
|
2628
|
+ f BIG, where f has a RULE
|
|
|
2629
|
+Then
|
|
|
2630
|
+ * We simplify BIG before trying the rule; but the rule does not fire
|
|
|
2631
|
+ (forcing this simplification is why we have the RULE in this example)
|
|
|
2632
|
+ * We inline f = \x. g x, in `simpl_lam`
|
|
|
2633
|
+ * So if `simpl_lam` did preInlineUnconditionally we get (g BIG)
|
|
|
2634
|
+ * Now if g has a RULE we'll simplify BIG again, and this whole thing can
|
|
|
2635
|
+ iterate.
|
|
|
2636
|
+ * However, if `f` did not have a RULE, so that BIG has /not/ already been
|
|
|
2637
|
+ simplified, we /want/ to do preInlineUnconditionally in simpl_lam.
|
|
|
2638
|
+
|
|
|
2639
|
+So we go to some effort to avoid repeatedly simplifying the same thing.
|
|
|
2640
|
+Suppose we are in the Plan (AFTER) case of rule application, for a rule
|
|
|
2641
|
+ RULE forall x,y. f (x,y) = ...x...
|
|
|
2642
|
+and a call
|
|
|
2643
|
+ f (e1,e2)
|
|
|
2644
|
+Then:
|
|
|
2645
|
+
|
|
|
2646
|
+* The (sc_env :: StaticEnv) field of ApplyToVal records if the argument
|
|
|
2647
|
+ has been evaluated. See Note [StaticEnv] in GHC.Core.Opt.Simplify.Utils.
|
|
|
2648
|
+
|
|
|
2649
|
+* The rule fires returning
|
|
|
2650
|
+ RuleMatch { rm_rhs = (\x y. ...x..), rm_args = [ e1, e2 ] }
|
|
|
2651
|
+ We assume that `rm_rhs` has been occ-anal'd by whoever generates
|
|
|
2652
|
+ the `RuleMatch`. (We do this once and for all when the rule is born;
|
|
|
2653
|
+ see Note [OccInfo in unfoldings and rules].)
|
|
|
2654
|
+
|
|
|
2655
|
+* `fireRuleAFTER` uses `pushOutArgs` to push [ e1, e2 ] back onto the
|
|
|
2656
|
+ continuation with sc_env=Simplified NoDup.
|
|
|
2657
|
+
|
|
|
2658
|
+* Beta-reduction fires (in `simpl_lam`) for the \x.
|
|
|
2659
|
+
|
|
|
2660
|
+* Suppose `x occurs many times. Then we want to behave like `let x=e1 in ..`,
|
|
|
2661
|
+ but we use `simplArg`, which in turn uses that `sc_env` flag to avoid
|
|
|
2662
|
+ re-simplifying `e1`.
|
|
|
2663
|
+
|
|
|
2664
|
+* Suppose `x` occurs just once or not at all; then the call to
|
|
|
2665
|
+ `preInlineUnconditionally` in `simpl_lam` will fire, and extend the
|
|
|
2666
|
+ substitution with
|
|
|
2667
|
+ x :-> DoneEx e1
|
|
|
2668
|
+
|
|
|
2669
|
+* At the /occurrence/ of `x`, the function `simplInId` calls `simplOutExpr`
|
|
|
2670
|
+ on `e1`. Calling `simplOutExpr` is critical: it knowns that we have already
|
|
|
2671
|
+ simplified `e1` so we must be cautious about doing so again.
|
|
|
2672
|
+
|
|
|
2673
|
+ The conservative case for `simplOutExpr` is just to call `rebuild_go`, which
|
|
|
2674
|
+ avoids re-simplifying `e1`. But if `e1` turns out to be a lambda, and there
|
|
|
2675
|
+ are some arguments, we have a new beta redex so we occurrence-analyse and
|
|
|
2676
|
+ zoom off to `simplLam`.
|
|
|
2677
|
+
|
|
|
2678
|
+* We go to some efforts to avoid unnecessarily simplifying ApplyToVal,
|
|
|
2679
|
+ in at least two places
|
|
|
2680
|
+ - In simplCast/addCoerce, where we check for isReflCo
|
|
|
2681
|
+ - We sometimes try rewrite RULES befoe simplifying arguments;
|
|
|
2682
|
+ see Note [tryRules: plan (BEFORE)]
|
|
|
2683
|
+
|
|
|
2684
|
+You might wonder (#13379) if the same thing can happen for a deeply-nested
|
|
|
2685
|
+application like
|
|
|
2686
|
+ f (f (f ....) ) )
|
|
|
2687
|
+
|
|
|
2688
|
+The danger is that we may
|
|
|
2689
|
+ - Simplify the (big) function argument
|
|
|
2690
|
+ - Decide to inline the function
|
|
|
2691
|
+ - Then preInilneUnconditionally the argument
|
|
|
2692
|
+ - And then re-simplified the big argument
|
|
|
2693
|
+
|
|
|
2694
|
+But in fact we try inlining /before/ simplifying arguments at all, so this can't
|
|
|
2695
|
+really arise. The main way that we get /simplified/ argument on the stack is
|
|
|
2696
|
+through rule application. Once they are there then the above scenario can
|
|
|
2697
|
+happen. But then the mechanism above prevents gratuitous re-simplification.
|
|
|
2698
|
+
|
|
|
2699
|
+Wrinkles:
|
|
|
2700
|
+
|
|
|
2701
|
+(SR1) All that said /postInlineUnconditionally/ (called in `completeBind`) does
|
|
|
2702
|
+ fire in the above (f BIG) situation. See Note [Post-inline for single-use
|
|
|
2703
|
+ things] in Simplify.Utils. This certainly risks repeated simplification,
|
|
|
2704
|
+ but in practice seems to be a small win.
|
|
2716
|
2705
|
|
|
2717
|
2706
|
Note [Shadowing in the Simplifier]
|
|
2718
|
2707
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|