https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59948
Jan Hubicka <hubicka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |mjambor at suse dot cz --- Comment #6 from Jan Hubicka <hubicka at gcc dot gnu.org> --- The nonzero check rewrite is already in tree, so .optimized dump is now better: int m() () { struct function h; int _23; <bb 2>: MEM[(int (*<T5861>) (int) *)&h] = f; h._M_invoker = _M_invoke; h.D.26130._M_manager = _M_manager; _23 = f (1); std::_Function_base::_Base_manager<int (*)(int)>::_M_manager (&MEM[(struct _Function_base *)&h]._M_functor, &MEM[(struct _Function_base *)&h]._M_functor, 3); h ={v} {CLOBBER}; return _23; } We fail to inline f because at .release_ssa time it is still passed via memory: int m() () { struct function h; bool (*<T5408>) (union _Any_data &, const union _Any_data &, _Manager_operation) _2; int _4; bool (*<T5408>) (union _Any_data &, const union _Any_data &, _Manager_operation) _5; <bb 2>: MEM[(struct _Function_base *)&h]._M_manager = 0B; MEM[(int (*<T5861>) (int) *)&h] = f; h._M_invoker = _M_invoke; h.D.26130._M_manager = _M_manager; _4 = std::function<int(int)>::operator() (&h, 1); Where operator () is: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}] (const struct function * const this, int __args#0) { bool (*<T543f>) (union _Any_data &, const union _Any_data &, _Manager_operation) _3; int (*<T585d>) (const union _Any_data &, int) _4; const union _Any_data * _5; int _7; <bb 2>: _3 = MEM[(bool (*<T5408>) (union _Any_data &, const union _Any_data &, _Manager_operation) *)this_1(D) + 16B]; ... We have Jump functions of caller int m()/290: callsite int m()/290 -> _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}]/361 : param 0: UNKNOWN Aggregate passed by reference: offset: 0, cst: f offset: 128, cst: _M_manager offset: 192, cst: _M_invoke param 1: CONST: 1 So we know that f is passed in the aggregate. We also know operator () is using it: Jump functions of caller _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}]/361: callsite _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}]/361 -> void std::__throw_bad_function_call()/539 : indirect aggregate callsite, calling param 0, offset 192, by reference, for stmt _7 = _4 (_5, __args#0_9(D)); param 0: UNKNOWN param 1: PASS THROUGH: 1, op nop_expr Later we propagate this call into _M_invoke and we lost track of f() that is invoked by it. We do have jump functoin here too: Jump functions of caller static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = int; _Functor = int (*)(int); _A indirect aggregate callsite, calling param 0, offset 0, by reference, for stmt _5 = _3 (__args#0_6(D)); param 0: PASS THROUGH: 1, op nop_expr Martin, what is going wrong here?