

A very old gcc "bug" - vinutheraj
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11203

======
Dilpil
My favorite gcc trick is to compile and run the following two line, and then
try to reconcile the results.

x = 7;

printf("%d %d %d",x++,++x,x++);

x = 7;

printf("%d %d %d",x++,x=2,x++);

Go ahead, try it, run it, and explain the output.

~~~
ecaron
For those curious, the output is: 9 10 7 2 3 7

The output should be (at least from my understanding and what PHP renders): 7
9 9 7 2 2

As far as reconciliation, I guess the first line makes sense when you think
about it as machine code and how the pointers probably behave. The second line
though, seems quite evil and I am going to go hide under my "Rails will save
me" blanket until someone can explain this voodoo.

~~~
yuvi
clang gives 7 9 9 7 2 2 as well. gcc gives 7 10 9 7 3 2 when targeting arm.

2,3,7 are all valid possibilities for the 4th and 6th numbers, but apparently
gcc interprets the 5th as 2 + 1 somehow, which I can't see as being valid
whatsoever.

~~~
ars
Why not? It's doing the x=2 first (before anything else in there), then the ++
of the last expression (and returning 2 for it), then giving you the result of
the middle one (which is now three since it ran after the last one). The 7 is
because it ran that one before doing anything to the other values.

It should be noted that this is illegal C, and compilers are allowed to do
absolutely anything they want when they see it. Even things that are totally
not logical.

~~~
yuvi
I re-read C99, and the reason this is allowed is not because of §6.5.2.2 p10,
but rather §6.5.16 p4 as far as I can tell. Though it's weird to me that the
expression (x = 2) can ever be evaluated as anything but 2.

Also, it's not illegal C, it's undefined C and compilers are only allowed to
do whatever they want within the undefined area (which is larger than I
expected.)

~~~
ars
Undefined C is illegal C, because the compiler is not even required to do the
same thing from run to run.

Undefined is not the same as implementation defined.

------
zandorg
I find it hard to believe that you wouldn't know how many registers code
should use. However - it's not C code, it's assembly code, so it seems unfair
to blame gcc - a _C_ compiler.

~~~
yuvi
There are a couple reasons you wouldn't know that (for an entire inline asm
function):

1\. x86_64 vs. x86_32. It's possible that you'd want to use more registers
than 32-bit has. In this case, it's usually optimal to use memory operands on
x86_32 but registers on x86_64.

2\. gcc _will not_ allow you to use ebx in inline asm with PIC code. Likewise
with ebp with frame pointer. There's no technical reason gcc couldn't just
save+restore those registers around the block, but it doesn't.

3\. The case in the bugreport: you have various locations in memory you want
to address, and you want gcc to figure out their addresses for you. Without
analysis that eliminates identical registers, the naive implementation of
using 1-2 new registers per operand will quickly fail.

~~~
viraptor
> There's no technical reason gcc couldn't just save+restore those registers
> around the block, but it doesn't.

While it's not impossible to do, it makes debugging a lot harder. gdb would
have a much harder job of figuring out what's going on if the code messed with
ebp, since the fp location would depend on the code. Some more debug
information to describe that location could solve the problem... but why
create that problem in the first place.

------
jacquesm
read comment #24:

Martin, you should realize that this problem _cannot_ be solved. Yes, there
will perhaps be a time when this particular test case compiles, though I think
that is unlikely. But anyway, then there will be other cases that fail.

The reason is dead simple: register allocation is NP-complete, so it is even
_theoretically_ not possible to write register allocators that always find a
coloring. That means any register allocator will always fail on some very
constrained asm input. And you cannot allow it to run indefinitely until a
coloring is found, because then you've turned the graph coloring problem into
the halting problem because you can't prove that a coloring exists and that
the register allocator algorithm will terminate.

So really it doesn't matter at all whether or not your specific inline asm
compiles or not. When yours does, someone else's will fail.

~~~
ars
You are not the only one who does not understand the halting problem.

The halting problem only says you can not prove every program will (or won't)
halt - the general case.

It says nothing at all about any specific case, and there are plenty of
programs where you can prove they halt.

And NP just means the solution does not scale well, not that it can't be done.

And NP-complete is something else entirely. It has to do with being able to
interconvert all NP-complete problems (i.e. if you solve one you solve all).

There are many NP problems that are not NP-complete. Proving any particular
problem is NP-complete, and not just NP is usually a big deal, so don't just
throw that term around.

~~~
jacquesm
It was a quote from the original thread.

As for your explanation, yes, that's correct. The thing that I didn't get
about the way they were sparring on the list was that if there is a solution
the problem might not be solved in an elegant way, but with the number of
variations involved you could simply brute force it.

Then if a solution exists you'll find it, if it doesn't exist then you can
report that. After all, if you say you want to put 12 variables in to 7
registers and there is no possible way then there is no possible way. If there
is such a possibility the number of permutations is small enough that it could
be found anyway.

GCC contributes to the problem by having some overhead that reserves registers
that could be saved on the stack for the duration of this part of the
computation.

