GHC未消除内循环构造函数

时间:2018-08-17 18:31:56

标签: haskell optimization stream ghc

我正在尝试使用不同的代码流融合方法

sum (filter even [0..n])

并达到了我期望构造函数专业化(使用-O2等)的地步,但似乎没有发挥作用。

有了-ddump-simpl,我得到了以下核心:

Rec {
-- RHS size: {terms: 33, types: 10, coercions: 0}
Main.main_go [Occ=LoopBreaker] :: Int -> RangeToState -> Int
[GblId, Arity=2, Caf=NoCafRefs, Str=DmdType]
Main.main_go =
  \ (z_a1Nf :: Int) (s1_a1Ng :: RangeToState) ->
    case s1_a1Ng of _ [Occ=Dead] { RangeToState ipv_s7O5 ipv1_s7O6 ->
    case z_a1Nf of z1_X1NN { GHC.Types.I# ipv2_s7O9 ->
    case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.<# ipv_s7O5 ipv1_s7O6)
    of _ [Occ=Dead] {
      False -> z1_X1NN;
      True ->
        Main.main_go
          (case GHC.Prim.remInt# ipv_s7O5 2# of _ [Occ=Dead] {
             __DEFAULT -> z1_X1NN;
             0# -> GHC.Types.I# (GHC.Prim.+# ipv2_s7O9 ipv_s7O5)
           })
          (Producer.RangeToState (GHC.Prim.+# ipv_s7O5 1#) ipv1_s7O6)
    }
    }
    }
end Rec }

(带有data RangeToState = RangeToState {-# UNPACK #-} !Int {-# UNPACK #-} !Int。)

我本来希望RangeToStateI#被淘汰,并且当我将Core从上面手动转换回基本的Haskell时:

foo2 = \ (z :: Int) (s :: RangeToState) ->
    case s of 
      RangeToState i n -> z `seq` case i < n of
        False -> z
        True -> foo2 (if even i then i + z else z)
          (RangeToState (i+1) n)

确实确实编译成无分配循环:

Rec {
-- RHS size: {terms: 31, types: 6, coercions: 0}
Producer.$wfoo2 [InlPrag=[0], Occ=LoopBreaker]
  :: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int#
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType <L,U><S,U><S,U>]
Producer.$wfoo2 =
  \ (ww_s4gO :: GHC.Prim.Int#)
    (ww1_s4gS :: GHC.Prim.Int#)
    (ww2_s4gT :: GHC.Prim.Int#) ->
    case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.<# ww1_s4gS ww2_s4gT)
    of _ [Occ=Dead] {
      False -> ww_s4gO;
      True ->
        case GHC.Prim.remInt# ww1_s4gS 2# of _ [Occ=Dead] {
          __DEFAULT ->
            Producer.$wfoo2 ww_s4gO (GHC.Prim.+# ww1_s4gS 1#) ww2_s4gT;
          0# ->
            Producer.$wfoo2
              (GHC.Prim.+# ww1_s4gS ww_s4gO) (GHC.Prim.+# ww1_s4gS 1#) ww2_s4gT
        }
    }
end Rec }

我的编译选项仅为ghc -O2 -fforce-recomp -ddump-simpl,并且我正在使用GHC 8.0.2。

是什么阻止第一版代码进一步编译为第二版?

0 个答案:

没有答案