Live data from Hacker News

When static makes your C code 10 times faster

mazzo.li

1–10 of 113 posts

Re: When static makes your C code 10 times faster

#2
>"When modulus is static, gcc / clang know that it is private to the current compilation unit, and therefore they can inline the value itself. Then, they turn the expensive div into a much cheaper and – since

mod’ing by a power of two -- is equal to bitwise and of that number minus one!

All you need to do is keep the bits lower than that power of two, which is what the and will do."

Re: When static makes your C code 10 times faster

#4
This can be accomplished more simply and reliably by marking modulus as const. The compiler currently has to reason about the whole compilation unit to determine that modulus is not modified, which works. However, if future code modifies modulus (either on purpose or accidentally) or something changes that prevents the compiler from performing global reasoning, the optimization will be lost. By marking the actual intention, any modifications of modulus turn into compiler errors. Plus, if it becomes important to expose modulus to another compilation unit, now that's possible.

This is a common issue with C code (including lots of code I've written). It's really easy to forget to const something, which forces the compiler to do global reasoning or to generate worse code. I've gotten into the habit of making things const unless I know I plan on mutating them, but I wish there was tooling that encouraged it. (BTW, this is something Rust does well by making things constant by default and requiring "mut" if it's mutable.)

Re: When static makes your C code 10 times faster

#5
post #3

I think a simple “const” would have also done the trick. Sometimes -O3 is clever enough to figure out that the value is never written, so it makes it an asm constant.

It is mostly about the fact that if the variable is not static, then it's non-local to the translation unit and can be modified from everywhere else. So its value needs to be loaded and a plain and slow division is applied.

Having it local or const makes the compiler able to inline it and do a simple bitwise and with a constant.

So yes, make your variables static const by default (if you really need global).

Re: When static makes your C code 10 times faster

#6
Wouldn’t making that const or using #define be a bit cleaner?

Honestly if I as the programmer knew that I was really trying to select bits from a number I’d just use a binary and directly. In that specific situation I think the intent is more clear that way. Like:

//select the bottom 8 bits

unsigned bottom8 = val & 0xff;

Re: When static makes your C code 10 times faster

#8
post #4

This can be accomplished more simply and reliably by marking modulus as const. The compiler currently has to reason about the whole compilation unit to determine that modulus is not modified, which works. However, if future code modifies modulus (either on purpose or accidentally) or something changes that prevents the compiler from performing global reasoning, the optimization will be lost. By marking the actual int…

If there were any expressions that took the address of the variable, then even both `static const` qualifiers wouldn't work for a sufficiently paranoid compiler.

Re: When static makes your C code 10 times faster

#9
post #4

This can be accomplished more simply and reliably by marking modulus as const. The compiler currently has to reason about the whole compilation unit to determine that modulus is not modified, which works. However, if future code modifies modulus (either on purpose or accidentally) or something changes that prevents the compiler from performing global reasoning, the optimization will be lost. By marking the actual int…

I agree. Static alone was the incorrect choice. If the global were being modified elsewhere in the file then this optimization would also not be possible.

The core optimization is modulus % constant (and a power-of-2 as well). The static just enabled the optimizer to do better heavy lifting to get there. A const would've made the intent clear to the human reader and the compiler.

static const would've been best.

Re: When static makes your C code 10 times faster

#10
post #8
post #4

This can be accomplished more simply and reliably by marking modulus as const. The compiler currently has to reason about the whole compilation unit to determine that modulus is not modified, which works. However, if future code modifies modulus (either on purpose or accidentally) or something changes that prevents the compiler from performing global reasoning, the optimization will be lost. By marking the actual int…

If there were any expressions that took the address of the variable, then even both `static const` qualifiers wouldn't work for a sufficiently paranoid compiler.

Are you sure? Isn't it UB to modify a const object? It will probably end up in a non-writable memory page.

EDIT: gcc seems to agree with me: you can see the optimized version here[1] and the unoptimzed version if you remove "const".

[1] https://godbolt.org/z/KWrW45rK8

Post reply on HN