ANF的缺點 [RG5R]

ANF可以保證每個計算都由一系列的let序列化,並且所有operands都一定是values,從而對指令語言後端編譯是好用的表示形式。但ANF也有一些缺點

ANF在 β\beta-reduction 下不封閉 [local-0]

ANF的缺點之一是在 β\beta-reduction 下不封閉,比如

(let (x ((λ (y) M) V)) x)=(let (x M[y:=V]) x)(\text{let}\ (x\ ((\lambda\ (y)\ M)\ V))\ x) = (\text{let}\ (x\ M[y:=V])\ x)

但這個表達式不是合法的ANF,在RHS位置 M[y:=V]M[y:=V] 不被允許出現。這讓ANF β\beta-equivalence必須重新normalize所有commuting conversions

這對最佳化來說是一個缺陷,因為 β\beta-equivalence model了inlining optimizations;而renormalize是不便又昂貴的計算

A2A_2 會導致程式碼指數級的增長 [local-1]

我們可以觀察以下案例套用 A2A_2 的結果

let x := if0 (if0 (if0 0 0 1) 0 1) 0 1
in LARGE

因為continuation E1[♢]E_1[♢] 是 let x := ♢ in LARGE,所以第一次轉換得到

if0 (if0 (if0 0 0 1) 0 1)
  E1[0]
  E1[1]

再來 E2[♢]E_2[♢] 是 if0 ♢ E1[0] E1[1],好吧,那就得到

if0 (if0 0 0 1)
  E2[0]
  E2[1]

再來 E3[♢]E_3[♢] 是 if0 ♢ E2[0] E2[1],所以是

if0 0
  E3[0]
  E3[1]

最後我們攤開來看就得到

if0 0
  if0 0
    if0 0
      let x := 0 in LARGE
      let x := 1 in LARGE
    if0 1
      let x := 0 in LARGE
      let x := 1 in LARGE
  if0 1
    if0 0
      let x := 0 in LARGE
      let x := 1 in LARGE
    if0 1
      let x := 0 in LARGE
      let x := 1 in LARGE

所以3層if的堆疊得到8個 LARGE

到這裡,Bowman就問說,如果ANF有這麼多問題,那麼與其去修復它,為什麼不要禁止 A2A_2 轉換然後允許 let x := if0 V M1 M2 in M 這個形式呢?畢竟這個形式說穿了也就是

begin:
  if0 V
    set! x M1
    set! x M2
  M

這完全是指令語言後端可以接受的程式!事實上,這早就已經是實用編譯器的常見做法

A-normalization對非monadic effect不安全 [local-2]

Bowman舉了letregion作為案例,並認為沒有文獻討論過這個缺陷。注意到Bowman不想重複join point的老路,也就是要避免用local continuation處理這個問題