2013-02-26 62 views
16

我有以下程序将6位ASCII转换为二进制格式。GHC生成冗余核心操作

ascii2bin :: Char -> B.ByteString 
ascii2bin = B.reverse . fst . B.unfoldrN 6 decomp . to6BitASCII -- replace to6BitASCII with ord if you want to compile this 
    where decomp n = case quotRem n 2 of (q,r) -> Just (chr r,q) 

bs2bin :: B.ByteString -> B.ByteString 
bs2bin = B.concatMap ascii2bin 

这产生以下核心段:

Rec { 
$wa 
$wa = 
    \ ww ww1 ww2 w -> 
    case ww2 of wild { 
     __DEFAULT -> 
     let { 
      wild2 
      wild2 = remInt# ww1 2 } in 
     case leWord# (int2Word# wild2) (__word 1114111) of _ { 
      False -> (lvl2 wild2) `cast` ...;                     
      True -> 
      case writeWord8OffAddr# 
        ww 0 (narrow8Word# (int2Word# (ord# (chr# wild2)))) w 
      of s2 { __DEFAULT -> 
      $wa (plusAddr# ww 1) (quotInt# ww1 2) (+# wild 1) s2 
      } 
     }; 
     6 -> (# w, (lvl, lvl1, Just (I# ww1)) #) 
    } 
end Rec } 

通知,ord . chr == id等方面存在是多余的操作这里:narrow8Word# (int2Word# (ord# (chr# wild2)))

是否有一个原因GHC被不必要地从int转换 - > Char - > Int,或者这是一个糟糕的代码生成的例子?这可以优化出来吗?

编辑:这是使用GHC 7.4.2,我还没有尝试编译与任何其他版本。我后来发现问题仍然存在于GHC 7.6.2中,但冗余操作在github的当前HEAD分支中被删除。

回答

19

是不是有一个原因GHC是不必要地从Int -> Char -> Int转换,或者这是一个糟糕的代码生成的例子?这可以优化出来吗?

不是(对两者)。你从-ddump-simpl获得的核心不是结局。在汇编代码的路上,还有一些优化和转换仍然完成。但是,在这里删除多余的转换实际上并不是一个优化。

它们可以在核心和程序集之间被删除。关键是这些首饰 - 除了缩小之外 - 没有任何操作,它们只存在于核心,因为它是打字的。由于它们是无操作的,核心中是否有冗余链条并不重要。

其7.6.1从代码产生的组件[它比7.4.2产生更可读的,所以采取] - 用的ord代替to6BitASCII - 是

ASCII.$wa_info: 
_cXT: 
    addq $64,%r12 
    cmpq 144(%r13),%r12 
    ja _cXX 
    movq %rdi,%rcx 
    cmpq $6,%rdi 
    jne _cXZ 
    movq $GHC.Types.I#_con_info,-56(%r12) 
    movq %rsi,-48(%r12) 
    movq $Data.Maybe.Just_con_info,-40(%r12) 
    leaq -55(%r12),%rax 
    movq %rax,-32(%r12) 
    movq $(,,)_con_info,-24(%r12) 
    movq $lvl1_rVq_closure+1,-16(%r12) 
    movq $lvl_rVp_closure+1,-8(%r12) 
    leaq -38(%r12),%rax 
    movq %rax,0(%r12) 
    leaq -23(%r12),%rbx 
    jmp *0(%rbp) 
_cXX: 
    movq $64,192(%r13) 
_cXV: 
    movl $ASCII.$wa_closure,%ebx 
    jmp *-8(%r13) 
_cXZ: 
    movl $2,%ebx 
    movq %rsi,%rax 
    cqto 
    idivq %rbx 
    movq %rax,%rsi 
    cmpq $1114111,%rdx 
    jbe _cY2 
    movq %rdx,%r14 
    addq $-64,%r12 
    jmp GHC.Char.chr2_info 
_cY2: 
    movb %dl,(%r14) 
    incq %r14 
    leaq 1(%rcx),%rdi 
    addq $-64,%r12 
    jmp ASCII.$wa_info 
    .size ASCII.$wa_info, .-ASCII.$wa_info 

的部分,其中narrow8Word# (int2Word# (ord# (chr# wild2)))核心出现在cmpq $1114111, %rdx之后。如果商不超出范围,则代码跳转到_cY2,其中不再包含此类转换。将一个字节写入数组,一些指针/计数器递增,就是这样,跳回顶部。

我认为从GHC中可以生成比GHC更好的代码,但冗余的无操作转换已经消失。

+2

是的,确切地说。这些大多数都是价值层面的噪声,只存在于改变类型。由于Core是键入的,所以这是必需的。 – 2013-02-26 19:19:22