https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65610
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I've tried: --- gcc/ipa-polymorphic-call.c.jj 2015-03-09 08:05:06.000000000 +0100 +++ gcc/ipa-polymorphic-call.c 2015-03-30 11:24:48.280199943 +0200 @@ -513,6 +513,38 @@ contains_type_p (tree outer_type, HOST_W } +/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor. + If CHECK_CLONES is true, also check for clones of ctor/dtors. */ + +tree +ctor_dtor_block_p (tree block, bool check_clones) +{ + tree fn = BLOCK_ABSTRACT_ORIGIN (block); + if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL) + return NULL_TREE; + + if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE + || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn))) + { + if (!check_clones) + return NULL_TREE; + + /* Watch for clones where we constant propagated the first + argument (pointer to the instance). */ + fn = DECL_ABSTRACT_ORIGIN (fn); + if (!fn + || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE + || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn))) + return NULL_TREE; + } + + if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) + return NULL_TREE; + + return fn; +} + + /* We know that the instance is stored in variable or parameter (not dynamically allocated) and we want to disprove the fact that it may be in construction at invocation of CALL. @@ -552,28 +584,8 @@ decl_maybe_in_construction_p (tree base, for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK; block = BLOCK_SUPERCONTEXT (block)) - if (BLOCK_ABSTRACT_ORIGIN (block) - && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) + if (tree fn = ctor_dtor_block_p (block, !base || is_global_var (base))) { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); - - if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE - || (!DECL_CXX_CONSTRUCTOR_P (fn) - && !DECL_CXX_DESTRUCTOR_P (fn))) - { - /* Watch for clones where we constant propagated the first - argument (pointer to the instance). */ - fn = DECL_ABSTRACT_ORIGIN (fn); - if (!fn - || (base && !is_global_var (base)) - || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE - || (!DECL_CXX_CONSTRUCTOR_P (fn) - && !DECL_CXX_DESTRUCTOR_P (fn))) - continue; - } - if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) - continue; - tree type = TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (fn))); if (!outer_type || !types_odr_comparable (type, outer_type)) @@ -1163,15 +1175,7 @@ noncall_stmt_may_be_vtbl_ptr_store (gimp block = BLOCK_SUPERCONTEXT (block)) if (BLOCK_ABSTRACT_ORIGIN (block) && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) - { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); - - if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) - return false; - return (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE - && (DECL_CXX_CONSTRUCTOR_P (fn) - || DECL_CXX_DESTRUCTOR_P (fn))); - } + return ctor_dtor_block_p (block, false); return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE && (DECL_CXX_CONSTRUCTOR_P (current_function_decl) || DECL_CXX_DESTRUCTOR_P (current_function_decl))); which I hope doesn't change ipa-polymorphic-call.c behavior, but before adjusting remove_unused_scope_block_p to also do else if (!cfun->after_inlining && ctor_dtor_block_p (scope, true)) unused = false; I've noticed that the noncall_stmt_may_be_vtbl_ptr_store call unfortunately doesn't care just about the cdtor blocks, but about all blocks where BLOCK_ABSTRACT_ORIGIN is a FUNCTION_DECL. Preserving all such blocks would be too costly for -g0 I guess; wonder if we e.g. could preserve in tree-ssa-live.c (!cfun->after_inlining ?) the ctor_dtor_block_p (scope, true) and also pass a bool with the return of that function down to the recursive remove_unused_scope_block_p calls and if that flag is true, preserve the outermost scope with FUNCTION_DECL block_abstract_origin there too.