https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86276
--- Comment #2 from Jan Hubicka <hubicka at gcc dot gnu.org> --- With -O3 we now do quite well. _Z4goodv: .LFB1248: .cfi_startproc ret .cfi_endproc .LFE1248: .size _Z4goodv, .-_Z4goodv .p2align 4 .globl _Z3badv .type _Z3badv, @function _Z3badv: .LFB1260: .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movq %rdi, %rbx movl $22, %edi call _Znwm movb $2, (%rax) leaq 22(%rax), %rdx movq %rax, (%rbx) addq $1, %rax movq %rax, 8(%rbx) movq %rbx, %rax movq %rdx, 16(%rbx) popq %rbx .cfi_def_cfa_offset 8 ret good is optimized to empty function since we now have __builtin_operator_new. Bad is pretty straighforward construction of the vector: struct vector bad () { unsigned char * __result; unsigned char * _26; unsigned char * _28; <bb 2> [local count: 1073741824]: _26 = operator new (22); something_3(D)->D.25721._M_impl.D.25032._M_start = _26; _28 = _26 + 22; something_3(D)->D.25721._M_impl.D.25032._M_end_of_storage = _28; MEM[(char * {ref-all})_26] = 2; __result_59 = _26 + 1; something_3(D)->D.25721._M_impl.D.25032._M_finish = __result_59; return something_3(D); } With -O2 however we end up offlining: ;; Function bad (_Z3badv, funcdef_no=1260, decl_uid=25847, cgraph_uid=171, symbol_order=187) struct vector bad () { void * D.27512; const unsigned char D.25850[1]; unsigned char * _33; unsigned char * _38; unsigned char * _40; unsigned char * _41; long int _42; long unsigned int _43; void * _44; long unsigned int _47; vector(2) long unsigned int _56; <bb 2> [local count: 1073741824]: MEM[(struct _Vector_impl_data *)something_3(D)]._M_start = 0B; MEM[(struct _Vector_impl_data *)something_3(D)]._M_end_of_storage = 0B; _38 = operator new (22); <bb 3> [local count: 1073741824]: _47 = (long unsigned int) _38; _56 = {_47, _47}; MEM <vector(2) long unsigned int> [(unsigned char * *)something_3(D)] = _56; _33 = _38 + 22; something_3(D)->D.25721._M_impl.D.25032._M_end_of_storage = _33; D.25850[0] = 2; std::vector<unsigned char>::_M_assign_aux.isra (something_3(D), &D.25850, &MEM <const unsigned char[1]> [(void *)&D.25850 + 1B]); <bb 4> [local count: 1073741824]: D.25850 ={v} {CLOBBER(eos)}; return something_3(D); <bb 5> [count: 0]: <L2>: D.25850 ={v} {CLOBBER(eos)}; _41 = MEM[(struct _Vector_base *)something_3(D)]._M_impl.D.25032._M_start; if (_41 != 0B) goto <bb 6>; [53.47%] else goto <bb 7>; [46.53%] <bb 6> [count: 0]: _40 = MEM[(struct _Vector_base *)something_3(D)]._M_impl.D.25032._M_end_of_storage; _42 = _40 - _41; _43 = (long unsigned int) _42; operator delete (_41, _43); <bb 7> [count: 0]: _44 = __builtin_eh_pointer (1); __builtin_unwind_resume (_44); } So it first constructs empty vector and then offlines assignment froom C array. Since it may throw an exception there is EH calling delete which is always noop. I think we need to start with ability to IPA propagate that the vector is empty and thus _M_start==_M_end_of_storage Curiously codegen for good is even longer: void good () { void * D.27490; unsigned char * something$_M_end_of_storage; unsigned char * something$_M_start; struct vector something; const unsigned char D.25837[1]; void * _10; unsigned char * _36; unsigned char * _41; long int _45; long unsigned int _46; long int _49; long unsigned int _50; vector(2) long unsigned int _53; long unsigned int _59; <bb 2> [local count: 1073741824]: MEM[(struct _Vector_impl_data *)&something] ={v} {CLOBBER(bob)}; _41 = operator new (22); goto <bb 4>; [100.00%] <bb 3> [count: 0]: <L4>: D.25837 ={v} {CLOBBER(eos)}; goto <bb 10>; [100.00%] <bb 4> [local count: 1073741824]: _59 = (long unsigned int) _41; _53 = {_59, _59}; _36 = _41 + 22; D.25837[0] = 2; MEM <vector(2) long unsigned int> [(void *)&something] = _53; MEM <unsigned char *> [(struct vector *)&something + 16B] = _36; std::vector<unsigned char>::_M_assign_aux.isra (&something, &D.25837, &MEM <const unsigned char[1]> [(void *)&D.25837 + 1B]); <bb 5> [local count: 1073741824]: something$_M_start_20 = MEM <unsigned char *> [(struct vector *)&something]; something$_M_end_of_storage_21 = MEM <unsigned char *> [(struct vector *)&something + 16B]; D.25837 ={v} {CLOBBER(eos)}; if (something$_M_start_20 != 0B) goto <bb 6>; [53.47%] else goto <bb 7>; [46.53%] <bb 6> [local count: 574129752]: _45 = something$_M_end_of_storage_21 - something$_M_start_20; _46 = (long unsigned int) _45; operator delete (something$_M_start_20, _46); [tail call] <bb 7> [local count: 1073741824]: something ={v} {CLOBBER(eob)}; something ={v} {CLOBBER(eos)}; return; <bb 8> [count: 0]: <L3>: something$_M_start_22 = MEM <unsigned char *> [(struct vector *)&something]; something$_M_end_of_storage_23 = MEM <unsigned char *> [(struct vector *)&something + 16B]; D.25837 ={v} {CLOBBER(eos)}; if (something$_M_start_22 != 0B) goto <bb 9>; [53.47%] else goto <bb 10>; [46.53%] <bb 9> [count: 0]: _49 = something$_M_end_of_storage_23 - something$_M_start_22; _50 = (long unsigned int) _49; operator delete (something$_M_start_22, _50); <bb 10> [count: 0]: something ={v} {CLOBBER(eob)}; _10 = __builtin_eh_pointer (2); __builtin_unwind_resume (_10); }