This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

placement new operator not inlined

Hello


While inspecting some compiler-generated code, I was surprised to find a call to operator new(unsigned int, void*). This is the placement form of operator new which simply returns the pointer argument and which cannot be overridden by the application. I never thought I'd see an actual call to it. In particular, the following trivial code snippet:

#include <new>

char buffer[100];

int* test()
{
  return ::new ( (void*) buffer ) int(42);
}

produces similarly simple x86 output using gcc (gcc -O3 -S):

__Z4testv:
LFB16:
        .cfi_startproc
        movl    $42, _buffer
        movl    $_buffer, %eax
        ret
        .cfi_endproc

but leads to much more complicated output using the C6000 compiler 7.4.16 (cl6x.exe -mv64+ --abi=eabi -O3 -k --rtti --opt_for_speed=5 --include_path="%PATH_TO_CCS_INC%")

_Z4testv:
;** --------------------------------------------------------------------------*
           MVKL    .S2     buffer,B4
           MVKH    .S2     buffer,B4

           STW     .D2T2   B3,*SP--(8)       ; |6|
||         CALLP   .S2     _ZnwjPv,B3
||         MVK     .L1     0x4,A4            ; |7|

$C$RL0:    ; CALL OCCURS {_ZnwjPv} {0}       ; |7|
;** --------------------------------------------------------------------------*

           MVK     .S1     42,A3             ; |7|
||         MV      .L1     A4,A0             ; |7|

   [ A0]   STW     .D1T1   A3,*A0            ; |7|
           LDW     .D2T2   *++SP(8),B3       ; |8|
   [!A0]   ZERO    .L1     A0                ; |7|
           MV      .L1     A0,A4             ; |7|
           NOP             2
           RETNOP  .S2     B3,5              ; |8|
           ; BRANCH OCCURS {B3}              ; |8|

Curiously, the TI compiler explicitly calls operator new (unsigned int, void*) (requiring stack space and saving registers) and even ignores the fact that the return value is guaranteed to be the second argument.
Admittedly, none of that is wrong, but as you typically use placement new in more performance-critical areas, it would be a lot nicer if the compiler just removed the call completely.
Maybe you can consider implementing that optimization for a future compiler release, given that it should be a rather trivial to add.

Markus

  • I have submitted SDSCM00052820 as a request to consider this enhancement. It will go into the queue of potential enhancements for prioritization.
  • Bringing an old topic up again because I just looked into <new> and realized that the observed behavior is caused by a TI-specific modification. The <new> header contains this declaration/definition of placement new, special-cased for __TI_COMPILER_VERSION__ (placement new[] is a few lines below that and looks similar):

    #if defined(__TI_COMPILER_VERSION__)
    void *operator new  (std::size_t, void *ptr) _THROW0();
    #else
    inline void *operator new(_CSTD size_t, void *_Where) _THROW0()
    	{	// construct with placement at _Where
    	return (_Where);
    	}
    #endif /* defined(__TI_COMPILER_VERSION__) */
    

    What's the reason behind this special treatment? If I temporarily add a " && false" to the #if condition, TI CGT 7.4.x inlines placement new just fine.

    Maybe the idea is to be able to link with a debug library that adds size checks of some kind to placement new? In that case it'd mean a high price to pay for anyone who's not using that feature (which is probably almost everyone).

    Markus

    EDIT: additionally, any such feature would better be implemented using a user-defined operator new, say operator new(std::size_t, void *where, DoFunkyStuffTag x)

  • We use a different bug tracking system now; this issue will now be known as CODEGEN-2170.

    The good news is that we now use a totally different implementation the header file "new," so the question about __TI_COMPILER_VERSION__ is no longer relevant. The bad news is that we still don't inline it, and I don't know why. I suspect it's just something that has fallen through the cracks. I've bumped the issue internally for re-evaluation.