2011-03-03 53 views
5

我对c/C++(不包含像C++中的模板参数)的(部分)编译时评估充满信心。让我们考虑下面的情况下(从[1]取):使用LLVM-gcc或gcc进行部分评估/专业化

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. 期间初始化阶段期间,在解释的初始化阶段运行PROGRAMM,该程序可以从文件中读取一些配置。初始化后解释器停止。

  2. 从那时起,一些变量(包括成员变量)被修复。提取这些变量(例如,在编译过程中用属性标记)。

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

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

这是我要求的很多,只有很少的计算密集型程序会从这样的优化中受益。但有些人必须在这方面努力。我可能只是不知道正确的搜索条件来提供谷歌。

注意:请不要使用非类型参数或手动专业化建议模板类,我已经这样做了。我只是喜欢编译器为我做的工作。

链接:

[1] Presentation how to partial evaluate in LLVM

[2] Forum message about partial evaluation

+0

有点相关:http://stackoverflow.com/questions/2940367/what-is-more-efficient-using-pow-to-square-or-just-multiply-it-with-itself/2940800#2940800 – 2011-03-03 20:59:28

回答

1

这在很大程度上是在间优化的竞技场。 llvm有其中的一些,尤其是IP常量传播,这只有在翻译单元中的所有呼叫站点使用mypower(x,3)时才有所帮助。你所描述的是可能的,但还没有真正完成。改善IPCP通行证是你想要做的 - 通过在特定的呼叫站点克隆和专门化一个功能。如果你有足够的翻译单元,这可能会导致一些非常大的代码膨胀,这就是为什么人们没有真正考虑过这样做。

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

0

您可以使用源到源转换来执行此操作。

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

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

使用partial-eval规范的解析,您需要查找函数调用名称以确定感兴趣的实际函数;它在这个源码堆栈中的某个地方,符号表将使这个很容易找到。 给定一个具有专业化的调用站点,可以复制所标识函数的AST并替换参数;可能只使用少量的转换,但您必须留意捕捉通过专用函数内的词法作用域进行的争论。绕过这可能需要额外的转换。 在确定指定函数的新名称和缩短参数列表之后,您需要在原函数定义站点附近重新插入AST,适当修改调用站点,然后吐出修改后的AST。无论你想添加额外的变换来展开特殊情况下的循环,还是其他你感兴趣的东西,都是实用的。

已使用DMS对C和C++代码进行大规模转换;这看起来“技术上”很容易。有一个小问题就是熟悉像DMS这样的工具;那里有一个公平的学习曲线。