如何合并Hoopl图块/如何通过块

时间:2011-08-20 18:14:35

标签: haskell compiler-optimization compiler-theory hoopl

我正在尝试将Hoopl引入某些编译器并遇到一些问题:创建 Hoopl的图形使节点按引入的标签顺序出现。

例如:

(define (test) (if (eq? (random) 1 ) 2 (if (eq? (random) 2 ) 3 0) ) )

“编译”到

L25:    call-direct random  -> _tmp7_6
    branch L27
L26:    return RETVAL
L27:    iconst 1 _tmp8_7
    branch L28
L28:    call-direct eq? _tmp7_6, _tmp8_7 -> _tmp4_8
    branch L29
L29:    cond-branch _tmp4_8 L30 L31
L30:    iconst 2 RETVAL
    branch L26
L31:    call-direct random  -> _tmp12_10
    branch L32
L32:    iconst 2 _tmp13_11
    branch L33
L33:    call-direct eq? _tmp12_10, _tmp13_11 -> _tmp9_12
    branch L34
L34:    cond-branch _tmp9_12 L36 L37
L35:    assign RETVAL _tmp6_15
    branch L26
L36:    iconst 3 _tmp6_15
    branch L35
L37:    iconst 0 _tmp6_15
    branch L35

指令的顺序(按showGraph的顺序)很奇怪,因为顺序 从AST建立的递归图形。为了生成代码,我需要以更自然的方式重新排序块,比如将RETVAL返回到函数的末尾,合并这样的块

    branch Lx:
Lx: ...

进入一个区块,依此类推。似乎我需要这样的东西:

block1 = get block
Ln = get_last jump
block2 = find block Ln
if (some conditions) 
    remove block2
    replace blick1 (merge block1 block2)

我完全很困惑如何用Hoopl执行此操作。当然,我可能会转储所有节点 然后在Hoopl框架之外执行转换,但我相信这一点 是个坏主意。

可能有人给我任何胶水吗?我没有找到任何有用的例子。在Lambdachine项目中执行类似的操作,但似乎太复杂了。

还有另一个问题。是否有任何意义使所有Call指令非本地? 考虑到Call的实现并没有改变任何本地,这就是重点 变量并始终将控制转移到块的下一条指令?如果调用指令定义为

data Insn e x where
   Call :: [Expr] -> Expr -> Label :: Insn O C -- last instruction of the block

导致图形看起来更奇怪。所以我用

-- what the difference with any other primitive, like "add a b -> c" 
Call :: [Expr] -> Expr -> Label :: Insn O O 

我可能错了吗?

2 个答案:

答案 0 :(得分:2)

可以使用HOOPL实现“块合并”。你的问题太笼统了,所以我给你一个计划:

  1. 确定此优化所需的分析类型(向前或向后)
  2. 设计分析点阵
  3. 设计转移功能
  4. 设计重写功能
  5. 创建传递
  6. 将传球与同一方向的其他传球合并,使它们交错
  7. 使用燃料运行通行证
  8. 将优化的图表转换回您需要的表格
  9. 您遇到哪些问题?一旦你阅读了论文,步骤1和2应该是相当简单的。

    您还应该理解basic block的一般概念 - 为什么指令被合并到块中,为什么控制流图由块而不是单个指令组成,为什么分析是在块上而不是在单个指令上执行的。< / p>

    您的重写函数应使用事实来重写块中的最后一个节点。因此,事实格子不仅应该包括“有关可达性的信息”,还应该包括目标块本身。

答案 1 :(得分:2)

我发现并尝试了几种方法来解决这个问题:

  1. 使用foldBlockNodesF3函数或其他foldBlockNodes ...函数
  2. 使用preorder_dfs *函数(如在Lambdachine项目中)
  3. 从头开始用较大的块构建图表
  4. 最后一个选项对我没用,因为FactBase与标签链接,因此每个更改变量活跃度的指令都应该有一个标签供以下分析使用。

    所以,我的最终解决方案是使用foldBlockNodesF3函数并线性化图形并手动删除额外标签并同时进行寄存器分配