﻿id summary reporter owner description type status priority milestone component version resolution keywords cc os architecture failure testcase blockedby blocking related differential wikipage 16335 Make CPR Analysis more aggressive for inductive cases sgraf "While investigating the generated Core for a simple toy benchmark, I came up with the following minimal example: {{{#!hs data Expr = Lit Int | Plus Expr Expr eval :: Expr -> Int eval (Lit n) = n eval (Plus a b) = eval a + eval b }}} resulting in the following Core: {{{ eval = \ (ds_d112 :: Expr) -> case ds_d112 of { Lit n_aXf -> n_aXf; Plus a_aXg b_aXh -> case eval a_aXg of { GHC.Types.I# x_a1bK -> case eval b_aXh of { GHC.Types.I# y_a1bO -> GHC.Types.I# (GHC.Prim.+# x_a1bK y_a1bO) } } } }}} Note that this needlessly unboxes and boxes primitive Ints. Lifting this is precisely the job of CPR, but `eval` doesn't exactly have the CPR property: the `Lit` case doesn't return a product. But we're punishing ourselves for the base case when ''even the function itself'' recurses multiple times! The code resulting from WWing here wouldn't even look bad in the `Lit` case: {{{ Foo.$weval = \ (w_s1cn :: Expr) -> case w_s1cn of { Lit dt_d11b -> case dt_d11b { I# ds_abcd -> ds_abcd }; Plus a_aXf b_aXg -> case Foo.$weval a_aXf of ww_s1cq { __DEFAULT -> case Foo.$weval b_aXg of ww1_X1dh { __DEFAULT -> GHC.Prim.+# ww_s1cq ww1_X1dh } } } eval = \ (w_s1cn :: Expr) -> case Foo.$weval w_s1cn of ww_s1cq { __DEFAULT -> GHC.Types.I# ww_s1cq } }}} Granted, this is bad for the case where there is no recursion happening and we need the result of `eval` boxed, but that's a small price to pay IMO. I begin to think of CPR more of as the ""dual"" to SpecConstr than to Strictness Analysis. Return pattern specialisation, so to speak." task new normal ⊥ Compiler 8.6.3 CPRAnalysis Unknown/Multiple Unknown/Multiple None/Unknown