https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100409
--- Comment #14 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Jason Merrill from comment #13) > (In reply to Richard Biener from comment #3) > > - if (! TREE_SIDE_EFFECTS (expr)) > > + if (! TREE_SIDE_EFFECTS (expr) && expr_noexcept_p (expr, 0)) > > expr = void_node; > > The assumption that an expression with TREE_SIDE_EFFECTS unset can be > discarded if its value is not used is made throughout the compiler. > Abandoning that invariant seems like a bad idea. And changing from checking > a flag to walking through the whole expression in all of those places sounds > like an algorithmic complexity problem. > > If a pure/const function can throw, fine. But that shouldn't affect how > optimization treats the function call, or we'll end up pessimizing the vast > majority of calls to pure/const functions that don't throw (but are not > explicitly declared noexcept). In this testcase, if the user doesn't want > the compiler to optimize away a call to foo(), they shouldn't mark it pure. Hmm, fair enough. Does that mean C++ should default to -fdelete-dead-exceptions? Elsewhere it's said that TREE_SIDE_EFFECTS, const/pure and EH are orthogonal concepts but yes, that we have to walk expressions recursively to figure nothrow sucks. Though the convert_to_void "optimization" could be seen as premature, on GIMPLE there's no recursive walking needed and nothrow discovery should discover nothrow-ness of most small functions that have the body available - so the other option I considered was to remove that optimization. Now, this C++ decision makes my life a bit harder (writing testcases for the middle-end issues around throwing pure/const functions).