【问题标题】:Partial evaluation/specialization with LLVM-gcc or gcc使用 LLVM-gcc 或 gcc 进行部分评估/专业化
【发布时间】:2011-03-03 20:24:43
【问题描述】:

我对 c/c++ 的(部分)编译时评估很感兴趣(不是像 c++ 中那样使用模板参数)。让我们考虑以下情况(取自 [1]):

double mypower(double x, int n) {
  int i;
  double ret = x;
  for (i = 1; i < n; i++) {
    ret *= x;
  }
  return ret;
}

然后你在代码的某处调用这个函数:

mypower(x,3); // y varies all the time, 

然后编译器可以对此进行优化(例如循环展开)。我使用的一些经常使用的函数可以真正从优化中受益(通过手动创建专用函数进行测试)。演示文稿 [1] 描述了一个过程,其中函数被搜索并被函数的专用版本替换。这似乎有效。但是好像不是很通用,要替换的功能需要写代码。

演示文稿似乎是 2008 年的,我找不到比此来源更多的信息。那么从那以后有什么改善吗?我更喜欢某种自动化,它对可能由属性语法控制的所有功能(例如__attribute__(peval)...)执行相同的操作。此外,我希望同样适用于面向对象的代码,为不同的对象创建专门的类([2] 似乎表明这是不可能的)。

此外,我希望这种专业化不仅适用于代码中的常量。我正在考虑编译为 LLVM IR(字节码)的程序可以执行以下操作:

  1. 在解释器的初始化阶段运行程序,在初始化阶段,程序可以从文件中读取一些配置。初始化后解释器停止。

  2. 从那时起,某些变量(包括成员变量)是固定的。提取这些变量(例如在编译期间由属性标记)。

  3. 创建专门的函数和类。将这些克隆到字节码中。

  4. 运行 JIT 以创建本机机器代码。

这是我要求的很多,只有少数计算密集型程序会从这种优化中受益。但有些人一定在努力。我可能只是不知道为谷歌提供信息的正确搜索词。

注意:请不要建议带有非类型参数或手动专业化的模板类,我已经这样做了。我只是希望编译器为我完成这项工作。

链接:

[1]Presentation how to partial evaluate in LLVM

[2]Forum message about partial evaluation

【问题讨论】:

标签: c++ optimization partial llvm evaluation


【解决方案1】:

这主要是在过程间优化领域。 llvm 有一些,特别是 IP 常量传播,只有在翻译单元中的所有调用站点都使用 mypower(x, 3) 时才会有帮助。你所描述的是可能的,但还没有真正做到。改进 IPCP 通行证是您想要考虑做的事情 - 通过在特定调用站点克隆和专门化一个功能。如果你有足够的翻译单元,这可能会导致一些相当大的代码膨胀,但这就是人们没有真正考虑这样做的原因。

当您可以查看程序中的所有调用时,这在 LTO 级别可能会有更多用途。

【讨论】:

    【解决方案2】:

    您可以使用源到源的转换来做到这一点。

    我们的DMS Software Reengineering Toolkit 可以用来实现这一点。 DMS 使用显式语言定义将源代码解析为 AST,将 AST 漂亮地打印回源代码,提供各种符号表、控制/数据流功能,并提供转换能力,使人们能够构建自定义源代码转换器。 DMS 拥有many front ends for differenct languages,包括带有完整预处理器的 C 和 C++。

    要使用 DMS 完成任务,您将使用 C 解析器来解析系统的所有代码(因为您必须检查所有调用站点是否有任何部分特化)。您需要定义一种方法来指定您希望的部分评估;正如您所建议的,一种方法是编写一个带有绑定到常量的参数的函数调用,但是您可以将其概括为绑定到任意表达式的参数。这样的规范可以由 DMS 的模式解析器解析,它可以处理任意语言的非终结符,例如,函数调用:-} 你需要将这些规范停放在某个地方;可能作为附加的外部文件,或者作为相关呼叫站点处或附近的 cmets。

    通过对部分评估规范的解析,您需要查找函数调用名称以确定实际感兴趣的函数;它位于源堆栈中的某个位置,符号表将使这很容易找到。 给定一个具有专业化的调用站点,可以复制已识别函数的 AST 并替换参数;可能只使用少量的转换,但您必须注意被专门化的函数内的词法范围捕获参数。解决这个问题可能需要额外的转换。 在为指定函数生成一个新名称和缩短的参数列表后,您将在原始函数定义站点附近重新插入其 AST,适当地修改调用站点,并吐出修改后的 AST。无论您是想为特殊情况的展开循环添加额外的转换,还是您感兴趣的任何其他内容,都是实用的。

    DMS 已被用于对 C 和 C++ 代码进行大量转换;这似乎“技术上”很容易。熟悉像 DMS 这样的工具是一件小事;那里有一个公平的学习曲线。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多