===================================================================
@@ -120,7 +120,7 @@
(GTFILES): Add trans-mem.c.
* omp-low.c (WALK_SUBSTMTS): Add GIMPLE_TRANSACTION.
* output.h (record_tm_clone_pair, finish_tm_clone_pairs,
- finish_tm_clone_pairs_1, get_tm_clone_pair): Declare.
+ get_tm_clone_pair): Declare.
* params.def (PARAM_TM_MAX_AGGREGATE_SIZE): New.
* passes.c (init_optimization_passes): Place transactional memory
passes.
@@ -190,5 +190,5 @@
is_tm_may_cancel_outer, is_tm_ending_fndecl, record_tm_replacement,
tm_malloc_replacement): Declare.
* varasm.c (tm_clone_pairs): New.
- (record_tm_clone_pair, finish_tm_clone_pairs, finish_tm_clone_pairs_1,
- get_tm_clone_pair): New.
+ (record_tm_clone_pair, finish_tm_clone_pairs, get_tm_clone_pair,
+ dump_tm_clone_to_vec, dump_tm_clone_pairs, alias_pair_cmp): New.
===================================================================
@@ -5901,58 +5901,104 @@ get_tm_clone_pair (tree o)
return NULL_TREE;
}
-/* Helper function for finish_tm_clone_pairs. Dump the clone table. */
+/* Helper function for finish_tm_clone_pairs. Dump a hash table entry
+ into a VEC in INFO. */
-int
-finish_tm_clone_pairs_1 (void **slot, void *info ATTRIBUTE_UNUSED)
+static int
+dump_tm_clone_to_vec (void **slot, void *info)
{
struct tree_map *map = (struct tree_map *) *slot;
- bool *switched = (bool *) info;
- tree src = map->base.from;
- tree dst = map->to;
- struct cgraph_node *src_n = cgraph_get_node (src);
- struct cgraph_node *dst_n = cgraph_get_node (dst);
-
- /* The function ipa_tm_create_version() marks the clone as needed if
- the original function was needed. But we also mark the clone as
- needed if we ever called the clone indirectly through
- TM_GETTMCLONE. If neither of these are true, we didn't generate
- a clone, and we didn't call it indirectly... no sense keeping it
- in the clone table. */
- if (!dst_n || !dst_n->needed)
- return 1;
+ VEC(alias_pair,gc) **alias_pairs = (VEC(alias_pair, gc) **) info;
+ alias_pair *p = VEC_safe_push (alias_pair, gc, *alias_pairs, NULL);
+ p->decl = map->base.from;
+ p->target = map->to;
+ p->emitted_diags = DECL_UID (p->decl);
+ return 1;
+}
- /* This covers the case where we have optimized the original
- function away, and only access the transactional clone. */
- if (!src_n || !src_n->needed)
- return 1;
+/* Dump the actual pairs to the .tm_clone_table section. */
- if (!*switched)
+static void
+dump_tm_clone_pairs (VEC(alias_pair,gc) *alias_pairs)
+{
+ unsigned i;
+ alias_pair *p;
+ bool switched = false;
+
+ FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
{
- switch_to_section (get_named_section (NULL, ".tm_clone_table", 3));
- assemble_align (POINTER_SIZE);
- *switched = true;
+ tree src = p->decl;
+ tree dst = p->target;
+ struct cgraph_node *src_n = cgraph_get_node (src);
+ struct cgraph_node *dst_n = cgraph_get_node (dst);
+
+ /* The function ipa_tm_create_version() marks the clone as needed if
+ the original function was needed. But we also mark the clone as
+ needed if we ever called the clone indirectly through
+ TM_GETTMCLONE. If neither of these are true, we didn't generate
+ a clone, and we didn't call it indirectly... no sense keeping it
+ in the clone table. */
+ if (!dst_n || !dst_n->needed)
+ continue;
+
+ /* This covers the case where we have optimized the original
+ function away, and only access the transactional clone. */
+ if (!src_n || !src_n->needed)
+ continue;
+
+ if (!switched)
+ {
+ switch_to_section (get_named_section (NULL, ".tm_clone_table", 3));
+ assemble_align (POINTER_SIZE);
+ switched = true;
+ }
+
+ assemble_integer (XEXP (DECL_RTL (src), 0),
+ POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ assemble_integer (XEXP (DECL_RTL (dst), 0),
+ POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
}
+}
- assemble_integer (XEXP (DECL_RTL (src), 0),
- POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
- assemble_integer (XEXP (DECL_RTL (dst), 0),
- POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
- return 1;
+/* Helper comparison function for qsorting by the DECL_UID stored in
+ alias_pair->emitted_diags. */
+
+static int
+alias_pair_cmp (const void *x, const void *y)
+{
+ const alias_pair *p1 = (const alias_pair *) x;
+ const alias_pair *p2 = (const alias_pair *) y;
+ if (p1->emitted_diags < p2->emitted_diags)
+ return -1;
+ if (p1->emitted_diags > p2->emitted_diags)
+ return 1;
+ return 0;
}
void
finish_tm_clone_pairs (void)
{
- bool switched = false;
+ VEC(alias_pair,gc) *alias_pairs = NULL;
if (tm_clone_pairs == NULL)
return;
- htab_traverse_noresize (tm_clone_pairs, finish_tm_clone_pairs_1,
- (void *) &switched);
+ /* We need a determenistic order for the .tm_clone_table, otherwise
+ we will get bootstrap comparison failures, so dump the hash table
+ to a vector, sort it, and dump the vector. */
+
+ /* Dump the hashtable to a vector. */
+ htab_traverse_noresize (tm_clone_pairs, dump_tm_clone_to_vec,
+ (void *) &alias_pairs);
+ /* Sort it. */
+ VEC_qsort (alias_pair, alias_pairs, alias_pair_cmp);
+
+ /* Dump it. */
+ dump_tm_clone_pairs (alias_pairs);
+
htab_delete (tm_clone_pairs);
tm_clone_pairs = NULL;
+ VEC_free (alias_pair, gc, alias_pairs);
}
===================================================================
@@ -608,7 +608,6 @@ extern void output_section_asm_op (const
extern void record_tm_clone_pair (tree, tree);
extern void finish_tm_clone_pairs (void);
-extern int finish_tm_clone_pairs_1 (void **, void *);
extern tree get_tm_clone_pair (tree);
extern void default_asm_output_source_filename (FILE *, const char *);