On the redundancy of C99's restrict
blog.frama-c.com
blog.frama-c.com
There's a new keyword in C99, which can be seen as a bad thing. There's also a confusing one-liner which compilers can reduce to a noop and which they can take as the same guarantee as "restrict". One of the most popular compilers sees it as noop but doesn't increase assumptions. Author calls for detection of the one-liner in compilers because he prefers it to the new keyword.
Why doesn't it make sense to me? I'd much rather see restrict than some not googlable magic line. If you're stuck to some old version of a compiler, it's usually (in my experience) because you need some specific architecture support - why not just drop down to asm when you really really need optimised code at that level? Why would you not have C99 support if you're writing for x86_64?
Maybe I'm missing the big idea about specifying pairwise not-aliasing, but can't it be achieved by passing the pointers to another function with restrict attributes instead and ensuring it's inlined?
"The previous post assumes the reader is familiar with the notion of undefined behavior and how C compilers have started to justify their more aggressive optimizations along the lines of “this program has always been undefined”....
This was not a serious suggestion, but should be understood as an argument in the debate about the exploitation of undefined behavior in compiler optimization.... I was not suggesting to replace the respected restrict keyword with an awkward replacement. All the arguments I put forward were in bad faith."
[1]: http://blog.frama-c.com/index.php?post/2012/07/25/The-previo...
So, no, this hack is not a replacement for "restrict" keyword in C99. If you use C99, use restrict. If you use C89, use __restrict or whatever your compiler provides you with.
Consider memcpy; its arguments are declared restrict. This not only means that the source and destination pointers cannot be the same (which is what Pascal's "replacement" says), but also means that the buffers cannot overlap at all (i.e. the src pointer cannot be anywhere in the range [dst-(length-1), dst+(length-1)]).
restrict also has the virtue of making this contract apparent to your callers, as it's part of the API. People should know that they can't call memcpy with overlapping buffers, and use memmove instead. If the information is instead encoded in a cryptic line in the implementation, then it isn't obvious to a developer who intends to use the function.
http://blog.frama-c.com/index.php?post/2012/07/25/The-restri...
"(* p=* p) & (* q=* q);"
"inform[s] the compiler that f2() will never be called with aliasing arguments."
Thanks
It's a common approach in C compilers for inferring more optimization-relevant semantics than the language constructs explicitly specify.
See also the C99 rationale:
"Undefined behavior gives the implementor license not to catch certain program errors that are difficult to diagnose. It also identifies areas of possible conforming language extension: the implementor may augment the language by providing a definition of the officially undefined behavior."
Undefined behavior only occurs in case of program errors or language extensions, in which case you're not dealing with standard C, but C-with-extensions.
It is only undefined behavior if you call the function with aliasing arguments, which is exactly what you are committing not to do anyway. It is only similar to writing the function in C99 with restrict and then calling it with aliasing pointers: you get garbage but it is your fault.
> Anyway it looks like a mess.
I actually wrote this blog post in reaction to the ongoing debate about the exploitation of undefined behavior by C compilers for optimization. As Tom Duff noted in other circumstances, “This code forms some sort of argument in that debate, but I'm not sure whether it's for or against.”
Can you provide some links to other examples of this?
Programmers might think that it is okay to use uninitialized variables as a source of additional entropy (xoring with the real source of entropy), but it isn't, because the compiler will treat the uninitialized access as undefined behavior and eliminate code altogether: http://kqueue.org/blog/2012/06/25/more-randomness-or-less/
This 3-part blog post by Chris Lattner has various examples: http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
So, it looks like they do quite good job. They noticed that there was some feature needed, provided with some workaround. They added it to standard. No workarounds needed anymore. Workaround that uses some compiler features, but in terms of programming language don't make any sense. That's great, makes C better with same, good sanity. In fact, one of best things I like C for. :)
Yuck, I would fire the developer with such clever tricks in our code base.