News for hackers. Stuff that matters.
Re:GodBolt: Enter C, get Assembly by rzimmerman on Thursday December 15, 2016 @02:18AM (#13183024)
Try with gcc 6.2 options -Ofast -march=native:

  int square(int num) {
    int a = 0;
    for (int x = 0; x < num; x+=2) {
      if (!(x % 2)) {
        a += x;
      }
   }
    return a;
  }
All kinds of loop unrolling and vector instructions. Now remove the "!"
Re:GodBolt: Enter C, get Assembly by harpocrates on Thursday December 15, 2016 @02:59AM (#13183176)
For anyone too lazy: https://godbolt.org/g/jvSKCD

I would be much more impressed if I hadn't taken a compilers course. I reckon (god alone knows exactly what GCC does) this is just linear induction variable substitution[1] (so `x` gets replace with `i*2`), then associativity of integer multiplication, then some (probably builtin) rule that `n%n` is always 0. From there, it is pretty straightforward.

Don't get me wrong - the devil is in the details and getting optimizations that are both powerful and only applied when they are valid, and at the right time is difficult as hell. That said, I do expect compilers to be at least this smart.

[1]: https://en.wikipedia.org/wiki/Induction_variable#Induction_v...

Re:GodBolt: Enter C, get Assembly by digler999 on Thursday December 15, 2016 @10:51AM (#13185362)
> I do expect compilers to be at least this smart.

Does anyone know if, internally, compilers second-guess / double-check themselves ? For instance, when they detect a clever shortcut do they generate and quickly run [1] the optimized bytecode on a sampling of inputs to verify it is functionally-equivalent to what non-optimized bytecode outputs ?

[1] obviously cross-compilers are a thing, so this wouldn't be possible if it were compiling/optimizing for a separate architecture.

Re:GodBolt: Enter C, get Assembly by CyberShadow on Thursday December 15, 2016 @11:17AM (#13185634)
> For instance, when they detect a clever shortcut do they generate and quickly run [1] the optimized bytecode on a sampling of inputs to verify it is functionally-equivalent to what non-optimized bytecode outputs ?

No. Optimization transformations are generally expected to result in provably identically-functional code (or sufficiently identical, in case of e.g. floating-point optimizations). Otherwise it is a bug.

Re:GodBolt: Enter C, get Assembly by vsl on Friday December 16, 2016 @06:50AM (#13192619)
Indeed, “provably” being the key word. If I, the compiler developer, prove (in the mathematical sense) that the transformation is functionally identical, I don’t need the compiler to run any experiments to verify it. A proof is much more solid than running a few experiments.
Re:GodBolt: Enter C, get Assembly by jcranmer on Thursday December 15, 2016 @11:17AM (#13185624)
Detecting functional equivalence of Turing-complete languages is a very non-trivial problem. So, no, compilers don't try to construct runtime proofs of their correctness.

There are people who do do more exhaustive checks of the peephole optimizations for correctness--or finding new opportunities (see John Regehr's Souper work). But production compilers are well-known (at least by anyone who works on them) for having lots of bugs in these kinds of optimizations.

Re:GodBolt: Enter C, get Assembly by drdrey on Thursday December 15, 2016 @03:25PM (#13187987)
I think Nuno Lopes also did some work on proving the correctness of instcombine optimizations, for instance: http://blog.regehr.org/archives/1170
Re:GodBolt: Enter C, get Assembly by foldr on Thursday December 15, 2016 @11:38AM (#13185833)
>then associativity of integer multiplication, then some (probably builtin) rule that `n%n` is always 0.

Is this quite right? It's not true in general that (a * b) % c = a * (b % c). E.g. it's not true for 2,3,4. The relevant generalization is that (a * b) % b = 0, which has nothing to do with associativity.

Re:GodBolt: Enter C, get Assembly by widdma on Thursday December 15, 2016 @11:58AM (#13186023)
Maybe they meant distributes? Modulo (sort of) distributes over multiplication: (a * b) % c = ((a % c) * (b % c)) % c
Re:GodBolt: Enter C, get Assembly by bartl on Thursday December 15, 2016 @07:38AM (#13184160)
If that function is really supposed to return the square of a number, you took a wrong turn somewhere. Because it says the square of 16 is 56.

Now here's a more efficient algorithm which does produce the currect result:

    int square(int num) {
        int a = 0;
        for (int x = 1, n = num; x <= num; x+=x, n+=n) {
          if( num & x) {
              a += n;
          }
       }
       return a;
    }

It would be nice if this site allowed us to run/step through the code, to see exactly what it is doing.
Re:GodBolt: Enter C, get Assembly by rzimmerman on Saturday December 17, 2016 @05:25PM (#13203049)
Oh, sorry, I never bothered to change the function name. It's just an interesting loop.
Re:GodBolt: Enter C, get Assembly by im3w1l on Thursday December 15, 2016 @04:46AM (#13183497)
GCC is messing up here. Compare with clang!

https://godbolt.org/g/HCifdP

Re:GodBolt: Enter C, get Assembly by amadvance on Thursday December 15, 2016 @05:47AM (#13183709)
We can say that clang is like the young Gauss :)

http://mathandmultimedia.com/2010/09/15/sum-first-n-positive...

Re:GodBolt: Enter C, get Assembly by frederikvs on Thursday December 15, 2016 @05:46AM (#13183703)
Wait, that contains no loop. Is clang using mathematical rules for series summation? Awesome!
Re:GodBolt: Enter C, get Assembly by janekm on Thursday December 15, 2016 @12:08PM (#13186122)
It gets even better after playing with the code a bit: https://godbolt.org/g/kUMCpl

magic constants galore... where does 3435973837 come from? ;)

Re:GodBolt: Enter C, get Assembly by Veedrac on Thursday December 15, 2016 @09:19PM (#13190558)
First it normalizes to

    if (num <= 0) {
    	return 0;
    }
  
    int a = 0;
    int loop_n = (unsigned)(num - 1) / 5;
    for (int x = 0; x <= loop_n; x++) {
        a += x * 5 - 1;
    }
    return a;
Division by 5 is done by multiplying by the modular inverse, 3435973837.

From there you just have a summation, which has two components.

    ((loop_n + 1) * loop_n / 2) * 5    // 5x
    - loop_n - 1                       // -1
The assembly between these the manual and automatic methods is slightly different, but the difference is fairly trivial and opaque.
Re:GodBolt: Enter C, get Assembly by frederikvs on Thursday December 15, 2016 @12:57PM (#13186564)
It's 0xCCCCCCCD in hex, which looks a lot more structured at least. Though how exactly this makes sense is still unclear :-)

[edit] and playing around with the increment of x it keeps throwing in some magical values which are a repeating pattern in hex, with the LSB off by one usually...

Re:GodBolt: Enter C, get Assembly by im3w1l on Saturday December 17, 2016 @12:13AM (#13199349)
I thought 0xCCCCCCCD was a very nice number so I asked myself why it would come out like that. I wondered whether

0.CCCCCCCC.... = 4/5 had anything to do with it.

Using hexadecimal we have

    5 * 3 = 10 - 1, so 
    5 * C = 40 - 4 so
    5 * (1 + C + C0 + C00 + C000...) = 5 - 4 + 40 - 40 + 400... where the last term is = 0 mod 2^32
         -----
           D
This relates to

    0.CCCCCC.... = 4 / 5
Because in order for that to come out right, multiplying 0.CCCC... with 5 has to have all intermediate terms cancel, leaving only a 4.

So why would it take its digit from 4 / 5 and not 1 / 5? Because it takes x=4 to make the 5-x subtraction in 5 - x + x0 - x0 + x00 to come out to 1.

So this gives us a general rule for inversion (for numbers less than 16). Take the hexadecimal expansion of (n-1) / n, truncate to get enough hex chars, add 1 to the least significant hex digit.

I.e. the inversion of 3 would be 0xAAAAAAAB

Re:GodBolt: Enter C, get Assembly by john_reel on Thursday December 15, 2016 @02:50PM (#13187633)
Well if A=1 (I know it’s not), D is 5-1. I’ve noticed that whatever you change five to fits this pattern. Ex: +=3 in the code gives you AAAAAAAB, and B would be (3-1) if A=1. I
Re:GodBolt: Enter C, get Assembly by 0x6c6f6c on Thursday December 15, 2016 @09:06AM (#13184602)
Alright maybe I'm stupid but I could have sworn that more than

    square(int):                             # @square(int)
        xor     eax, eax
        ret
is required to perform this, what's going on?
Re:GodBolt: Enter C, get Assembly by akeruu on Thursday December 15, 2016 @09:12AM (#13184635)
X can always by devided by 2, meaning the condition will always be false thus returning "a" unchanged. "xor eax, eax" is a shortcut to "mov eax, 0".
Re:GodBolt: Enter C, get Assembly by syncsynchalt on Thursday December 15, 2016 @05:44PM (#13189358)
"xor r,r" is intel-ese for "set r to zero". For various reasons it's faster and smaller than the more obvious "mov r,0".

From this we can see that gcc and clang have figured out that the "if" can never be true, then they elided the loop, then optimized out the variable, ending in the equivalent of "return 0;".

Re:GodBolt: Enter C, get Assembly by Sean1708 on Thursday December 15, 2016 @05:00AM (#13183546)

  > Now remove the "!"
To be fair 4.6 and clang also do that, and I suspect so do earlier versions if I could be arsed to fix the compilation error.

Also as pointed out elsewhere clang turns the "!" version into a simple equation in terms of n, so I'm actually kind of disappointed in GCC here.

Re:GodBolt: Enter C, get Assembly by OskarS on Thursday December 15, 2016 @02:58AM (#13183175)
Dude, modern compilers are smart.
Re:GodBolt: Enter C, get Assembly by user51442 on Thursday December 15, 2016 @05:03AM (#13183557)
A simple recursive factorial function:

https://godbolt.org/g/97dUFg

Not sure if that's smart or stupid.

Re:GodBolt: Enter C, get Assembly by GlitchMr on Thursday December 15, 2016 @05:32AM (#13183646)
It does try to vectorize it (doing multiple math operations at once is faster).

(1 * 5 * 9 * 13 * 17 * ...) * (2 * 6 * 10 * 14 * 18 * ...) * (3 * 7 * 11 * 15 * 19 * ...) * (4 * 8 * 12 * 16 * 20 * ...)

(it's not precisely that, but close enough)

It isn't optimal however, optimal code would be pre-computed results (signed integer overflow is undefined, so n <= 12 is defined)

(if signed integer overflow would be defined to be 2's complement overflow, you can still use a table, as n > 33 gives 0)

Re:GodBolt: Enter C, get Assembly by Tuna-Fish on Thursday December 15, 2016 @05:34AM (#13183653)
Dude, your code got:

1. Turned from recursive form into iterative form 2. Unrolled heavily 3. Autovectorized (!)

The throughput will be substantially more than the simple version.

Re:GodBolt: Enter C, get Assembly by user51442 on Thursday December 15, 2016 @06:19AM (#13183833)
Well, the optimizations are pretty smart to be sure, the stupid thing is that anything over 12! overflows (as GlitchMr points out).

I'd like to know how the recursion to iteration step was done.

Re:GodBolt: Enter C, get Assembly by eutectic on Thursday December 15, 2016 @08:05AM (#13184287)
Presumably there is a pass to turn f(recur(x), y) into recur(f(y, acc), x) and then tail-call optimization can be applied. This works for any associative f.
Re:GodBolt: Enter C, get Assembly by jdcarter on Thursday December 15, 2016 @12:36PM (#13186379)
I took that and check out what Clang does with 32-bit ints:

https://godbolt.org/g/ORsX5h

vs. what it does with 64-bit ints:

https://godbolt.org/g/2wBzn3

Can anybody explain the 32 bit version?

Re:GodBolt: Enter C, get Assembly by CorvusCrypto on Thursday December 15, 2016 @05:59PM (#13189478)
It's just vectorizing calculations so that it's faster than pure iterative calculation. 64 bit version doesn't get this probably because that optimizer isn't SSE2 aware yet (just a guess I actually don't know) and can't do SIMD arithmetic with 2 64 bit floats
Re:GodBolt: Enter C, get Assembly by user2994cb on Thursday December 15, 2016 @05:35PM (#13189263)
Harder to vectorize 64-bit arithmetic?
Re:GodBolt: Enter C, get Assembly by CorvusCrypto on Thursday December 15, 2016 @05:52PM (#13189406)
was going to say this. It probably only does SSE and not SSE2. Therefore vectorization only happens for 32 bit ints.
Re:GodBolt: Enter C, get Assembly by user2994cb on Friday December 16, 2016 @03:00AM (#13191789)
Seems to need -mavx2 to really go to town with 64 bit: https://godbolt.org/g/6EFYeY
Re:GodBolt: Enter C, get Assembly by jdcarter on Friday December 16, 2016 @03:31PM (#13196497)
Thank you both, I appreciate the insight!
Re:GodBolt: Enter C, get Assembly by yellowapple on Friday December 16, 2016 @06:49PM (#13197967)
Interestingly, all the RISC architectures except for 64-bit ARM seem to compile down to something a lot simpler.
Re:GodBolt: Enter C, get Assembly by lisivka on Thursday December 15, 2016 @01:40PM (#13186952)
Use -Os to check. Compiler turned recursive function to loop.
Re:GodBolt: Enter C, get Assembly by topkekz on Thursday December 15, 2016 @08:03AM (#13184279)
Check this one (clang)

https://godbolt.org/g/Brn57Z

Re:GodBolt: Enter C, get Assembly by Veedrac on Thursday December 15, 2016 @08:09AM (#13184314)
That's not smart - that's pattern matching.
Re:GodBolt: Enter C, get Assembly by joelthelion on Thursday December 15, 2016 @07:52AM (#13184225)
Why the hell doesn't gcc eliminate the loop in this case?

https://godbolt.org/g/eXLhxH

Re:GodBolt: Enter C, get Assembly by noselasd on Thursday December 15, 2016 @12:09PM (#13186139)
Oddly enough, gcc 5.4 does.
Re:GodBolt: Enter C, get Assembly by cestith on Thursday December 15, 2016 @02:57PM (#13187711)
Try the same thing again with -Os and see the difference.