打开内联程序集参数的即时值传播的特定GCC标志是什么?
考虑以下x86代码示例:打开内联程序集参数的即时值传播的特定GCC标志是什么?,c,gcc,compiler-optimization,inline-assembly,compiler-options,C,Gcc,Compiler Optimization,Inline Assembly,Compiler Options,考虑以下x86代码示例: #include <stdlib.h> static int i; static inline __attribute__((always_inline)) test(int x) { asm volatile("mov %1, %0" : "=r"(i): "i"(x)); } int main(void) { test(5); return i; } 它建造得很好 如果我使用(无优化)构建它: 它在组装阶段失败,因为值'
#include <stdlib.h>
static int i;
static inline __attribute__((always_inline)) test(int x)
{
asm volatile("mov %1, %0" : "=r"(i): "i"(x));
}
int main(void)
{
test(5);
return i;
}
它建造得很好
如果我使用(无优化)构建它:
它在组装阶段失败,因为值'5'
没有作为立即值传播到内联函数测试,所以我们没有通过约束
我希望能够编译此代码,而无需启用其他无关的优化,以使调试更容易
从理论上讲,-O
只是一条捷径,可以同时启用一系列GCC优化选项,这些选项都记录在文档中。不幸的是,我无法找到打开此行为的特定GCC标志
有什么想法吗
澄清:为了消除任何疑问,代码片段只是一个示例。它本身并没有多大意义,除了显示我正在努力做什么。实际用例涉及自定义处理器上的一条指令,该指令只能将一个立即数作为参数,我正试图将其封装在C构造中。一个宏确实可以做到这一点,但它会受到宏的所有常规缩回的影响,因此我试图避免它
更新:对于那些想知道的人来说,宏也不起作用。似乎内联函数在这里根本不起作用。例如,这也不起作用:
void foo (void)
{
int i = 6;
asm volatile ("" : : "i" (i));
}
我还修改了问题标题以反映这一点。看起来像是
-ftree ter
(替换SSA中的临时表达式->正常通行证-不管是什么)实现了以下功能:
gcc -ftree-ter test.c # no errors
我是这样决定的:
gcc-Q--help=optimizers
告诉您默认启用/禁用哪些优化(有些已启用)gcc-O-Q--help=optimizers
告诉您对-O
-O
时才启用的优化,直到其中一个起作用always_inline
是一个奇怪的属性,非常特定于GCC,可能特定于GCC版本(因此GCC 4.5和GCC 4.7的详细行为可能不同)
GCC通过运行大量优化过程来工作(即使在-O0
中,其中一些过程正在运行,否则不会发出任何代码)。通常,一个GCC-O1
编译运行200次优化过程
使用gcc-4.7
您的代码甚至不会在-O0
中编译:
alw.c: In function ‘main’:
alw.c:7:5: warning: asm operand 1 probably doesn’t match constraints [enabled by default]
alw.c:7:5: error: impossible constraint in ‘asm’
为了更好地理解GCC正在做什么,您可以使用GCC-fdump tree all
运行它,对于大多数GCC过程,您将得到一个所谓的“转储文件”(通过过程转换的一些内部表示的文本表示)。请注意,您将获得数百个此类转储文件(遗憾的是,转储文件名称中的数字并不重要)
我不明白你为什么要那样做。我建议您要么将您的测试设置为宏,要么始终进行优化(最近的GCC很好地处理了-g
和-O1
)
一种可能的替代方法是使用插件扩展GCC,或者更好的方法是使用扩展(MELT是扩展GCC的高级领域特定语言,作为GPLv3许可的GCC插件实现)。然后您可以让您的测试功能成为您自己的GCC,因为GCC可以扩展为添加内置和pragma。然后,您的扩展将安装特定的内置程序,并插入一些特定的过程来适当地处理它们。(这意味着几天的工作,即使你很了解GCC内部结构)。请注意,内置通常用于连接额外的处理器特定指令(就像您的用例一样)
最近的GCC(尤其是4.6和4.7)接受插件(如果它们配置了--启用插件)。如果您的特定gcc正在接受插件,请检查gcc-v
。一些发行版不喜欢GCC插件(例如Suse&也许是Redhat),因此不包含GCC接受插件
如果您的特定Linux发行版(最近的一个)还不支持GCC插件,我建议您打开一个bug报告,请求在GCC内部启用插件。如果您的GCC交叉编译器供应商不支持插件,我也建议您查询该功能,它在FSF GNU GCC中已经存在了好几年,例如从4.5开始
在Debian或Ubuntu上,我建议安装gcc-4.6-plugin-dev
或gcc-4.7-plugin-dev
软件包。然后,您将能够构建并使用该插件(我正在为GCC4.6和4.7发布MELT 0.9.6,即2012年7月)
使用GCC4.6或4.7的最新发行版(Debian、Ubuntu、Mandriva、ArchLinux等)具有可扩展的GCC插件。MELT就是这样一个插件(它是一个元插件,因为MELT.so
正在自己做一些dlopen
)。一旦你有了一个接受插件的GCC并安装了一些插件(例如MELT),使用它就可以运行GCC-fplugin=MELT
和一些其他特定于插件的选项(例如-fplugin arg-MELT mode=
你的MELT模式)。可能你只是滥用了的“i”
约束。如果不进行优化,编译器就无法“知道”这将是最后的一个即时消息
我认为您应该让gcc来做这项工作,以决定可以优化多少。我只是使用“g”
作为约束,而不是“I”
。我非常确信,当您使用优化进行编译时,一切都会立即得到很好的解决。但是您最好检查生成的汇编程序以确定。c支持内联吗?如果是,您使用的是哪个版本?几乎在所有情况下,您都可以使用内联和宏执行任何操作。那么,在优化之后,您期望得到什么呢?(这么小的代码段没有奇迹)@BasileStary
gcc -ftree-ter test.c # no errors
alw.c: In function ‘main’:
alw.c:7:5: warning: asm operand 1 probably doesn’t match constraints [enabled by default]
alw.c:7:5: error: impossible constraint in ‘asm’