#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "hash-map.h"
-#include "hash-table.h"
#include "alloc-pool.h"
#include "tm.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 "wide-int.h"
-#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
#include "predict.h"
#include "internal-fn.h"
#include "tree-eh.h"
#include "gimple-expr.h"
-#include "is-a.h"
#include "gimple.h"
#include "stor-layout.h"
#include "gimplify.h"
#include "ssa-iterators.h"
#include "stringpool.h"
#include "tree-ssanames.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 "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "symbol-summary.h"
#include "ipa-prop.h"
/* Set when we discover that this pointer is not safe to dereference in the
caller. */
unsigned grp_not_necessarilly_dereferenced : 1;
+
+ /* Pool allocation new operator. */
+ inline void *operator new (size_t)
+ {
+ return pool.allocate ();
+ }
+
+ /* Delete operator utilizing pool allocation. */
+ inline void operator delete (void *ptr)
+ {
+ pool.remove ((access *) ptr);
+ }
+
+ /* Memory allocation pool. */
+ static pool_allocator<access> pool;
};
typedef struct access *access_p;
/* Alloc pool for allocating access structures. */
-static alloc_pool access_pool;
+pool_allocator<struct access> access::pool ("SRA accesses", 16);
/* A structure linking lhs and rhs accesses from an aggregate assignment. They
are used to propagate subaccesses from rhs to lhs as long as they don't
{
struct access *lacc, *racc;
struct assign_link *next;
+
+ /* Pool allocation new operator. */
+ inline void *operator new (size_t)
+ {
+ return pool.allocate ();
+ }
+
+ /* Delete operator utilizing pool allocation. */
+ inline void operator delete (void *ptr)
+ {
+ pool.remove ((assign_link *) ptr);
+ }
+
+ /* Memory allocation pool. */
+ static pool_allocator<assign_link> pool;
};
/* Alloc pool for allocating assign link structures. */
-static alloc_pool link_pool;
+pool_allocator<assign_link> assign_link::pool ("SRA links", 16);
/* Base (tree) -> Vector (vec<access_p> *) map. */
static hash_map<tree, auto_vec<access_p> > *base_access_vec;
/* Candidate hash table helpers. */
-struct uid_decl_hasher : typed_noop_remove <tree_node>
+struct uid_decl_hasher : nofree_ptr_hash <tree_node>
{
- typedef tree_node value_type;
- typedef tree_node compare_type;
- static inline hashval_t hash (const value_type *);
- static inline bool equal (const value_type *, const compare_type *);
+ static inline hashval_t hash (const tree_node *);
+ static inline bool equal (const tree_node *, const tree_node *);
};
/* Hash a tree in a uid_decl_map. */
inline hashval_t
-uid_decl_hasher::hash (const value_type *item)
+uid_decl_hasher::hash (const tree_node *item)
{
return item->decl_minimal.uid;
}
/* Return true if the DECL_UID in both trees are equal. */
inline bool
-uid_decl_hasher::equal (const value_type *a, const compare_type *b)
+uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
{
return (a->decl_minimal.uid == b->decl_minimal.uid);
}
should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
gcc_obstack_init (&name_obstack);
- access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
- link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
base_access_vec = new hash_map<tree, auto_vec<access_p> >;
memset (&sra_stats, 0, sizeof (sra_stats));
encountered_apply_args = false;
candidates = NULL;
BITMAP_FREE (should_scalarize_away_bitmap);
BITMAP_FREE (cannot_scalarize_away_bitmap);
- free_alloc_pool (access_pool);
- free_alloc_pool (link_pool);
+ access::pool.release ();
+ assign_link::pool.release ();
obstack_free (&name_obstack, NULL);
delete base_access_vec;
static struct access *
create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
{
- struct access *access;
+ struct access *access = new struct access ();
- access = (struct access *) pool_alloc (access_pool);
memset (access, 0, sizeof (struct access));
access->base = base;
access->offset = offset;
{
struct assign_link *link;
- link = (struct assign_link *) pool_alloc (link_pool);
+ link = new assign_link;
memset (link, 0, sizeof (struct assign_link));
link->lacc = lacc;
misalign = (misalign + offset) & (align - 1);
if (misalign != 0)
align = (misalign & -misalign);
- if (align < TYPE_ALIGN (exp_type))
+ if (align != TYPE_ALIGN (exp_type))
exp_type = build_aligned_type (exp_type, align);
mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
DECL_CONTEXT (repl) = current_function_decl;
}
else
- repl = create_tmp_var (access->type, "SR");
+ /* Drop any special alignment on the type if it's not on the main
+ variant. This avoids issues with weirdo ABIs like AAPCS. */
+ repl = create_tmp_var (build_qualified_type
+ (TYPE_MAIN_VARIANT (access->type),
+ TYPE_QUALS (access->type)), "SR");
if (TREE_CODE (access->type) == COMPLEX_TYPE
|| TREE_CODE (access->type) == VECTOR_TYPE)
{
create_artificial_child_access (struct access *parent, struct access *model,
HOST_WIDE_INT new_offset)
{
- struct access *access;
struct access **child;
tree expr = parent->base;
gcc_assert (!model->grp_unscalarizable_region);
- access = (struct access *) pool_alloc (access_pool);
+ struct access *access = new struct access ();
memset (access, 0, sizeof (struct access));
if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
model->type))
{
basic_block this_block;
- node->call_for_symbol_thunks_and_aliases (convert_callers_for_node,
- &adjustments, false);
+ node->call_for_symbol_and_aliases (convert_callers_for_node,
+ &adjustments, false);
if (!encountered_recursive_call)
return;
{
bool has_callers;
bool bad_arg_alignment;
+ bool has_thunk;
};
/* If NODE has a caller, mark that fact in DATA which is pointer to
for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller)
{
+ if (cs->caller->thunk.thunk_p)
+ {
+ iscc->has_thunk = true;
+ return true;
+ }
gimple call_stmt = cs->call_stmt;
unsigned count = gimple_call_num_args (call_stmt);
for (unsigned i = 0; i < count; i++)
return false;
}
- if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
+ if ((DECL_ONE_ONLY (node->decl) || DECL_EXTERNAL (node->decl))
&& inline_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
{
if (dump_file)
struct ipa_sra_check_caller_data iscc;
memset (&iscc, 0, sizeof(iscc));
- node->call_for_symbol_thunks_and_aliases (ipa_sra_check_caller, &iscc, true);
+ node->call_for_symbol_and_aliases (ipa_sra_check_caller, &iscc, true);
if (!iscc.has_callers)
{
if (dump_file)
return false;
}
+ if (iscc.has_thunk)
+ {
+ if (dump_file)
+ fprintf (dump_file,
+ "A has thunk.\n");
+ return false;
+ }
+
return true;
}
goto simple_out;
}
- if (node->call_for_symbol_thunks_and_aliases
+ if (node->call_for_symbol_and_aliases
(some_callers_have_mismatched_arguments_p, NULL, true))
{
if (dump_file)
goto simple_out;
}
- if (node->call_for_symbol_thunks_and_aliases
+ if (node->call_for_symbol_and_aliases
(some_callers_have_no_vuse_p, NULL, true))
{
if (dump_file)