[LLVMdev] optimization assumes malloc return is non-null
Mike Stump
mrs at apple.com
Thu May 1 15:11:33 PDT 2008
On Apr 30, 2008, at 9:26 PM, Chris Lattner wrote:
> Personally to me, I have a bigger axe to grind with C++ operator new.
> AFAIK, the standard doesn't give leeway to do a number of interesting
> optimizations for new/delete because the user is explicitly allowed to
> override them and the std doesn't require them to behave "as
> expected".
Yes it does:
Replaceable:
a C++ program may define a function with this function
signature
that displaces the default version defined by the C++
Standard
library.
Required behavior:
Return a non-null pointer to suitably aligned
storage
(_basic.stc.dynamic_), or else throw a bad_alloc exception.
This
requirement is binding on a replacement version of this function.
These _are_ the defined semantics. You cannot imagine any other
semantic and substitute it. Any program that does, is outside the
scope of the standard and has _no_ constraint upon it. Meaning, the
compiler free to do anything, technically.
The latitude exists to do exactly what you want to do as in
intelligent optimization person.
You can see that this is what the standard mandates by imagining what
would happen if you had the allocator return the same pointer to the
same memory all the time that was maximally aligned. What does cout
<< "Hi" << "there" do, or some other complex program that underneath
wanted to use the allocator? Either, they _have_ to work, which is
impossible and nonsensical, or there has to be enough latitude in the
standard to allow the code to not work. The requirements on the
replacement versions of the allocators is the constraint that provides
the mechanism to decide wether your program is going to work. If you
behaves exactly as if you allocated suitably aligned storage and
return it or throw bad_alloc, then, the execution of the program is as
constrained by the abstract semantics. If not then _all_ requirements
of the standard are vacated. In particular, printf("Hi") in the
allocator means the standard places no requirements on the program.
You can print Hi, not print it, print it twice, whatever you want.
> Very interesting properties to me would be:
>
> 1) Safety to remove "delete (new int);" and friends.
You are free to do that.
> 2) Aliasing guarantees about the result of new.
The replacements have their behavior required (you can also read this
as constrained). They are required to allocate new memory, and
aliasing falls out from that.
> There are a huge number of code pessimizations that happen because
> the optimizer has to
> assume that 'new' can return a pointer that already exists in the
> program.
This one is safe. It has to behaves as if it allocates storage. If
you can detect it didn't, there are no requirements placed upon the
semantics of the code.
> 3) Lifetime guarantees. It would be really nice to be able to delete
> the store to X in: " double *X = ...; *X = 4.0; delete X;" which is
> safe with 'free'.
Again, you can't inspect the value as there is no way to have those
semantics without also then violating the required semantics of the
deallocator and if you did that, then that standard places no
requirements on the program, so net result you are free to omit the
store.
> A lot of nice guarantees that we have with malloc/free aren't
> available with new/delete. Also, since new/delete can be overridden
> at any time (as late as runtime with LD_PRELOAD and friends),
3 The program's definitions are used instead of the default versions
supplied by the implementation (_dcl.fct.def_). Such
replacement
occurs prior to program startup (_basic.def.odr_, _basic.start_).
So, the replacement is done before start, if later, there are no
requirements. And, the replacement has known semantics.
More information about the llvm-dev
mailing list