打开内联程序集参数的即时值传播的特定GCC标志是什么?

打开内联程序集参数的即时值传播的特定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; } 它建造得很好 如果我使用(无优化)构建它: 它在组装阶段失败,因为值'

考虑以下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;
}
它建造得很好

如果我使用(无优化)构建它:

它在组装阶段失败,因为值
'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’