#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
#include "alias.h"
#include "symtab.h"
#include "options.h"
-#include "wide-int.h"
-#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
#include "predict.h"
#include "gimple-fold.h"
#include "tree-eh.h"
#include "gimple-expr.h"
-#include "is-a.h"
#include "gimple.h"
-#include "hashtab.h"
#include "rtl.h"
#include "flags.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
#include "insn-config.h"
#include "expmed.h"
#include "dojump.h"
#include "gimple-walk.h"
#include "langhooks.h"
#include "target.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "alloc-pool.h"
#include "symbol-summary.h"
/* Allocation pool for reference descriptions. */
-static alloc_pool ipa_refdesc_pool;
+static pool_allocator<ipa_cst_ref_desc> ipa_refdesc_pool
+ ("IPA-PROP ref descriptions", 32);
/* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl associated
with NODE should prevent us from analyzing it for the purposes of IPA-CP. */
else if (type == IPA_JF_ANCESTOR)
{
fprintf (f, "ANCESTOR: ");
- fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC,
+ fprintf (f, "%d, offset " HOST_WIDE_INT_PRINT_DEC,
jump_func->value.ancestor.formal_id,
jump_func->value.ancestor.offset);
if (jump_func->value.ancestor.agg_preserved)
&& TREE_CODE (TREE_OPERAND (constant, 0)) == FUNCTION_DECL)
{
struct ipa_cst_ref_desc *rdesc;
- if (!ipa_refdesc_pool)
- ipa_refdesc_pool = create_alloc_pool ("IPA-PROP ref descriptions",
- sizeof (struct ipa_cst_ref_desc), 32);
- rdesc = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool);
+ rdesc = ipa_refdesc_pool.allocate ();
rdesc->cs = cs;
rdesc->next_duplicate = NULL;
rdesc->refcount = 1;
/* Walk the inline stack and watch out for ctors/dtors. */
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)
- {
- tree fn = BLOCK_ABSTRACT_ORIGIN (block);
-
- if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
- continue;
- if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
- && (DECL_CXX_CONSTRUCTOR_P (fn)
- || DECL_CXX_DESTRUCTOR_P (fn)))
- return true;
- }
+ if (inlined_polymorphic_ctor_dtor_block_p (block, false))
+ return true;
return false;
}
}
target = canonicalize_constructor_val (target, NULL);
if (!target || TREE_CODE (target) != FUNCTION_DECL)
{
- if (ie->indirect_info->member_ptr)
- /* Member pointer call that goes through a VMT lookup. */
- return NULL;
+ /* Member pointer call that goes through a VMT lookup. */
+ if (ie->indirect_info->member_ptr
+ /* Or if target is not an invariant expression and we do not
+ know if it will evaulate to function at runtime.
+ This can happen when folding through &VAR, where &VAR
+ is IP invariant, but VAR itself is not.
+
+ TODO: Revisit this when GCC 5 is branched. It seems that
+ member_ptr check is not needed and that we may try to fold
+ the expression and see if VAR is readonly. */
+ || !is_gimple_ip_invariant (target))
+ {
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location_safe (ie->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "discovered direct call non-invariant "
+ "%s/%i\n",
+ ie->caller->name (), ie->caller->order);
+ }
+ return NULL;
+ }
+
if (dump_enabled_p ())
{
new_direct_edge->indirect_inlining_edge = 1;
top = IPA_EDGE_REF (cs);
res = true;
- continue;
+ if (!new_direct_edge->speculative)
+ continue;
}
else if (new_direct_edge)
{
if (jfunc->type == IPA_JF_PASS_THROUGH
&& ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
{
- if ((ici->agg_contents
- && !ipa_get_jf_pass_through_agg_preserved (jfunc))
- || (ici->polymorphic
- && !ipa_get_jf_pass_through_type_preserved (jfunc)))
+ if (ici->agg_contents
+ && !ipa_get_jf_pass_through_agg_preserved (jfunc)
+ && !ici->polymorphic)
ici->param_index = -1;
else
- ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
+ {
+ ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
+ if (ici->polymorphic
+ && !ipa_get_jf_pass_through_type_preserved (jfunc))
+ ici->vptr_changed = true;
+ }
}
else if (jfunc->type == IPA_JF_ANCESTOR)
{
- if ((ici->agg_contents
- && !ipa_get_jf_ancestor_agg_preserved (jfunc))
- || (ici->polymorphic
- && !ipa_get_jf_ancestor_type_preserved (jfunc)))
+ if (ici->agg_contents
+ && !ipa_get_jf_ancestor_agg_preserved (jfunc)
+ && !ici->polymorphic)
ici->param_index = -1;
else
{
ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc);
ici->offset += ipa_get_jf_ancestor_offset (jfunc);
+ if (ici->polymorphic
+ && !ipa_get_jf_ancestor_type_preserved (jfunc))
+ ici->vptr_changed = true;
}
}
else
gcc_checking_assert (ref);
dst->caller->clone_reference (ref, ref->stmt);
- gcc_checking_assert (ipa_refdesc_pool);
- struct ipa_cst_ref_desc *dst_rdesc
- = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool);
+ struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
dst_rdesc->cs = dst;
dst_rdesc->refcount = src_rdesc->refcount;
dst_rdesc->next_duplicate = NULL;
}
else if (src_rdesc->cs == src)
{
- struct ipa_cst_ref_desc *dst_rdesc;
- gcc_checking_assert (ipa_refdesc_pool);
- dst_rdesc
- = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool);
+ struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
dst_rdesc->cs = dst;
dst_rdesc->refcount = src_rdesc->refcount;
dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
{
ipa_free_all_edge_args ();
ipa_free_all_node_params ();
- free_alloc_pool (ipcp_sources_pool);
- free_alloc_pool (ipcp_cst_values_pool);
- free_alloc_pool (ipcp_poly_ctx_values_pool);
- free_alloc_pool (ipcp_agg_lattice_pool);
+ ipcp_sources_pool.release ();
+ ipcp_cst_values_pool.release ();
+ ipcp_poly_ctx_values_pool.release ();
+ ipcp_agg_lattice_pool.release ();
ipa_unregister_cgraph_hooks ();
- if (ipa_refdesc_pool)
- free_alloc_pool (ipa_refdesc_pool);
+ ipa_refdesc_pool.release ();
}
}
ipa_free_all_edge_args ();
ipa_free_all_node_params ();
ipa_unregister_cgraph_hooks ();
- if (ipcp_sources_pool)
- free_alloc_pool (ipcp_sources_pool);
- if (ipcp_cst_values_pool)
- free_alloc_pool (ipcp_cst_values_pool);
- if (ipcp_poly_ctx_values_pool)
- free_alloc_pool (ipcp_poly_ctx_values_pool);
- if (ipcp_agg_lattice_pool)
- free_alloc_pool (ipcp_agg_lattice_pool);
- if (ipa_refdesc_pool)
- free_alloc_pool (ipa_refdesc_pool);
+ ipcp_sources_pool.release ();
+ ipcp_cst_values_pool.release ();
+ ipcp_poly_ctx_values_pool.release ();
+ ipcp_agg_lattice_pool.release ();
+ ipa_refdesc_pool.release ();
}
/* Print ipa_tree_map data structures of all functions in the
unsigned int count;
lto_input_block ib_main ((const char *) data + main_offset,
- header->main_size);
+ header->main_size, file_data->mode_table);
data_in =
lto_data_in_create (file_data, (const char *) data + string_offset,
unsigned int count;
lto_input_block ib_main ((const char *) data + main_offset,
- header->main_size);
+ header->main_size, file_data->mode_table);
data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
header->string_size, vNULL);