That is not what any compiler writer I know would say, for all compilers I'm aware of assume that casting a pointer to an integer causes the pointer to escape and every integer-to-pointer conversion creates a pointer that may alias any external pointer (including the aforementioned escaping pointers). The problem that's been identified is that this is not sufficient .
It doesn't sound to me like clang is treats pointer-to-int conversions as having release semantics with regard to later int-to-pointe conversions, since if the conversions really were being processed with such semantics, any pointer produced by an integer-to-pointer conversion would be recognized as potentially aliasing every pointer that has leaked.
With LLVM, there is another wrinkle, in that memory is untyped, so effectively every load or store instruction is converting its type to an integer.
So, LLVM needs to include acquire/release notations when the conversions occur as a result of source-code constructs and, until tools that generate LLVM can properly generate such notations, a "force soundness" mode that would sacrifice optimizations for the benefit of people who would prefer a compiler that generates code that's reliably correct, even if it's sub-optimal, to one which generates more "efficient" code that will "probably" work.
(it doesn't help that the LLVM community isn't particularly welcoming towards formalizing their semantic model).
I don't think it would be possible to formalize anything resembling the LLVM semantic model without making some fundamental changes to it first. Such changes would include the abandonment of the idea that optimization must never observably affect the behavior of correct programs, and its replacement with specifications describing when transformations may be generally performed, and what constructs would block them. A program whose behavior might be affected by such transformations could be a correct program if it would meet all its application requirements with any allowable combination of transforms applied.
Consider, for example, the following two language rules: 1. If program would enter a loop whose exit point is statically reachable, but the loop would never terminate, an implementation may behave in arbitrary fashion; 2. If no individual operation within a loop would be observably ordered before any later operation that is statically reachable from it, the execution of the loop or any portion thereof may be reordered with respect to that later operation, or omitted entirely if it is not observably ordered before any observable operation.
If one allows that an implementation may impose a limit on a program's execution time, and raise a signal if it determines that the limit either has been exceeded, or would inevitably be exceeded in the absence of the signal, that would give an implementation license to trap if it happens to detect that it will never escape a particular loop. I can easily imagine situations where it may be useful to have an implementation trap on endless loops that it happens to detect, or where it would be useful to postpone or omit the execution of a loop which would be unable to affect program behavior under any circumstance where it would terminate. Note that if a compiler were given something like:
int test(long long x, int mode)
{
do
{ x = no_side_effects(x); }
while(x & 15);
if (!mode) return 0;
return x & 1;
}
Under the latter rules, a compiler would be allowed to generate code that skips the execution of the loop in cases where mode
is zero, or that performs the loop unconditionally and then returns zero without bothering to look at the value of mode
. If mode
is non-zero, however, the read of x
within the return
statement would be sequenced after its computation within the loop. If a compiler observes that x & 15
is zero, it would be entitled to assume that x & 1
would likewise be zero, but a compiler that postpones the evaluation of x & 15
that would have occurred within the loop would not be entitled to use computations it hasn't performed to justify assumptions about the value of x & 1