LLVM Is Smarter Than Me
blog.sulami.xyz
LLVM Is Smarter Than Me
1–10 of 18 posts
Re: LLVM Is Smarter Than Me
#2It's weird that LLVM computes n(n-1)/2 in such a convoluted way, namely:
(n-1)(n-2)/2 + n - 1
Re: LLVM Is Smarter Than Me
#3Re: LLVM Is Smarter Than Me
#4Re: LLVM Is Smarter Than Me
#5Does someone know how the compiler comes up with the closed form solution? Is there a hardcoded list of common patterns and their solution in the compiler, or is this really generated from the code itself?
Re: LLVM Is Smarter Than Me
#6Does someone know how the compiler comes up with the closed form solution? Is there a hardcoded list of common patterns and their solution in the compiler, or is this really generated from the code itself?
Re: LLVM Is Smarter Than Me
#7A small correction: the sigma summation should go to n-1, not n. It's weird that LLVM computes n(n-1)/2 in such a convoluted way, namely: (n-1)(n-2)/2 + n - 1
Re: LLVM Is Smarter Than Me
#8Does someone know how the compiler comes up with the closed form solution? Is there a hardcoded list of common patterns and their solution in the compiler, or is this really generated from the code itself?
Yeah, one suspects this is a dumb micro-optimisation to make benchmark figures look better with little practical application.
Re: LLVM Is Smarter Than Me
#9A small correction: the sigma summation should go to n-1, not n. It's weird that LLVM computes n(n-1)/2 in such a convoluted way, namely: (n-1)(n-2)/2 + n - 1
IIRC that way of doing the summation is specifically done to avoid issues with overflow.
The multiplication of (n-1)(n-2) already expands to 64 bits. It has to: Even when the loop accumulator doesn't overflow when counting up to n(n-1)/2 in the abstract machine, (n-1)(n-2) will be larger (and possibly overflow 32 bits) for most n. (The highest valid n is 92682, I think.)
So surely once you're doing that, I'd think n(n-1)/2 can be done in 64 bits just as easily.
unsigned int sum2(unsigned int n) {
unsigned long ln = n;
return ln * (ln - 1) / 2;
}
a.out : pushq %rbp
a.out : movq %rsp, %rbp
a.out : movl %edi, %ecx
a.out : leaq -0x1(%rcx), %rax
a.out : imulq %rcx, %rax
a.out : shrq %rax
a.out : popq %rbp
a.out : retqRe: LLVM Is Smarter Than Me
#10Converting an awful algorithm into a superior form (from O(N) to O(1)) is a neat trick, but obviously can only apply if: - Such an algorithm can be easily detected by the Compiler and there is actually a replacement algorithm which does exactly the same thing within the defined behavior. These cases are very rare. - The programmer is unable or unwilling to identify the optimization, which in most cases means he does not understand his algorithm well or does not care about performance.
Just as an example this substitutions CAN NOT be applied if you replace ints with floats. Of course the O(1) algorithm is still generally preferable in that case a Compiler will never help you with that if you use floats.