https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110378
Bug ID: 110378 Summary: SRA for destructors Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: hubicka at gcc dot gnu.org Target Milestone: --- In thestcase from PR109849 built with profile feedback we get the following cleanup: <L10>: D.28322 ={v} {CLOBBER}; cur ={v} {CLOBBER(eol)}; std::vector<std::pair<unsigned int, unsigned int> >::~vector (&stack); _28 = __builtin_eh_pointer (2); __builtin_unwind_resume (_28); which calls destructor of std::vector. This destructor compiles to: void std::vector<std::pair<unsigned int, unsigned int> >::~vector (struct vector * const this) { struct pair * _6; struct pair * _7; long int _8; long unsigned int _15; ;; basic block 2, loop depth 0, count 10000 (precise) ;; prev block 0, next block 3, flags: (NEW, REACHABLE, VISITED) ;; pred: ENTRY [always] count:10000 (precise) (FALLTHRU,EXECUTABLE) _6 = MEM[(struct _Vector_base *)this_3(D)]._M_impl.D.25963._M_end_of_storage; _7 = MEM[(struct _Vector_base *)this_3(D)]._M_impl.D.25963._M_start; _8 = _6 - _7; if (_7 != 0B) goto <bb 3>; [100.00%] else goto <bb 4>; [0.00%] ;; succ: 3 [always] count:10000 (precise) (TRUE_VALUE,EXECUTABLE) ;; 4 [never] count:0 (precise) (FALSE_VALUE,EXECUTABLE) ;; basic block 3, loop depth 0, count 10000 (precise) ;; prev block 2, next block 4, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [always] count:10000 (precise) (TRUE_VALUE,EXECUTABLE) _15 = (long unsigned int) _8; operator delete (_7, _15); [tail call] ;; succ: 4 [always] count:10000 (precise) (FALLTHRU,EXECUTABLE) ;; basic block 4, loop depth 0, count 10000 (precise) ;; prev block 3, next block 1, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [never] count:0 (precise) (FALSE_VALUE,EXECUTABLE) ;; 3 [always] count:10000 (precise) (FALLTHRU,EXECUTABLE) return; ;; succ: EXIT [always] count:10000 (precise) (EXECUTABLE) /usr/include/c++/13/bits/stl_vector.h:735:7 } and it is used twice in code that is considered cold. Since the code itself is longer than the call of operator delete, it makes sense to not inline it. Before ipa-cp it is: Released 8 names, 53.33%, removed 8 holes void std::vector<std::pair<unsigned int, unsigned int> >::~vector (struct vector * const this) { struct pair * _1; struct pair * _2; struct pair * _6; struct pair * _7; long int _8; long int _9; long unsigned int _10; struct _Vector_impl * _11; ;; basic block 2, loop depth 0, count 1073741824 (estimated locally), maybe hot ;; prev block 0, next block 3, flags: (NEW, REACHABLE, VISITED) ;; pred: ENTRY [always] count:1073741824 (estimated locally) (FALLTHRU,EXECUTABLE) _1 = this_3(D)->D.26656._M_impl.D.25963._M_finish; _2 = this_3(D)->D.26656._M_impl.D.25963._M_start; std::_Destroy<std::pair<unsigned int, unsigned int>*> (_2, _1); _6 = MEM[(struct _Vector_base *)this_3(D)]._M_impl.D.25963._M_end_of_storage; _7 = MEM[(struct _Vector_base *)this_3(D)]._M_impl.D.25963._M_start; _8 = _6 - _7; _9 = _8 /[ex] 8; _10 = (long unsigned int) _9; if (_7 != 0B) goto <bb 3>; [53.47%] else goto <bb 4>; [46.53%] ;; succ: 3 [53.5% (guessed)] count:574129752 (estimated locally) (TRUE_VALUE,EXECUTABLE) ;; 4 [46.5% (guessed)] count:499612072 (estimated locally) (FALSE_VALUE,EXECUTABLE) ;; basic block 3, loop depth 0, count 574129753 (estimated locally), maybe hot ;; prev block 2, next block 4, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [53.5% (guessed)] count:574129752 (estimated locally) (TRUE_VALUE,EXECUTABLE) _11 = &MEM[(struct _Vector_base *)this_3(D)]._M_impl; std::__new_allocator<std::pair<unsigned int, unsigned int> >::deallocate (_11, _7, _10); ;; succ: 4 [always] count:574129753 (estimated locally) (FALLTHRU,EXECUTABLE) /usr/include/c++/13/bits/alloc_traits.h:516:35 ;; basic block 4, loop depth 0, count 1073741824 (estimated locally), maybe hot ;; prev block 3, next block 1, flags: (NEW, REACHABLE, VISITED) ;; pred: 2 [46.5% (guessed)] count:499612072 (estimated locally) (FALSE_VALUE,EXECUTABLE) ;; 3 [always] count:574129753 (estimated locally) (FALLTHRU,EXECUTABLE) /usr/include/c++/13/bits/alloc_traits.h:516:35 *this_3(D) ={v} {CLOBBER}; return; ;; succ: EXIT [always] count:1073741824 (estimated locally) (EXECUTABLE) /usr/include/c++/13/bits/stl_vector.h:735:7 } I think it is the clobber that prevents ipa-sra :)