This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug ipa/59948] Optimize std::function


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?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]