2013-02-26 141 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