Compiler optimizing out calls to new()

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Compiler optimizing out calls to new()

Oleg Smolsky via cfe-dev

Hi All,

 

A commit earlier this year, r325630, changed the behavior of the following program under –O1:

 

-----------------------------------------------------------------------------------

#include <new>

#include <stdlib.h>

extern "C" int printf(const char *, ...);

int UsedMyCode = 0;

void * operator new(std::size_t count)

{

    UsedMyCode = 1;

    return malloc(count);

}

int main(int argc, char * argv[])

{

    int* p = new int();

    *p = 10;

    printf("*p=%d.  UsedMyCode=%d\n", *p,  UsedMyCode);

    delete p;

    return 0;

}

 

The printed value of UsedMyCode became 0 after that checkin.

 

The compiler is eliminating the new/delete pair, printing just 10 for *p,  because  the usage

inside the function can be fully analyzed.

 

But I am wondering whether this is a valid optimization, because the implementation is not

calling the user supplied replacement as per 15.5.4.6. The complaint is that the side effects of

the user supplied replacement are not occurring.

 

The commit r325630 did not actually implement this optimization, but most likely it enabled

an already implemented optimization that was being foiled by something.

 

Any opinions?

 

Thanks

 

Sunil Srivastava

Sony Interactive Entertainment.

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Compiler optimizing out calls to new()

Oleg Smolsky via cfe-dev

(remembering to cc the list this time)

On 12/3/18 8:02 PM, Hal Finkel wrote:
On 12/3/18 7:44 PM, via cfe-dev wrote:

Hi All,

 

A commit earlier this year, r325630, changed the behavior of the following program under –O1:

 

-----------------------------------------------------------------------------------

#include <new>

#include <stdlib.h>

extern "C" int printf(const char *, ...);

int UsedMyCode = 0;

void * operator new(std::size_t count)

{

    UsedMyCode = 1;

    return malloc(count);

}

int main(int argc, char * argv[])

{

    int* p = new int();

    *p = 10;

    printf("*p=%d.  UsedMyCode=%d\n", *p,  UsedMyCode);

    delete p;

    return 0;

}

 

The printed value of UsedMyCode became 0 after that checkin.

 

The compiler is eliminating the new/delete pair, printing just 10 for *p,  because  the usage

inside the function can be fully analyzed.

 

But I am wondering whether this is a valid optimization, because the implementation is not

calling the user supplied replacement as per 15.5.4.6. The complaint is that the side effects of

the user supplied replacement are not occurring.

 

The commit r325630 did not actually implement this optimization, but most likely it enabled

an already implemented optimization that was being foiled by something.

 

Any opinions?

The implementation is allowed to elide those side effects, and the standard was clarified in recent years to reflect this explicitly. See 8.3.4p10, "An implementation is allowed to omit a call to a replaceable global allocation function (21.6.2.1, 21.6.2.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation..."

 -Hal

 

Thanks

 

Sunil Srivastava

Sony Interactive Entertainment.

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Compiler optimizing out calls to new()

Oleg Smolsky via cfe-dev
More generally, a (non-placement) new-expression is not required to call any 'operator new' in particular to get its storage. It's permitted to do so, but it's also permitted to get storage from another place (such as the heap) or combine multiple allocations into a single operator new call, so long as all the relevant side-conditions are satisfied. (Calls to 'operator new' from new-expressions are considered non-observable behavior in some sense.)

On Mon, 3 Dec 2018 at 18:25, Finkel, Hal J. via cfe-dev <[hidden email]> wrote:

(remembering to cc the list this time)

On 12/3/18 8:02 PM, Hal Finkel wrote:
On 12/3/18 7:44 PM, via cfe-dev wrote:

Hi All,

 

A commit earlier this year, r325630, changed the behavior of the following program under –O1:

 

-----------------------------------------------------------------------------------

#include <new>

#include <stdlib.h>

extern "C" int printf(const char *, ...);

int UsedMyCode = 0;

void * operator new(std::size_t count)

{

    UsedMyCode = 1;

    return malloc(count);

}

int main(int argc, char * argv[])

{

    int* p = new int();

    *p = 10;

    printf("*p=%d.  UsedMyCode=%d\n", *p,  UsedMyCode);

    delete p;

    return 0;

}

 

The printed value of UsedMyCode became 0 after that checkin.

 

The compiler is eliminating the new/delete pair, printing just 10 for *p,  because  the usage

inside the function can be fully analyzed.

 

But I am wondering whether this is a valid optimization, because the implementation is not

calling the user supplied replacement as per 15.5.4.6. The complaint is that the side effects of

the user supplied replacement are not occurring.

 

The commit r325630 did not actually implement this optimization, but most likely it enabled

an already implemented optimization that was being foiled by something.

 

Any opinions?

The implementation is allowed to elide those side effects, and the standard was clarified in recent years to reflect this explicitly. See 8.3.4p10, "An implementation is allowed to omit a call to a replaceable global allocation function (21.6.2.1, 21.6.2.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation..."

 -Hal

 

Thanks

 

Sunil Srivastava

Sony Interactive Entertainment.

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Compiler optimizing out calls to new()

Oleg Smolsky via cfe-dev

On 3 Dec 2018, at 21:51, Richard Smith via cfe-dev wrote:

More generally, a (non-placement) new-expression is not required to call
any 'operator new' in particular to get its storage.

To be precise, this rule applies to new-expressions that directly use one
of the "replaceable global allocation functions", which both includes some
placement forms (e.g. new (std::nothrow) double[10]) and excludes some
non-placement forms (e.g. new MyClass where MyClass declares an
operator new).

John.


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Compiler optimizing out calls to new()

Oleg Smolsky via cfe-dev
In reply to this post by Oleg Smolsky via cfe-dev

Thanks Hal and Richard,

 

Ø  The implementation is allowed to elide those side effects, and the standard was clarified in recent years to reflect this explicitly.

 

That settles it.

 

Thanks.

 

Sunil Srivastava

 

From: Finkel, Hal J. <[hidden email]>
Sent: Monday, December 3, 2018 6:02 PM
To: Srivastava, Sunil <[hidden email]>
Cc: Richard Smith <[hidden email]>
Subject: Re: [cfe-dev] Compiler optimizing out calls to new()

 

On 12/3/18 7:44 PM, via cfe-dev wrote:

Hi All,

 

A commit earlier this year, r325630, changed the behavior of the following program under –O1:

 

-----------------------------------------------------------------------------------

#include <new>

#include <stdlib.h>

extern "C" int printf(const char *, ...);

int UsedMyCode = 0;

void * operator new(std::size_t count)

{

    UsedMyCode = 1;

    return malloc(count);

}

int main(int argc, char * argv[])

{

    int* p = new int();

    *p = 10;

    printf("*p=%d.  UsedMyCode=%d\n", *p,  UsedMyCode);

    delete p;

    return 0;

}

 

The printed value of UsedMyCode became 0 after that checkin.

 

The compiler is eliminating the new/delete pair, printing just 10 for *p,  because  the usage

inside the function can be fully analyzed.

 

But I am wondering whether this is a valid optimization, because the implementation is not

calling the user supplied replacement as per 15.5.4.6. The complaint is that the side effects of

the user supplied replacement are not occurring.

 

The commit r325630 did not actually implement this optimization, but most likely it enabled

an already implemented optimization that was being foiled by something.

 

Any opinions?

The implementation is allowed to elide those side effects, and the standard was clarified in recent years to reflect this explicitly. See 8.3.4p10, "An implementation is allowed to omit a call to a replaceable global allocation function (21.6.2.1, 21.6.2.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation..."

 -Hal

 

Thanks

 

Sunil Srivastava

Sony Interactive Entertainment.

 



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev