This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug ipa/59948] Optimize std::function
- From: "glisse at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sun, 26 Jan 2014 13:24:53 +0000
- Subject: [Bug ipa/59948] Optimize std::function
- Auto-submitted: auto-generated
- References: <bug-59948-4 at http dot gcc dot gnu dot org/bugzilla/>
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59948
--- Comment #1 from Marc Glisse <glisse at gcc dot gnu.org> ---
(In reply to Marc Glisse from comment #0)
> if (f != 0B)
> // Shouldn't we know that f!=0? It is defined just above.
This happens because the test in fold-const.c is:
return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
and f is marked as weak. If I remove 'inline' or put 'static' then this code is
folded to true. However, I can't easily do the same for _M_manager. The
condition in fold-const.c probably needs to be weakened (no pun), as I strongly
doubt it is legal to replace an inline f with 0.
Note that cp/class.c contains this:
/* ??? Probably should check DECL_WEAK here. */
if (t && DECL_P (t))
*nonnull = 1;
which we may want to keep in sync.
With f static, we get the shorter but still not so good:
int m() ()
{
struct function h;
int _21;
<bb 2>:
MEM[(int (*<T58fa>) (int) *)&h] = f;
h._M_invoker = _M_invoke;
h.D.26465._M_manager = _M_manager;
if (_M_manager == 0B)
// Can't make it non-weak
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
std::__throw_bad_function_call ();
<bb 4>:
_21 = f (1);
// Did we notice the function is really f too late for inlining?
std::_Function_base::_Base_manager<int (*)(int)>::_M_manager (&MEM[(struct
_Function_base *)&h]._M_functor, &MEM[(struct _Function_base *)&h]._M_functor,
3);
// Again, not inlined
h ={v} {CLOBBER};
h ={v} {CLOBBER};
//Maybe we could remove one of the clobbers somewhere along the way?
return _21;
}
If I change fold-const.c (the condition is probably wrong, I just wanted to
move forward):
- return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
+ return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base) ||
DECL_DECLARED_INLINE_P (base);
It removes the test _M_manager == 0, but it still inlines neither f nor
_M_manager.