Live data from Hacker News

Why Const Doesn't Make C Code Faster

theartofmachinery.com

151–160 of 197 posts

Re: Why Const Doesn't Make C Code Faster

#151

gcc has some attributes to help with that, for example try __attribute__((pure)) on funcs that will always return the same thing for the same inputs (given the same global state) and do not modify said input or state (and thus can be called more or fewer times than programmer wrote). Usually gcc will be quite aggressive with optimizations if you use that. For even more aggressiveness, try __attribute__((const)) which…

>__attribute__((const)) which tells it that the func accesses NOTHING but the params, not even global vars.

If you're actually not accessing any global state at all (including making no memory allocation), shouldn't the compiler figure that out anyway? That doesn't seem like something that would be very hard to check for.

Re: Why Const Doesn't Make C Code Faster

#152
post #102

Earlier quoted context omitted.

Local constant stack values surely can be completely deterministically verified as such by the optimiser even without the `const` modifier. Only if their address doesn't escape.

The compiler will detect any attempt at taking the address of the variable (including fancy things like most inline assembly) and skip the optimization, marking it as requiring a memory location. However, it can still cheat by rearranging the memory write or even letting linker initialize the address.

We are in violent agreement.

An explicitly const-qualified object instead can be replaced with its value even if its address has escaped.

Re: Why Const Doesn't Make C Code Faster

#153

gcc has some attributes to help with that, for example try __attribute__((pure)) on funcs that will always return the same thing for the same inputs (given the same global state) and do not modify said input or state (and thus can be called more or fewer times than programmer wrote). Usually gcc will be quite aggressive with optimizations if you use that. For even more aggressiveness, try __attribute__((const)) which…

>__attribute__((const)) which tells it that the func accesses NOTHING but the params, not even global vars. If you're actually not accessing any global state at all (including making no memory allocation), shouldn't the compiler figure that out anyway? That doesn't seem like something that would be very hard to check for.

Not if it is defined in another translation unit and you are not using LTO.

Re: Why Const Doesn't Make C Code Faster

#154

> This is true in practice because enough real-world C code has “I know what I’m doing” casting away of const. I found this out the hard way when I implemented OptimumC, the first data flow analysis optimizer for DOS C compilers back in the 1980's. I had to undo doing optimizations on const. Anecdote: Optimum C blew away all the other C compilers on a magazine benchmark article because it figured out that the benchma…

> Anecdote: Optimum C blew away all the other C compilers on a magazine benchmark article because it figured out that the benchmark code did nothing and deleted it.

I remember this problem being discussed in a CPPCon talk a few years ago, and some ways to "trick" the (modern) compilers into not optimising away the benchmark code - I think it was Chandler Carruth's "Tuning C++" talk: https://youtu.be/nXaxk27zwlk

Re: Why Const Doesn't Make C Code Faster

#155
post #118

Earlier quoted context omitted.

If the initial object itself isn't const, then merely declaring the function parameter as a pointer to const won't guarantee that some other thread of execution won't change the value under your nose. Or if you have multiple pointer parameters, they can alias each other. Indirection in C and C++ is a mess, but at least C has the "restrict" keyword. Best to program with value types whenever you can, and use pointers a…

> won't guarantee that some other thread of execution won't change the value under your nose My understanding is that compilers can always assume that there is no other thread involved, which (part of) why C11 atomics are necessary. Is that not the case?

Yes, but it can't assume any random function call it does doesn't use a different pointer to the same object which is not const. So, even if you don't cast const to non-const pointers you can run into the const value changing.

Re: Why Const Doesn't Make C Code Faster

#156
post #108

Earlier quoted context omitted.

While specifying inline alone is useless for optimization, the inline specifier is important for another type of optimization: putting a function in a header file. If you put a function in a header file and don't mark it inline, that tends to be undefined behavior because it tends to violate the One Definition Rule, (both C and C++).

How does making the function static not solve this in C? Then the definition is local to the translation unit and there are no linkage concerns at all.

Static but not inline functions will trigger warnings of unused functions. Static and inline does not trigger this.

Re: Why Const Doesn't Make C Code Faster

#157

Earlier quoted context omitted.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p053... has an explanation. In short, placement new (or some scenarios involving unions) technically cause undefined behavior if you try to use the object after the call to placement new, since the pre-existing object there has had its lifetime expire. std::launder lets you use a pre-existing pointer to the memory at the same location to access the data there.

Yes, I know what std::launder does, and that document contains some of my own thoughts: namely, placement new (the only use I've seen suggested) should automatically launder, and std::launder should just not exist.

AFAIK placement new does launder. But both new and launder have no effect on their argument (well, placement new of course constructs an object there), they only 'bless' pointer returned from it. The use case is if you placement new on some byte storage. Now you want to access the object stored there, and of course you do not want to placement new the storage again, nor you have cached the result of the previous placement new (it would be suboptimal), instead you want to get a pointer to T from the storage address itself.

Re: Why Const Doesn't Make C Code Faster

#158

Earlier quoted context omitted.

> Unfortunately in C++, the compiler is not allowed to assume that if it passes a const reference to a function, that function will not change the object. how could it make that assumption ? there is nothing that prevents you to implement the function in fortran or even in raw assembly

You have it backwards. const is your promise to the compiler that the object won't change. It doesn't care whether you const_cast, implement the function in fortran or use raw assembly to mess with that object - it assumes that you don't. If you modify a const object in any way you have violated the C++ standard and get UB in return. Now, the tricky part is that const objects (i.e. objects declared as const ) enjoy t…

Interestingly, top level cost does not guarantee immutability, but any const member reachable from that reference is in fact guaranteed to be immutable: ergo:

  template
  struct deep_const { const T value; };

  template
  const deep_const& freeze(const T&) { /* magic */ }

  template
  const T & thaw(deep_const const&) { /* more magic */ }
magic and more magic left as an exercise for the reader.

edit: I do not think either GCC or clang take advantage of that though, so currently it is just a curiosity.

edit: missed actual const keywords /facepalm

Re: Why Const Doesn't Make C Code Faster

#159
post #108

The key difference between `const` and the `register` and `inline` keywords is that, despite all of them often flagging optimisations that the compiler can often work out anyway, `const` still aids human comprehension by declaring constraints, whereas the latter two do not. It seems that interprocedure optimisations in modern compilers make a lot of const-by-reference optimisations apply even when the code is mutable…

While specifying inline alone is useless for optimization, the inline specifier is important for another type of optimization: putting a function in a header file. If you put a function in a header file and don't mark it inline, that tends to be undefined behavior because it tends to violate the One Definition Rule, (both C and C++).

You’re completely correct. I was conflating the ODR-adhering standard ‘inline’ keyword with the various inlining pragma in some compilers that actually are about solely forcing inlining as an optimisation.

Re: Why Const Doesn't Make C Code Faster

#160
post #77
post #60

Earlier quoted context omitted.

Cast away const. One of the many reasons I gave up on C++. What is const if it can be cast away?

const should have been renamed to readonly, because that's what it means. It means that a variable only has readonly access to a value, but it is possible that another variable has write permissions, and so a compiler can not assume that just because one variable has readonly permission, that all variables have readonly permission except for in very limited circumstances.

const values are really const (i.e. immutable). Const references are actually readonly. Could have used different keywords of course.
Post reply on HN