简体   繁体   English

什么是特定的GCC标志,它为内联汇编参数打开立即值传播?

[英]What is the specific GCC flag that turns on immediate value propagation for inline assembly parameters?

Consider the following x86 code example: 请考虑以下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;
}

If I build it with: 如果我用它构建它:

gcc -O test.c

It builds fine. 它建立得很好。

If I build it with (no optimization): 如果我用它构建它(没有优化):

gcc test.c

It fails during assembly phase, because the value '5' is not propagated as an immediate value to the inline function test, so we fail the constraint. 它在汇编阶段失败,因为值'5'不会作为立即值传播到内联函数测试,因此我们使约束失败。

I wish to be able to compile this code without turning on other non related optimization, in order to make debugging easier. 我希望能够在不启用其他非相关优化的情况下编译此代码,以便更轻松地进行调试。

In theory, -O is simply a short cut to enable a bunch of GCC optimization options at once that are documented in the fine GCC manual . 从理论上讲, -O只是一个捷径,可以在GCC手册中记录一系列GCC优化选项。 Unfortunately, I was not able to find the specific GCC flag that turns this behavior on. 不幸的是,我无法找到打开此行为的特定GCC标志。

Any ideas? 有任何想法吗?

Clarification : To relieve any doubt, the code snippet is just an example. 澄清 :为了减轻任何疑问,代码片段只是一个例子。 It does not make much sense by itself except to show what I am trying to do. 除了展示我想要做的事情之外,它本身并没有多大意义。 The actual use case involves an instruction on a custom processor that can only take an immediate as an argument which I am trying to wrap in a C construct. 实际的用例涉及一个自定义处理器上的指令,该处理器只能立即作为参数,我试图将其包装在C构造中。 A macro will indeed do the trick, but suffers from all the usual draw backs of a macro, hence I am trying to avoid it. 一个宏确实可以做到这一点,但是遭受了宏的所有通常的缺点,因此我试图避免它。

Update : For those who wondered, a macro wont work either. 更新 :对于那些想知道的人,一个宏也不会工作。 It seems the inline function doesn't play a part here at all. 似乎内联函数根本不起作用。 Eg, this doesn't work either: 例如,这也不起作用:

void foo (void)
{
  int i = 6;

  asm volatile ("" : : "i" (i));
}

I also fixed the question title to reflect this. 我还修正了问题标题以反映这一点。

Looks like -ftree-ter (Replace temporary expressions in the SSA->normal pass - whatever that is) does the trick: 看起来-ftree-ter (替换SSA中的临时表达式 - >正常传递 - 无论是什么)都可以解决问题:

gcc -ftree-ter test.c   # no errors

Here's how I determined that: 以下是我如何确定:

  1. gcc -Q --help=optimizers tells you what optimizations are enabled/disabled by default (some are enabled) gcc -Q --help=optimizers告诉您默认启用/禁用哪些优化(某些已启用)
  2. gcc -O -Q --help=optimizers tells you what optimizations are enabled/disabled for -O gcc -O -Q --help=optimizers告诉您为-O启用/禁用了哪些优化
  3. redirect the output of those commands to files and diff them. 将这些命令的输出重定向到文件并进行区分。
  4. try the optimizations that are enabled only when -O is specified until one works. 尝试仅在指定-O时才启用的优化,直到一个工作。

always_inline is a strange attribute, very GCC specific, and possibly GCC version specific (so the detailed behavior might not be the same with GCC 4.5 and with GCC 4.7). always_inline是一个奇怪的属性,非常具有GCC特性,可能还有特定于GCC的版本(因此详细行为可能与GCC 4.5和GCC 4.7不同)。

GCC is working by running a lot of optimization passes (even in -O0 some of these passes are running, otherwise no code would be emitted). GCC正在通过运行大量优化传递来工作(即使在-O0其中一些传递正在运行,否则不会发出代码)。 Typically a GCC -O1 compilation is running two hundred optimization passes. 通常,GCC -O1编译正在运行两百个优化过程。

With gcc-4.7 your code don't even compile in -O0 : 使用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’

To understand more what GCC is doing, you could run it with gcc -fdump-tree-all and you'll get a so called "dump file" (a textual representation of some of the internal representations transformed by a pass) for most GCC passes. 为了更多地了解GCC正在做什么,您可以使用gcc -fdump-tree-all运行它,并且您将获得所谓的“转储文件”(通过转换的一些内部表示的文本表示),用于大多数GCC经过。 Beware, you'll get hundred[s] of such dump files (and sadly, the number inside the name of dump files is not significant). 请注意,您将获得数百个这样的转储文件(遗憾的是,转储文件名称中的数字并不重要)。

I can't understand why you want to do that. 我不明白你为什么要那样做。 I suggest either making your test a macro, or always optimize (recent GCC deal quite well with both -g and -O1 ). 我建议要么让你的test成为一个宏,要么总是优化(最近的GCC与-g-O1交易都很好)。

A possible alternative could be to extend GCC with a plugin , or better, a MELT extension (MELT is a high level domain specific language to extend GCC, implemented as a GPLv3 licensed GCC plugin). 一种可能的替代方案可能是使用插件或更好的MELT 扩展来扩展GCC(MELT是扩展GCC的高级域特定语言,实现为GPLv3许可的GCC插件)。 Then you could make your test function your own GCC builtin , since GCC can be extended to add builtins and pragmas . 然后你可以让你的test功能成为你自己的GCC 内置 ,因为GCC可以扩展为添加内置和编译指示 Your extension will then install your specific builtins and insert some specific passes to handle them appropriately. 然后,您的扩展将安装您的特定内置并插入一些特定的传递以适当地处理它们。 (This means several days of work, even if you know well GCC internals). (这意味着几天的工作,即使你很了解GCC的内部情况)。 Notice that builtins are commonly used to interface extra target processor specific instructions (just like your use case). 请注意,内置函数通常用于连接额外的目标处理器特定指令(就像您的用例一样)。

Recent GCC (notably 4.6 and 4.7) accept plugins (if they have been configured with --enable-plugins ). 最近的GCC(特别是4.6和4.7)接受插件(如果它们配置了--enable-plugins )。 Check with gcc -v if your particular GCC is accepting plugins. 如果您的特定GCC正在接受插件,请检查gcc -v Some distributions dislike the GCC plugin idea (eg Suse & perhaps Redhat) so don't contain a GCC accepting plugins. 一些发行版不喜欢GCC插件的想法(例如Suse和Redhat),所以不要包含GCC接受插件。

If your particular Linux distribution (a recent one) does not support yet GCC plugins, I suggest you to open a bug report to request plugins to be enabled inside GCC. 如果您的特定Linux发行版(最近的发行版)不支持GCC插件,我建议您打开一个错误报告,以请求在GCC内启用插件。 If your GCC cross-compiler supplier don't support plugins, I also suggest you to query that feature, which exists in the FSF GNU Gcc since several years, eg since 4.5! 如果您的GCC交叉编译器供应商不支持插件,我还建议您查询该功能,该功能自几年以来一直存在于FSF GNU Gcc中,例如从4.5开始!

On Debian or Ubuntu, I suggest installing the gcc-4.6-plugin-dev or gcc-4.7-plugin-dev package. 在Debian或Ubuntu上,我建议安装gcc-4.6-plugin-devgcc-4.7-plugin-dev软件包。 You'll then be able to build and use the MELT plugin (I am working to release MELT 0.9.6 for GCC 4.6 & 4.7 very soon, ie in july 2012). 然后,您将能够构建和使用MELT插件(我正在努力为GCC 4.6和4.7很快发布MELT 0.9.6,即2012年7月)。

Most recent distributions (Debian, Ubuntu, Mandriva, ArchLinux, ...) with a GCC 4.6 or 4.7 have a GCC extensible with plugins. 具有GCC 4.6或4.7的最新发行版(Debian,Ubuntu,Mandriva,ArchLinux,...)具有可扩展的插件。 MELT is such a plugin (it is a meta plugin, because melt.so is doing itself some dlopen ). MELT就是这样一个插件(它是一个插件,因为melt.so正在做一些dlopen )。 Once you have a GCC accepting plugins and have installed some plugin (eg MELT), using it is just running gcc -fplugin=melt with some other plugin specific options (eg -fplugin-arg-melt-mode= your-melt-mode for MELT). 一旦你有一个GCC接受插件并安装了一些插件(例如MELT),使用它只是运行gcc -fplugin=melt与其他一些插件特定的选项(例如-fplugin-arg-melt-mode= your-melt-mode for熔化)。

Probably you are just abusing the "i" constraint. 可能你只是在滥用"i"约束。 If you don't optimize there is no way for the compiler to "know" that this will be an immediate at the end. 如果你没有进行优化,那么编译器就无法“知道”这将在最后立即生效。

I think you just should let gcc do the work to decide how much this can be optimised. 我认为你应该让gcc做好工作来决定这可以优化多少。 I'd just use "g" as a constraint instead of "i" . 我只是用"g"作为约束而不是"i" I am quite sure that when you compile with optimization on, everything will resolve fine to an immediate. 我很确定当你使用优化进行编译时,一切都会立即解决。 But you'd better check the assembler that is produced to be sure. 但是你最好检查一下生产的汇编程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM