GCC Explorer is great and I use it on a semi-regular basis. I often use it to show what kinds of optimizations a modern compiler will do. Just yesterday I was using it to show someone how a piece of code like:
int launched = 0;
// ...
start_thread(...);
while (!launched) {}
could result in an endless loop since the compiler just rewrote it to 'if(!launched) { while(true){} }'. The person had the thread write to 'launched' and expected the first thread to exit the loop once launched had been set to 1.
Great tool. I hope it doesn't get a HN hug of death.
C has atomic types now also. And I believe in general that volatile only prevents elision of reads and stores, but not optimization in general. That works for many cases (and I think it would work here) but it doesn't solve data races in general.
Unless 'launched' was directly or indirectly local to the stack frame, I don't see how this optimisation is legal. In general your compiler has to assume values will change across an opaque function call.
To expand on what to3m said. The code was transformed into something like this:
int launched = 0;
start_thread(...);
if (!launched) {
while (true) {}
}
That's a perfectly legal optimization. The integer here isn't atomic and if another thread modifies the variable, that would be a data race and those have undefined behavior. Therefore, the compiler can assume that there is no race and move the comparison out of the loop.
Changing it to be "std::atomic<int> launched;" fixes that problem.
>That's a perfectly legal optimization. The integer here isn't atomic and if another thread modifies the variable, that would be a data race and those have undefined behavior. Therefore, the compiler can assume that there is no race and move the comparison out of the loop.
In this case, the data race is fairly minimal, since we're talking about a 4 byte integer being used as a boolean flag. Operations like x = 1 for 4 byte ints are pretty much guaranteed to be atomic with x86, and worst case, you go through 1 more iteration of your loop than you would have otherwise(which your code should account for at any rate with locking for critical sections). Any change to the int should cause the while loop to exit.
It should be a volatile(C pre C11) or atomic(C++11/C11) integer if you're passing it between threads, though.
It presumably checks launched just before the while loop, after the start_thread call is complete, under the assumption that whatever start_thread might have done to that variable has been done. (An implementation could have some kind of markup on the thread creation function so that the compiler can infer the pointed-at memory has become volatile... but I doubt anybody actually does that. Much easier to let the code fuck up and blame the programmer ;))
Hi! I'm the developer of GCC Explorer and ... sorry for the slow service! This is the second time I've made it on HN - thanks for all your support. GCC Explorer runs on an Amazon EC2 instance and my "secondary" instance that I spin up from time to time is woefully out of date...
Better late than never...I've increased the power and number of instances running GCC Explorer, so hopefully it's a lot more usable under load now. Although my HN 5-minute fame seems to be over now :)
GCC Explorer is awesome, but I would not call it a "C/C++ Fiddle".
It's really slow (unusable) at the moment due to, I reckon, being on HN. Do revisit it later!
I have had some issues with it in the past when importing just iostream and trying to see the output for a small example. The combined source is too large, and GCC Explorer refuses to compile and show the assembly sometimes for even small examples.
Do play with the settings. Colourise is especially nice.
The code is on GitHub [0], so I suppose you can self host it, although I have not tried to do so yet.
I haven't considered that: porting the variety of compilers to Javascript is a bit tricky. Plus the closed-source Intel compiler wouldn't be an option. It's an interesting thought though!
I'm not quite sure what you were expecting to happen - here the template just recurses, but as a run-time recursion. GCC and the explorer handle it just fine.
Doing the more usual template<N-1> trick lets you hit the -ftemplate-depth limit if you pass, for example ZVTemplate<2048>. It still works ok though :)
Please do let me know if you can find a "poison" input...although at the moment the site is pretty busy just through sheer weight of users, so it's hard to tell I know!
Presumably would require cross compilers for each architecture, but it would be very interesting to see what you could do with it, for example comparing side by side.
Great tool. I hope it doesn't get a HN hug of death.