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 通道的所谓“转储文件”(通过通道转换的一些内部表示的文本表示)。请注意,您将获得数百个此类转储文件(遗憾的是,转储文件名称中的数字并不重要)。
我不明白你为什么要这样做。我建议要么让你test成为一个宏,要么总是优化(最近的 GCC 很好地处理了-g和-O1)。
一种可能的替代方法是使用插件扩展 GCC ,或者更好的是MELT 扩展(MELT 是扩展 GCC 的高级域特定语言,作为 GPLv3 许可的 GCC 插件实现)。然后你可以让你的test函数成为你自己的 GCC内置函数,因为GCC 可以扩展为添加内置函数和 pragma。然后,您的扩展程序将安装您的特定内置插件并插入一些特定的通行证以适当地处理它们。(这意味着需要几天的工作,即使您非常了解 GCC 内部结构)。请注意,内置函数通常用于连接额外的目标处理器特定指令(就像您的用例一样)。
最近的 GCC(特别是 4.6 和 4.7)接受插件(如果它们已经配置了--enable-plugins)。检查gcc -v您的特定 GCC 是否接受插件。一些发行版不喜欢 GCC 插件的想法(例如 Suse 和可能是 Redhat),因此不包含接受插件的 GCC。
如果您的特定 Linux 发行版(最近的发行版)尚不支持 GCC 插件,我建议您打开一个错误报告以请求在 GCC 中启用插件。如果您的 GCC 交叉编译器供应商不支持插件,我还建议您查询该功能,该功能在 FSF GNU Gcc 中已经存在好几年了,例如从 4.5 开始!
在 Debian 或 Ubuntu 上,我建议安装gcc-4.6-plugin-devorgcc-4.7-plugin-dev包。然后,您将能够构建和使用MELT插件(我正在努力尽快发布适用于 GCC 4.6 和 4.7 的 MELT 0.9.6,即 2012 年 7 月)。
带有 GCC 4.6 或 4.7 的最新发行版(Debian、Ubuntu、Mandriva、ArchLinux 等)具有可通过插件扩展的 GCC。MELT 就是这样一个插件(它是一个元插件,因为melt.so它自己在做一些事情dlopen)。一旦你有一个 GCC 接受插件并安装了一些插件(例如 MELT),使用它只是运行gcc -fplugin=melt一些其他插件特定选项(例如用于 MELT-fplugin-arg-melt-mode=的 your-melt-mode )。