This removes a pointless stmt -> RDG index hash (simply use gimple_uid) and arranges to compute and analyze data-references once instead of O(stmts^4) when looking for common data accesses (ugh!).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2012-06-04 Richard Guenther <rguent...@suse.de> * tree-data-ref.c (struct rdg_vertex_info): Remove. (rdg_vertex_for_stmt): Simplify using gimple_uid. (create_rdg_vertices): Pass loop argument, remove stmt to RDG index hashtable. Record stmt data-references. (hash_stmt_vertex_info): Remove. (eq_stmt_vertex_info): Likewise. (hash_stmt_vertex_del): Likewise. (build_empty_rdg): Simplify. (build_rdg): Adjust. (free_rdg): Likewise. (ref_base_address): Remove. (have_similar_memory_accesses): Likewise. * tree-data-ref.h (create_rdg_vertices): Remove. (struct rdg_vertex): Add datarefs member. (RDGV_DATAREFS): New define. (RDG_DATAREFS): Likewise. (have_similar_memory_accesses): Remove. (rdg_has_similar_memory_accesses): Likewise. * tree-loop-distribution.c (ref_base_address): Re-implement here. (similar_memory_accesses): Re-implement using existing data-references. (tree_loop_distribution): Initialize stmt uids for the stmt to RDG index mapping. * tree-vect-loop.c (vect_create_epilog_for_reduction): Only access stmt vinfo for stmts in loop. Index: trunk/gcc/tree-data-ref.c =================================================================== *** trunk.orig/gcc/tree-data-ref.c 2012-06-04 15:09:18.000000000 +0200 --- trunk/gcc/tree-data-ref.c 2012-06-04 15:09:40.605652827 +0200 *************** dot_rdg (struct graph *rdg) *** 4924,4952 **** #endif } - /* This structure is used for recording the mapping statement index in - the RDG. */ - - struct GTY(()) rdg_vertex_info - { - gimple stmt; - int index; - }; - /* Returns the index of STMT in RDG. */ int ! rdg_vertex_for_stmt (struct graph *rdg, gimple stmt) { ! struct rdg_vertex_info rvi, *slot; ! ! rvi.stmt = stmt; ! slot = (struct rdg_vertex_info *) htab_find (rdg->indices, &rvi); ! ! if (!slot) ! return -1; ! ! return slot->index; } /* Creates an edge in RDG for each distance vector from DDR. The --- 4924,4937 ---- #endif } /* Returns the index of STMT in RDG. */ int ! rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple stmt) { ! int index = gimple_uid (stmt); ! gcc_checking_assert (index == -1 || RDG_STMT (rdg, index) == stmt); ! return index; } /* Creates an edge in RDG for each distance vector from DDR. The *************** create_rdg_edges (struct graph *rdg, VEC *** 5041,5048 **** /* Build the vertices of the reduced dependence graph RDG. */ ! void ! create_rdg_vertices (struct graph *rdg, VEC (gimple, heap) *stmts) { int i, j; gimple stmt; --- 5026,5033 ---- /* Build the vertices of the reduced dependence graph RDG. */ ! static void ! create_rdg_vertices (struct graph *rdg, VEC (gimple, heap) *stmts, loop_p loop) { int i, j; gimple stmt; *************** create_rdg_vertices (struct graph *rdg, *** 5052,5084 **** VEC (data_ref_loc, heap) *references; data_ref_loc *ref; struct vertex *v = &(rdg->vertices[i]); - struct rdg_vertex_info *rvi = XNEW (struct rdg_vertex_info); - struct rdg_vertex_info **slot; ! rvi->stmt = stmt; ! rvi->index = i; ! slot = (struct rdg_vertex_info **) htab_find_slot (rdg->indices, rvi, INSERT); ! ! if (!*slot) ! *slot = rvi; ! else ! free (rvi); v->data = XNEW (struct rdg_vertex); ! RDG_STMT (rdg, i) = stmt; ! ! RDG_MEM_WRITE_STMT (rdg, i) = false; ! RDG_MEM_READS_STMT (rdg, i) = false; if (gimple_code (stmt) == GIMPLE_PHI) continue; get_references_in_stmt (stmt, &references); FOR_EACH_VEC_ELT (data_ref_loc, references, j, ref) ! if (!ref->is_read) ! RDG_MEM_WRITE_STMT (rdg, i) = true; ! else ! RDG_MEM_READS_STMT (rdg, i) = true; ! VEC_free (data_ref_loc, heap, references); } } --- 5037,5067 ---- VEC (data_ref_loc, heap) *references; data_ref_loc *ref; struct vertex *v = &(rdg->vertices[i]); ! /* Record statement to vertex mapping. */ ! gimple_set_uid (stmt, i); v->data = XNEW (struct rdg_vertex); ! RDGV_STMT (v) = stmt; ! RDGV_DATAREFS (v) = NULL; ! RDGV_HAS_MEM_WRITE (v) = false; ! RDGV_HAS_MEM_READS (v) = false; if (gimple_code (stmt) == GIMPLE_PHI) continue; get_references_in_stmt (stmt, &references); FOR_EACH_VEC_ELT (data_ref_loc, references, j, ref) ! { ! data_reference_p dr; ! if (!ref->is_read) ! RDGV_HAS_MEM_WRITE (v) = true; ! else ! RDGV_HAS_MEM_READS (v) = true; ! dr = create_data_ref (loop, loop_containing_stmt (stmt), ! *ref->pos, stmt, ref->is_read); ! if (dr) ! VEC_safe_push (data_reference_p, heap, RDGV_DATAREFS (v), dr); ! } VEC_free (data_ref_loc, heap, references); } } *************** known_dependences_p (VEC (ddr_p, heap) * *** 5130,5166 **** return true; } - /* Computes a hash function for element ELT. */ - - static hashval_t - hash_stmt_vertex_info (const void *elt) - { - const struct rdg_vertex_info *const rvi = - (const struct rdg_vertex_info *) elt; - gimple stmt = rvi->stmt; - - return htab_hash_pointer (stmt); - } - - /* Compares database elements E1 and E2. */ - - static int - eq_stmt_vertex_info (const void *e1, const void *e2) - { - const struct rdg_vertex_info *elt1 = (const struct rdg_vertex_info *) e1; - const struct rdg_vertex_info *elt2 = (const struct rdg_vertex_info *) e2; - - return elt1->stmt == elt2->stmt; - } - - /* Free the element E. */ - - static void - hash_stmt_vertex_del (void *e) - { - free (e); - } - /* Build the Reduced Dependence Graph (RDG) with one vertex per statement of the loop nest, and one edge per data dependence or scalar dependence. */ --- 5113,5118 ---- *************** hash_stmt_vertex_del (void *e) *** 5168,5178 **** struct graph * build_empty_rdg (int n_stmts) { - int nb_data_refs = 10; struct graph *rdg = new_graph (n_stmts); - - rdg->indices = htab_create (nb_data_refs, hash_stmt_vertex_info, - eq_stmt_vertex_info, hash_stmt_vertex_del); return rdg; } --- 5120,5126 ---- *************** build_rdg (struct loop *loop, *** 5195,5201 **** VEC (gimple, heap) *stmts = VEC_alloc (gimple, heap, 10); stmts_from_loop (loop, &stmts); rdg = build_empty_rdg (VEC_length (gimple, stmts)); ! create_rdg_vertices (rdg, stmts); create_rdg_edges (rdg, *dependence_relations); VEC_free (gimple, heap, stmts); } --- 5143,5149 ---- VEC (gimple, heap) *stmts = VEC_alloc (gimple, heap, 10); stmts_from_loop (loop, &stmts); rdg = build_empty_rdg (VEC_length (gimple, stmts)); ! create_rdg_vertices (rdg, stmts, loop); create_rdg_edges (rdg, *dependence_relations); VEC_free (gimple, heap, stmts); } *************** free_rdg (struct graph *rdg) *** 5218,5227 **** for (e = v->succ; e; e = e->succ_next) free (e->data); free (v->data); } - htab_delete (rdg->indices); free_graph (rdg); } --- 5166,5176 ---- for (e = v->succ; e; e = e->succ_next) free (e->data); + gimple_set_uid (RDGV_STMT (v), -1); + free_data_refs (RDGV_DATAREFS (v)); free (v->data); } free_graph (rdg); } *************** stores_zero_from_loop (struct loop *loop *** 5307,5346 **** free (bbs); } - /* For a data reference REF, return the declaration of its base - address or NULL_TREE if the base is not determined. */ - - static inline tree - ref_base_address (gimple stmt, data_ref_loc *ref) - { - tree base = NULL_TREE; - tree base_address; - struct data_reference *dr = XCNEW (struct data_reference); - - DR_STMT (dr) = stmt; - DR_REF (dr) = *ref->pos; - dr_analyze_innermost (dr, loop_containing_stmt (stmt)); - base_address = DR_BASE_ADDRESS (dr); - - if (!base_address) - goto end; - - switch (TREE_CODE (base_address)) - { - case ADDR_EXPR: - base = TREE_OPERAND (base_address, 0); - break; - - default: - base = base_address; - break; - } - - end: - free_data_ref (dr); - return base; - } - /* Determines whether the statement from vertex V of the RDG has a definition used outside the loop that contains this statement. */ --- 5256,5261 ---- *************** rdg_defs_used_in_other_loops_p (struct g *** 5368,5405 **** return false; } - - /* Determines whether statements S1 and S2 access to similar memory - locations. Two memory accesses are considered similar when they - have the same base address declaration, i.e. when their - ref_base_address is the same. */ - - bool - have_similar_memory_accesses (gimple s1, gimple s2) - { - bool res = false; - unsigned i, j; - VEC (data_ref_loc, heap) *refs1, *refs2; - data_ref_loc *ref1, *ref2; - - get_references_in_stmt (s1, &refs1); - get_references_in_stmt (s2, &refs2); - - FOR_EACH_VEC_ELT (data_ref_loc, refs1, i, ref1) - { - tree base1 = ref_base_address (s1, ref1); - - if (base1) - FOR_EACH_VEC_ELT (data_ref_loc, refs2, j, ref2) - if (base1 == ref_base_address (s2, ref2)) - { - res = true; - goto end; - } - } - - end: - VEC_free (data_ref_loc, heap, refs1); - VEC_free (data_ref_loc, heap, refs2); - return res; - } --- 5283,5285 ---- Index: trunk/gcc/tree-data-ref.h =================================================================== *** trunk.orig/gcc/tree-data-ref.h 2012-06-04 15:09:18.000000000 +0200 --- trunk/gcc/tree-data-ref.h 2012-06-04 15:09:40.606652827 +0200 *************** extern bool compute_all_dependences (VEC *** 403,409 **** extern tree find_data_references_in_bb (struct loop *, basic_block, VEC (data_reference_p, heap) **); - extern void create_rdg_vertices (struct graph *, VEC (gimple, heap) *); extern bool dr_may_alias_p (const struct data_reference *, const struct data_reference *, bool); extern bool dr_equal_offsets_p (struct data_reference *, --- 403,408 ---- *************** typedef struct rdg_vertex *** 525,530 **** --- 524,532 ---- /* The statement represented by this vertex. */ gimple stmt; + /* Vector of data-references in this statement. */ + VEC(data_reference_p, heap) *datarefs; + /* True when the statement contains a write to memory. */ bool has_mem_write; *************** typedef struct rdg_vertex *** 533,541 **** --- 535,545 ---- } *rdg_vertex_p; #define RDGV_STMT(V) ((struct rdg_vertex *) ((V)->data))->stmt + #define RDGV_DATAREFS(V) ((struct rdg_vertex *) ((V)->data))->datarefs #define RDGV_HAS_MEM_WRITE(V) ((struct rdg_vertex *) ((V)->data))->has_mem_write #define RDGV_HAS_MEM_READS(V) ((struct rdg_vertex *) ((V)->data))->has_mem_reads #define RDG_STMT(RDG, I) RDGV_STMT (&(RDG->vertices[I])) + #define RDG_DATAREFS(RDG, I) RDGV_DATAREFS (&(RDG->vertices[I])) #define RDG_MEM_WRITE_STMT(RDG, I) RDGV_HAS_MEM_WRITE (&(RDG->vertices[I])) #define RDG_MEM_READS_STMT(RDG, I) RDGV_HAS_MEM_READS (&(RDG->vertices[I])) *************** index_in_loop_nest (int var, VEC (loop_p *** 608,614 **** void stores_from_loop (struct loop *, VEC (gimple, heap) **); void stores_zero_from_loop (struct loop *, VEC (gimple, heap) **); bool rdg_defs_used_in_other_loops_p (struct graph *, int); - bool have_similar_memory_accesses (gimple, gimple); bool stmt_with_adjacent_zero_store_dr_p (gimple); /* Returns true when STRIDE is equal in absolute value to the size of --- 612,617 ---- *************** stride_of_unit_type_p (tree stride, tree *** 623,638 **** TYPE_SIZE_UNIT (type))); } - /* Determines whether RDG vertices V1 and V2 access to similar memory - locations, in which case they have to be in the same partition. */ - - static inline bool - rdg_has_similar_memory_accesses (struct graph *rdg, int v1, int v2) - { - return have_similar_memory_accesses (RDG_STMT (rdg, v1), - RDG_STMT (rdg, v2)); - } - /* In tree-data-ref.c */ void split_constant_offset (tree , tree *, tree *); --- 626,631 ---- Index: trunk/gcc/tree-loop-distribution.c =================================================================== *** trunk.orig/gcc/tree-loop-distribution.c 2012-06-04 15:09:18.000000000 +0200 --- trunk/gcc/tree-loop-distribution.c 2012-06-04 15:09:40.607652827 +0200 *************** classify_partition (loop_p loop, struct *** 878,883 **** --- 878,897 ---- partition->kind = PKIND_MEMSET; } + /* For a data reference REF, return the declaration of its base + address or NULL_TREE if the base is not determined. */ + + static tree + ref_base_address (data_reference_p dr) + { + tree base_address = DR_BASE_ADDRESS (dr); + if (base_address + && TREE_CODE (base_address) == ADDR_EXPR) + return TREE_OPERAND (base_address, 0); + + return base_address; + } + /* Returns true when PARTITION1 and PARTITION2 have similar memory accesses in RDG. */ *************** static bool *** 885,901 **** similar_memory_accesses (struct graph *rdg, partition_t partition1, partition_t partition2) { ! unsigned i, j; bitmap_iterator bi, bj; EXECUTE_IF_SET_IN_BITMAP (partition1->stmts, 0, i, bi) if (RDG_MEM_WRITE_STMT (rdg, i) || RDG_MEM_READS_STMT (rdg, i)) EXECUTE_IF_SET_IN_BITMAP (partition2->stmts, 0, j, bj) if (RDG_MEM_WRITE_STMT (rdg, j) || RDG_MEM_READS_STMT (rdg, j)) ! if (rdg_has_similar_memory_accesses (rdg, i, j)) ! return true; return false; } --- 899,934 ---- similar_memory_accesses (struct graph *rdg, partition_t partition1, partition_t partition2) { ! unsigned i, j, k, l; bitmap_iterator bi, bj; + data_reference_p ref1, ref2; + + /* First check whether in the intersection of the two partitions are + any loads or stores. Common loads are the situation that happens + most often. */ + EXECUTE_IF_AND_IN_BITMAP (partition1->stmts, partition2->stmts, 0, i, bi) + if (RDG_MEM_WRITE_STMT (rdg, i) + || RDG_MEM_READS_STMT (rdg, i)) + return true; + /* Then check all data-references against each other. */ EXECUTE_IF_SET_IN_BITMAP (partition1->stmts, 0, i, bi) if (RDG_MEM_WRITE_STMT (rdg, i) || RDG_MEM_READS_STMT (rdg, i)) EXECUTE_IF_SET_IN_BITMAP (partition2->stmts, 0, j, bj) if (RDG_MEM_WRITE_STMT (rdg, j) || RDG_MEM_READS_STMT (rdg, j)) ! { ! FOR_EACH_VEC_ELT (data_reference_p, RDG_DATAREFS (rdg, i), k, ref1) ! { ! tree base1 = ref_base_address (ref1); ! if (base1) ! FOR_EACH_VEC_ELT (data_reference_p, ! RDG_DATAREFS (rdg, j), l, ref2) ! if (base1 == ref_base_address (ref2)) ! return true; ! } ! } return false; } *************** tree_loop_distribution (void) *** 1252,1257 **** --- 1285,1300 ---- struct loop *loop; loop_iterator li; bool changed = false; + basic_block bb; + + FOR_ALL_BB (bb) + { + gimple_stmt_iterator gsi; + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + gimple_set_uid (gsi_stmt (gsi), -1); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + gimple_set_uid (gsi_stmt (gsi), -1); + } /* We can at the moment only distribute non-nested loops, thus restrict walking to innermost loops. */ Index: trunk/gcc/tree-vect-loop.c =================================================================== *** trunk.orig/gcc/tree-vect-loop.c 2012-06-04 15:09:38.000000000 +0200 --- trunk/gcc/tree-vect-loop.c 2012-06-04 15:09:50.690652479 +0200 *************** vect_finalize_reduction: *** 4211,4217 **** orig_name = PHI_RESULT (exit_phi); FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name) { ! stmt_vec_info use_stmt_vinfo = vinfo_for_stmt (use_stmt); stmt_vec_info new_phi_vinfo; tree vect_phi_init, preheader_arg, vect_phi_res, init_def; basic_block bb = gimple_bb (use_stmt); --- 4211,4217 ---- orig_name = PHI_RESULT (exit_phi); FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name) { ! stmt_vec_info use_stmt_vinfo; stmt_vec_info new_phi_vinfo; tree vect_phi_init, preheader_arg, vect_phi_res, init_def; basic_block bb = gimple_bb (use_stmt); *************** vect_finalize_reduction: *** 4221,4231 **** node. */ if (gimple_code (use_stmt) != GIMPLE_PHI || gimple_phi_num_args (use_stmt) != 2 - || !use_stmt_vinfo - || STMT_VINFO_DEF_TYPE (use_stmt_vinfo) - != vect_double_reduction_def || bb->loop_father != outer_loop) continue; /* Create vector phi node for double reduction: vs1 = phi <vs0, vs2> --- 4221,4233 ---- node. */ if (gimple_code (use_stmt) != GIMPLE_PHI || gimple_phi_num_args (use_stmt) != 2 || bb->loop_father != outer_loop) continue; + use_stmt_vinfo = vinfo_for_stmt (use_stmt); + if (!use_stmt_vinfo + || STMT_VINFO_DEF_TYPE (use_stmt_vinfo) + != vect_double_reduction_def) + continue; /* Create vector phi node for double reduction: vs1 = phi <vs0, vs2>