

On the redundancy of C99's restrict - pascal_cuoq
http://blog.frama-c.com/index.php?post/2012/07/25/On-the-redundancy-of-C99-s-restrict

======
viraptor
So let me try to TL;DR this article:

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?

~~~
3JPLW
See also Pascal's followup post, "The previous post was written in jest."[1]

 _"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...](http://blog.frama-c.com/index.php?post/2012/07/25/The-previous-
post-was-written-in-jest)

------
exDM69
This technique may work for simple pointers to integers but is very clumsy if
you consider real world use cases where you have pointers to arrays of
structures. There's no oneliner magic that tell the compiler that they don't
alias.

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.

------
gioele
Having `restrict` in the function declaration allow other tools to know about
the aliasing constraint without the need to read and understand the function
code. Think of documentation tools, static checkers, code completion
functionalities in IDEs...

------
stephencanon
The proposed replacement doesn't actually have the same semantics as restrict.
I believe that Pascal knows this, as he's a smart guy.

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.

~~~
pascal_cuoq
I find your explanation about “restrict” being part of the function interface
extremely insightful. Just that makes my misguided attempt at humor worth it
(for me). The idea was in gioele's comment too but you made me understand it.

------
thornjm
Could someone please explain how this line:

"(* p=* p) & (* q=* q);"

"inform[s] the compiler that f2() will never be called with aliasing
arguments."

Thanks

~~~
cygx
In contrast to &&, & does not introduce a sequence point, which makes the
expression illegal (ie it will exhibit undefined behavior) if p and q alias:
an object may only be modified once between sequence points.

~~~
justincormack
Undefined behaviour yes, but does that really make it illegal? Sure the
compiler is allowed to play some AC/DC at this point or other undefined
behaviour, but I am not sure that makes it an _assertion_ per se?

~~~
mjn
That's true, but in many cases of undefined behavior, compilers take the
liberty of interpreting it as an assertion. In this case, for example, it's
legal for the compiler to assume that p and q don't alias when it sees this
expression, because either: 1) they really don't alias, in which case the
assumption and subsequent optimization is correct; or 2) they really do alias,
but in that case the behavior is undefined, so the compiler's choice to apply
"erroneous" optimizations is not prohibited.

It's a common approach in C compilers for inferring more optimization-relevant
semantics than the language constructs explicitly specify.

------
krollew
Doesn't "undefined behaviour" means that solution might not be portable?
Anyway it looks like a mess. I guess the most of C programmers wouldn't have
any idea what that first line of function does and why. If one see restricted
he just looks on google what does it mean. Looking for meaning of your
solution might be troublesome.

~~~
pascal_cuoq
> Doesn't "undefined behaviour" means that solution might not be portable?

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.”

~~~
capisce
> ongoing debate about the exploitation of undefined behavior by C compilers
> for optimization

Can you provide some links to other examples of this?

~~~
pascal_cuoq
There was much gnawing of teeth when compilers started to take advantage of
the “strict aliasing rule”: [http://labs.qt.nokia.com/2011/06/10/type-punning-
and-strict-...](http://labs.qt.nokia.com/2011/06/10/type-punning-and-strict-
aliasing/)

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-...](http://blog.llvm.org/2011/05/what-every-c-programmer-should-
know.html)

------
pjmlp
So he wants to replace something informative like restrict by this expression
"(* p=* p) & (* q=* q);"?!

Yuck, I would fire the developer with such clever tricks in our code base.

------
the_mitsuhiko
If only there was a preprocessor in the language that could be used to hide
the keyword from older compilers.

------
cliffbean
It's kind of late to be complaining about a new keyword in a language standard
from 1999 in 2012. However, it does reflect an attitude I've seen in a variety
of places, that C99 is a corruption of the spirit of C, which was most closely
captured in the old ANSI C. Standard C, they called it. To these people, C99
(and its successors) will always be a proposal, a hypothetical, and a foreign
idea. Fun to think about and debate, but not really something that really
matters.

