On Fri, Jun 16, 2017 at 11:03 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Mon, Jun 12, 2017 at 7:03 PM, Bin Cheng <bin.ch...@arm.com> wrote: >> Hi, >> This patch computes and caches data dependence relation in a hash table >> so that it can be queried multiple times later for partition dependence >> check. >> Bootstrap and test on x86_64 and AArch64. Is it OK? > > +/* Vector of data dependence relations. */ > +static vec<ddr_p> *ddrs_vec; > + > +/* Hash table for data dependence relation in the loop to be distributed. */ > +static hash_table<ddr_entry_hasher> *ddrs_table; > > avoid the extra indirection. > > +/* Hashtable entry for data reference relation. */ > +struct ddr_entry > +{ > + data_reference_p a; > + data_reference_p b; > + ddr_p ddr; > + hashval_t hash; > +}; > ... > +/* Hash table equality function for data reference relation. */ > + > +inline bool > +ddr_entry_hasher::equal (const ddr_entry *entry1, const ddr_entry *entry2) > +{ > + return (entry1->hash == entry2->hash > + && DR_STMT (entry1->a) == DR_STMT (entry2->a) > + && DR_STMT (entry1->b) == DR_STMT (entry2->b) > + && operand_equal_p (DR_REF (entry1->a), DR_REF (entry2->a), 0) > + && operand_equal_p (DR_REF (entry1->b), DR_REF (entry2->b), 0)); > +} > > what's the issue with using hash_table <ddr_p> with a custom hasher? > That is, simply key on the dataref pointers (hash them, compare those > for equality)? > > Your scheme looks too complicated / expensive to me ... > > You can drop ddrs_vec needed only for memory removal if you traverse > the hashtable. Thanks for reviewing. Patch simplified as suggested. Is it OK?
Thanks, bin 2017-06-17 Bin Cheng <bin.ch...@arm.com> * tree-loop-distribution.c (struct ddr_hasher): New. (ddr_hasher::hash, ::equal, get_data_dependence): New function. (ddrs_table): New. (classify_partition): Call get_data_dependence. (pg_add_dependence_edges): Ditto. (distribute_loop): Release data dependence hash table.
From 6a3d78078355df492877955b5f00784a795a94d8 Mon Sep 17 00:00:00 2001 From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com> Date: Fri, 9 Jun 2017 13:02:09 +0100 Subject: [PATCH 09/13] cache-data-dependence-20170608.txt --- gcc/tree-loop-distribution.c | 97 ++++++++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 26 deletions(-) diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 2e5a828..a2e543e 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -70,6 +70,33 @@ along with GCC; see the file COPYING3. If not see #define MAX_DATAREFS_NUM \ ((unsigned) PARAM_VALUE (PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS)) +/* Hashtable helpers. */ + +struct ddr_hasher : nofree_ptr_hash <struct data_dependence_relation> +{ + static inline hashval_t hash (const data_dependence_relation *); + static inline bool equal (const data_dependence_relation *, + const data_dependence_relation *); +}; + +/* Hash function for data dependence. */ + +inline hashval_t +ddr_hasher::hash (const data_dependence_relation *ddr) +{ + return iterative_hash_object (DDR_A (ddr), + iterative_hash_object (DDR_B (ddr), 0)); +} + +/* Hash table equality function for data dependence. */ + +inline bool +ddr_hasher::equal (const data_dependence_relation *ddr1, + const data_dependence_relation *ddr2) +{ + return (DDR_A (ddr1) == DDR_A (ddr2) && DDR_B (ddr1) == DDR_B (ddr2)); +} + /* The loop (nest) to be distributed. */ static vec<loop_p> loop_nest; @@ -79,6 +106,10 @@ static vec<data_reference_p> datarefs_vec; /* Store index of data reference in aux field. */ #define DR_INDEX(dr) ((uintptr_t) (dr)->aux) +/* Hash table for data dependence relation in the loop to be distributed. */ +static hash_table<ddr_hasher> ddrs_table (389); + + /* A Reduced Dependence Graph (RDG) vertex representing a statement. */ struct rdg_vertex { @@ -1057,6 +1088,32 @@ generate_code_for_partition (struct loop *loop, return false; } +/* Return data dependence relation for data references A and B. The two + data references must be in lexicographic order wrto reduced dependence + graph RDG. We firstly try to find ddr from global ddr hash table. If + it doesn't exist, compute the ddr and cache it. */ + +static data_dependence_relation * +get_data_dependence (struct graph *rdg, data_reference_p a, data_reference_p b) +{ + struct data_dependence_relation ent, **slot; + struct data_dependence_relation *ddr; + + gcc_assert (DR_IS_WRITE (a) || DR_IS_WRITE (b)); + gcc_assert (rdg_vertex_for_stmt (rdg, DR_STMT (a)) + <= rdg_vertex_for_stmt (rdg, DR_STMT (b))); + ent.a = a; + ent.b = b; + slot = ddrs_table.find_slot (&ent, INSERT); + if (*slot == NULL) + { + ddr = initialize_data_dependence_relation (a, b, loop_nest); + compute_affine_dependence (ddr, loop_nest[0]); + *slot = ddr; + } + + return *slot; +} /* Returns a partition with all the statements needed for computing the vertex V of the RDG, also including the loop exit conditions. */ @@ -1223,44 +1280,27 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition) return; /* Now check that if there is a dependence this dependence is of a suitable form for memmove. */ - vec<loop_p> loops = vNULL; - ddr_p ddr; - loops.safe_push (loop); - ddr = initialize_data_dependence_relation (single_load, single_store, - loops); - compute_affine_dependence (ddr, loop); + ddr_p ddr = get_data_dependence (rdg, single_load, single_store); if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) - { - free_dependence_relation (ddr); - loops.release (); - return; - } + return; + if (DDR_ARE_DEPENDENT (ddr) != chrec_known) { if (DDR_NUM_DIST_VECTS (ddr) == 0) - { - free_dependence_relation (ddr); - loops.release (); - return; - } + return; + lambda_vector dist_v; FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v) { int dist = dist_v[index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr))]; if (dist > 0 && !DDR_REVERSED_P (ddr)) - { - free_dependence_relation (ddr); - loops.release (); - return; - } + return; } partition->kind = PKIND_MEMMOVE; } else partition->kind = PKIND_MEMCPY; - free_dependence_relation (ddr); - loops.release (); partition->main_dr = single_store; partition->secondary_dr = single_load; partition->niter = nb_iter; @@ -1474,8 +1514,7 @@ pg_add_dependence_edges (struct graph *rdg, int dir, std::swap (dr1, dr2); this_dir = -this_dir; } - ddr = initialize_data_dependence_relation (dr1, dr2, loop_nest); - compute_affine_dependence (ddr, loop_nest[0]); + ddr = get_data_dependence (rdg, dr1, dr2); if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) this_dir = 2; else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) @@ -1501,7 +1540,6 @@ pg_add_dependence_edges (struct graph *rdg, int dir, } else this_dir = 0; - free_dependence_relation (ddr); if (this_dir == 2) return 2; else if (dir == 0) @@ -1764,6 +1802,13 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts, ldist_done: loop_nest.release (); free_data_refs (datarefs_vec); + for (hash_table<ddr_hasher>::iterator iter = ddrs_table.begin (); + iter != ddrs_table.end (); ++iter) + { + free_dependence_relation (*iter); + *iter = NULL; + } + ddrs_table.empty (); FOR_EACH_VEC_ELT (partitions, i, partition) partition_free (partition); -- 1.9.1