What is a specific GCC flag that enables the immediate propagation of a value for built-in build parameters?

Consider the following x86 code example:

#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 

He builds great.

If I build it with (without optimization):

 gcc test.c 

It does not work at the build stage, because the value '5' not distributed as an immediate value for the test of the built-in function, therefore we do not fulfill the restriction.

I want to be able to compile this code without turning on another unrelated optimization to make debugging easier.

Theoretically, -O is simply a shorthand, allowing you to immediately group the GCC optimization parameters that are described in the full GCC manual . Unfortunately, I could not find a specific GCC flag that includes this behavior.

Any ideas?

Explanation . To eliminate any doubts, the code snippet is just an example. That alone doesn't make much sense except to show what I'm trying to do. An actual use case includes an instruction on a user processor that can only take an immediate argument, which I am trying to wrap in a C construct. A macro will actually do the trick, but suffers from all the usual inverse macros, so I try to avoid this.

Refresh . For those who wondered, the macro does not work. It seems that the built-in function does not play any role here. For example, this also does not work:

 void foo (void) { int i = 6; asm volatile ("" : : "i" (i)); } 

I also corrected the title of the question to reflect this.

+4
source share
3 answers

Looks like -ftree-ter (Replace temporary expressions in the standard SSA-> pass, whatever that is) does the trick:

 gcc -ftree-ter test.c # no errors 

Here is how I determined that:

  • gcc -Q --help=optimizers reports which optimizations are enabled / disabled by default (some of them are enabled)
  • gcc -O -Q --help=optimizers reports which optimizations are enabled / disabled for -O
  • redirect the output of these commands to files and split them.
  • try optimization, which is enabled only when -O is specified until it is executed.
+6
source

always_inline is a strange attribute specific to GCC and possibly GCC (therefore, the detailed behavior may not coincide with GCC 4.5 and GCC 4.7).

GCC works by performing many optimization passes (even at -O0 some of these passes work, otherwise the code will not be emitted). Typically, GCC -O1 compilation runs two hundred optimization passes.

With gcc-4.7 your code does not even compile in -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 what GCC does, you can run it with gcc -fdump-tree-all and you will get a so-called “dump file” (a textual representation of some internal representations converted by pass) for most GCC transmissions. Beware you will get hundreds [s] such dump files (and, unfortunately, the number inside the dump file name does not matter).

I do not understand why you want to do this. I suggest either making your test macro or always optimizing (the recent GCC deal is well suited with both -g and -O1 ).

A possible alternative could be the GCC extension using the plugin , or better, the MELT extension (MELT is a high-level domain language for the GCC extension, implemented as a licensed GPLv3 GCC plugin). Then you can make your test function your own GCC builtin , since GCC can be extended to add inline and pragmatic ones . Your extension will then install your built-in functions and insert some specific omissions for their proper management. (This means that you have been working for several days, even if you know the GCC internals well). Note that built-in functions are usually used to connect additional target specific instructions to the processor (like your use case).

Recent GCCs (notably 4.6 and 4.7) accept plugins (if configured using --enable-plugins ). Check with gcc -v if your GCC accepts plugins. Some distributions do not like the idea of ​​a GCC plugin (for example, Suse and, possibly, Redhat), and therefore do not contain plugins that accept GCC.

If your particular Linux distribution (the latter) does not support GCC plugins, I suggest you open an error report to allow plugins to be included inside GCC. If your GCC cross-compiler provider does not support plugins, I also suggest that you request this function, which has existed in the GNU Gcc FSF since several years, for example. since 4.5!

On Debian or Ubuntu, I suggest installing the gcc-4.6-plugin-dev or gcc-4.7-plugin-dev . Then you can create and use the MELT plugin (I will work on the release of MELT 0.9.6 for GCC 4.6 and 4.7 very soon, that is, in July 2012).

The latest distributions (Debian, Ubuntu, Mandriva, ArchLinux, ...) with GCC 4.6 or 4.7 have a GCC extension with plugins. MELT is such a plugin (it is a meta plugin because melt.so does something dlopen ). After you have plugins that accept GCC and install some kind of plugin (like MELT), it just runs gcc -fplugin=melt with some other plugin options (like -fplugin-arg-melt-mode= your -Melt mode for MELT).

+2
source

Perhaps you are simply violating the "i" restriction. If you do not optimize, the compiler will not be able to “know” that it will be immediately at the end.

I think you just have to let gcc do the work to decide how much this can be optimized. I would use "g" as a constraint instead of "i" . I am absolutely sure that when you compile with optimization, everything will solve everything at once. But it’s better to check the assembler, which is ready for release.

+2
source

All Articles