【问题标题】:How to identify similar expressions for automatic function extraction?如何识别用于自动函数提取的相似表达式?
【发布时间】:2015-01-18 16:49:48
【问题描述】:

如何识别 AST 的结构上常见的子树,以便将它们分解为单独的函数?

例如给定这个伪代码(假设该语言只允许纯的终止函数):

f(a, b, c) {
    return (a + b) * c * 6;
}

g(x[4], k) {
    var y[4];
    for (i in 0..3)
        y[i] = f(x[i], 1, k);
    return y;
}

varying arr[4];
result = g(arr, 1);

...在完全特化和内联之后,我们将得到以下表示程序结果值的原始操作树:

(make-vec4
    (* (arr 0) 6)
    (* (+ (arr 1) 1) 6)
    (* (+ (arr 2) 1) 6)
    (* (+ (arr 3) 1) 6) )

(这是一个糟糕的例子,因为扩展结果在结构上仍然与输入非常相似...假设更改可以传播到输入代码的结构边界)

人眼很明显,结果树包含三个相似的表达式,我们现在可以将它们重构为对 fn(i) { return 6 * (arr[i] + 1); } 之类的函数的调用,因为 instruction cache size mumble mumble etc(或更现实地利用例如mapfold 原语)。但是编译器如何将它们识别为相似,以便将它们视为提取的候选对象?

消除 相同的 子表达式应该很容易,使用类似 hash-consing 的方法。但是你不能用它来解决这个问题,因为从叶子向上移动构建的哈希不会以任何方式相互关联。有没有办法从根节点“构建”并确定两个表达式树之间的分歧点,看看分支在哪里成为参数? (没有使用任何关于原始程序形式的知识,假设它已经扩展得面目全非,而且无论如何可能没有被最佳分割)

感觉应该有办法通过排序子树和比较邻居来做到这一点,但这需要某种与元素位置无关的排序......?

【问题讨论】:

    标签: compiler-construction inline compiler-optimization


    【解决方案1】:

    您要做的就是所谓的“克隆检测”。您特别想要做的是检测抽象语法树上的克隆。

    这篇(由我撰写的)技术论文是(上次我查看的)关于如何执行此操作的引用最多的论文:Clone Detection Using Abstract Syntax Trees

    有一个基于这种方法的商业工具,称为 CloneDR。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 2023-02-24
      • 2022-06-24
      • 2019-08-03
      • 1970-01-01
      • 2020-06-18
      相关资源
      最近更新 更多