diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-10-30 09:35:42 +0000 |
---|---|---|
committer | <> | 2015-01-09 11:51:27 +0000 |
commit | c27a97d04853380f1e80525391b3f0d156ed4c84 (patch) | |
tree | 68ffaade7c605bc80cffa18360799c98a810976f /gcc/tree-data-ref.c | |
parent | 6af3fdec2262dd94954acc5e426ef71cbd4521d3 (diff) | |
download | gcc-tarball-c27a97d04853380f1e80525391b3f0d156ed4c84.tar.gz |
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-4.9.2.tar.bz2.gcc-4.9.2
Diffstat (limited to 'gcc/tree-data-ref.c')
-rw-r--r-- | gcc/tree-data-ref.c | 1481 |
1 files changed, 413 insertions, 1068 deletions
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index ed4d88679b..a15494a89b 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -1,6 +1,5 @@ /* Data references and dependences detectors. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 2003-2014 Free Software Foundation, Inc. Contributed by Sebastian Pop <pop@cri.ensmp.fr> This file is part of GCC. @@ -77,12 +76,23 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "expr.h" #include "gimple-pretty-print.h" -#include "tree-flow.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-ssa.h" #include "cfgloop.h" #include "tree-data-ref.h" #include "tree-scalar-evolution.h" -#include "tree-pass.h" +#include "dumpfile.h" #include "langhooks.h" #include "tree-affine.h" #include "params.h" @@ -140,43 +150,40 @@ int_divides_p (int a, int b) /* Dump into FILE all the data references from DATAREFS. */ -void -dump_data_references (FILE *file, VEC (data_reference_p, heap) *datarefs) +static void +dump_data_references (FILE *file, vec<data_reference_p> datarefs) { unsigned int i; struct data_reference *dr; - FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, dr) + FOR_EACH_VEC_ELT (datarefs, i, dr) dump_data_reference (file, dr); } -/* Dump into STDERR all the data references from DATAREFS. */ +/* Unified dump into FILE all the data references from DATAREFS. */ DEBUG_FUNCTION void -debug_data_references (VEC (data_reference_p, heap) *datarefs) +debug (vec<data_reference_p> &ref) { - dump_data_references (stderr, datarefs); + dump_data_references (stderr, ref); } -/* Dump to STDERR all the dependence relations from DDRS. */ - DEBUG_FUNCTION void -debug_data_dependence_relations (VEC (ddr_p, heap) *ddrs) +debug (vec<data_reference_p> *ptr) { - dump_data_dependence_relations (stderr, ddrs); + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); } -/* Dump into FILE all the dependence relations from DDRS. */ -void -dump_data_dependence_relations (FILE *file, - VEC (ddr_p, heap) *ddrs) -{ - unsigned int i; - struct data_dependence_relation *ddr; +/* Dump into STDERR all the data references from DATAREFS. */ - FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr) - dump_data_dependence_relation (file, ddr); +DEBUG_FUNCTION void +debug_data_references (vec<data_reference_p> datarefs) +{ + dump_data_references (stderr, datarefs); } /* Print to STDERR the data_reference DR. */ @@ -212,6 +219,24 @@ dump_data_reference (FILE *outf, fprintf (outf, "#)\n"); } +/* Unified dump function for a DATA_REFERENCE structure. */ + +DEBUG_FUNCTION void +debug (data_reference &ref) +{ + dump_data_reference (stderr, &ref); +} + +DEBUG_FUNCTION void +debug (data_reference *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} + + /* Dumps the affine function described by FN to the file OUTF. */ static void @@ -220,8 +245,8 @@ dump_affine_function (FILE *outf, affine_fn fn) unsigned i; tree coef; - print_generic_expr (outf, VEC_index (tree, fn, 0), TDF_SLIM); - for (i = 1; VEC_iterate (tree, fn, i, coef); i++) + print_generic_expr (outf, fn[0], TDF_SLIM); + for (i = 1; fn.iterate (i, &coef); i++) { fprintf (outf, " + "); print_generic_expr (outf, coef, TDF_SLIM); @@ -237,23 +262,25 @@ dump_conflict_function (FILE *outf, conflict_function *cf) unsigned i; if (cf->n == NO_DEPENDENCE) - fprintf (outf, "no dependence\n"); + fprintf (outf, "no dependence"); else if (cf->n == NOT_KNOWN) - fprintf (outf, "not known\n"); + fprintf (outf, "not known"); else { for (i = 0; i < cf->n; i++) { + if (i != 0) + fprintf (outf, " "); fprintf (outf, "["); dump_affine_function (outf, cf->fns[i]); - fprintf (outf, "]\n"); + fprintf (outf, "]"); } } } /* Dump function for a SUBSCRIPT structure. */ -void +static void dump_subscript (FILE *outf, struct subscript *subscript) { conflict_function *cf = SUB_CONFLICTS_IN_A (subscript); @@ -264,29 +291,28 @@ dump_subscript (FILE *outf, struct subscript *subscript) if (CF_NONTRIVIAL_P (cf)) { tree last_iteration = SUB_LAST_CONFLICT (subscript); - fprintf (outf, " last_conflict: "); - print_generic_stmt (outf, last_iteration, 0); + fprintf (outf, "\n last_conflict: "); + print_generic_expr (outf, last_iteration, 0); } cf = SUB_CONFLICTS_IN_B (subscript); - fprintf (outf, " iterations_that_access_an_element_twice_in_B: "); + fprintf (outf, "\n iterations_that_access_an_element_twice_in_B: "); dump_conflict_function (outf, cf); if (CF_NONTRIVIAL_P (cf)) { tree last_iteration = SUB_LAST_CONFLICT (subscript); - fprintf (outf, " last_conflict: "); - print_generic_stmt (outf, last_iteration, 0); + fprintf (outf, "\n last_conflict: "); + print_generic_expr (outf, last_iteration, 0); } - fprintf (outf, " (Subscript distance: "); - print_generic_stmt (outf, SUB_DISTANCE (subscript), 0); - fprintf (outf, " )\n"); - fprintf (outf, " )\n"); + fprintf (outf, "\n (Subscript distance: "); + print_generic_expr (outf, SUB_DISTANCE (subscript), 0); + fprintf (outf, " ))\n"); } /* Print the classic direction vector DIRV to OUTF. */ -void +static void print_direction_vector (FILE *outf, lambda_vector dirv, int length) @@ -331,14 +357,14 @@ print_direction_vector (FILE *outf, /* Print a vector of direction vectors. */ -void -print_dir_vectors (FILE *outf, VEC (lambda_vector, heap) *dir_vects, +static void +print_dir_vectors (FILE *outf, vec<lambda_vector> dir_vects, int length) { unsigned j; lambda_vector v; - FOR_EACH_VEC_ELT (lambda_vector, dir_vects, j, v) + FOR_EACH_VEC_ELT (dir_vects, j, v) print_direction_vector (outf, v, length); } @@ -356,28 +382,20 @@ print_lambda_vector (FILE * outfile, lambda_vector vector, int n) /* Print a vector of distance vectors. */ -void -print_dist_vectors (FILE *outf, VEC (lambda_vector, heap) *dist_vects, - int length) +static void +print_dist_vectors (FILE *outf, vec<lambda_vector> dist_vects, + int length) { unsigned j; lambda_vector v; - FOR_EACH_VEC_ELT (lambda_vector, dist_vects, j, v) + FOR_EACH_VEC_ELT (dist_vects, j, v) print_lambda_vector (outf, v, length); } -/* Debug version. */ - -DEBUG_FUNCTION void -debug_data_dependence_relation (struct data_dependence_relation *ddr) -{ - dump_data_dependence_relation (stderr, ddr); -} - /* Dump function for a DATA_DEPENDENCE_RELATION structure. */ -void +static void dump_data_dependence_relation (FILE *outf, struct data_dependence_relation *ddr) { @@ -428,7 +446,7 @@ dump_data_dependence_relation (FILE *outf, fprintf (outf, " inner loop index: %d\n", DDR_INNER_LOOP (ddr)); fprintf (outf, " loop nest: ("); - FOR_EACH_VEC_ELT (loop_p, DDR_LOOP_NEST (ddr), i, loopi) + FOR_EACH_VEC_ELT (DDR_LOOP_NEST (ddr), i, loopi) fprintf (outf, "%d ", loopi->num); fprintf (outf, ")\n"); @@ -450,45 +468,49 @@ dump_data_dependence_relation (FILE *outf, fprintf (outf, ")\n"); } -/* Dump function for a DATA_DEPENDENCE_DIRECTION structure. */ +/* Debug version. */ -void -dump_data_dependence_direction (FILE *file, - enum data_dependence_direction dir) +DEBUG_FUNCTION void +debug_data_dependence_relation (struct data_dependence_relation *ddr) { - switch (dir) - { - case dir_positive: - fprintf (file, "+"); - break; + dump_data_dependence_relation (stderr, ddr); +} - case dir_negative: - fprintf (file, "-"); - break; +/* Dump into FILE all the dependence relations from DDRS. */ - case dir_equal: - fprintf (file, "="); - break; +void +dump_data_dependence_relations (FILE *file, + vec<ddr_p> ddrs) +{ + unsigned int i; + struct data_dependence_relation *ddr; - case dir_positive_or_negative: - fprintf (file, "+-"); - break; + FOR_EACH_VEC_ELT (ddrs, i, ddr) + dump_data_dependence_relation (file, ddr); +} - case dir_positive_or_equal: - fprintf (file, "+="); - break; +DEBUG_FUNCTION void +debug (vec<ddr_p> &ref) +{ + dump_data_dependence_relations (stderr, ref); +} - case dir_negative_or_equal: - fprintf (file, "-="); - break; +DEBUG_FUNCTION void +debug (vec<ddr_p> *ptr) +{ + if (ptr) + debug (*ptr); + else + fprintf (stderr, "<nil>\n"); +} - case dir_star: - fprintf (file, "*"); - break; - default: - break; - } +/* Dump to STDERR all the dependence relations from DDRS. */ + +DEBUG_FUNCTION void +debug_data_dependence_relations (vec<ddr_p> ddrs) +{ + dump_data_dependence_relations (stderr, ddrs); } /* Dumps the distance and direction vectors in FILE. DDRS contains @@ -496,24 +518,24 @@ dump_data_dependence_direction (FILE *file, dependence vectors, or in other words the number of loops in the considered nest. */ -void -dump_dist_dir_vectors (FILE *file, VEC (ddr_p, heap) *ddrs) +static void +dump_dist_dir_vectors (FILE *file, vec<ddr_p> ddrs) { unsigned int i, j; struct data_dependence_relation *ddr; lambda_vector v; - FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr) + FOR_EACH_VEC_ELT (ddrs, i, ddr) if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE && DDR_AFFINE_P (ddr)) { - FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), j, v) + FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), j, v) { fprintf (file, "DISTANCE_V ("); print_lambda_vector (file, v, DDR_NB_LOOPS (ddr)); fprintf (file, ")\n"); } - FOR_EACH_VEC_ELT (lambda_vector, DDR_DIR_VECTS (ddr), j, v) + FOR_EACH_VEC_ELT (DDR_DIR_VECTS (ddr), j, v) { fprintf (file, "DIRECTION_V ("); print_direction_vector (file, v, DDR_NB_LOOPS (ddr)); @@ -526,18 +548,24 @@ dump_dist_dir_vectors (FILE *file, VEC (ddr_p, heap) *ddrs) /* Dumps the data dependence relations DDRS in FILE. */ -void -dump_ddrs (FILE *file, VEC (ddr_p, heap) *ddrs) +static void +dump_ddrs (FILE *file, vec<ddr_p> ddrs) { unsigned int i; struct data_dependence_relation *ddr; - FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr) + FOR_EACH_VEC_ELT (ddrs, i, ddr) dump_data_dependence_relation (file, ddr); fprintf (file, "\n\n"); } +DEBUG_FUNCTION void +debug_ddrs (vec<ddr_p> ddrs) +{ + dump_ddrs (stderr, ddrs); +} + /* Helper function for split_constant_offset. Expresses OP0 CODE OP1 (the type of the result is TYPE) as VAR + OFF, where OFF is a nonzero constant of type ssizetype, and returns true. If we cannot do this @@ -755,13 +783,12 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest) { if (!integer_zerop (TREE_OPERAND (base, 1))) { + double_int moff = mem_ref_offset (base); + tree mofft = double_int_to_tree (sizetype, moff); if (!poffset) - { - double_int moff = mem_ref_offset (base); - poffset = double_int_to_tree (sizetype, moff); - } + poffset = mofft; else - poffset = size_binop (PLUS_EXPR, poffset, TREE_OPERAND (base, 1)); + poffset = size_binop (PLUS_EXPR, poffset, mofft); } base = TREE_OPERAND (base, 0); } @@ -771,7 +798,7 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest) if (in_loop) { if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv, - false)) + nest ? true : false)) { if (nest) { @@ -808,7 +835,8 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest) offset_iv.step = ssize_int (0); } else if (!simple_iv (loop, loop_containing_stmt (stmt), - poffset, &offset_iv, false)) + poffset, &offset_iv, + nest ? true : false)) { if (nest) { @@ -855,7 +883,7 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest) static void dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) { - VEC (tree, heap) *access_fns = NULL; + vec<tree> access_fns = vNULL; tree ref, op; tree base, off, access_fn; basic_block before_loop; @@ -865,7 +893,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) if (!nest) { DR_BASE_OBJECT (dr) = DR_REF (dr); - DR_ACCESS_FNS (dr) = NULL; + DR_ACCESS_FNS (dr).create (0); return; } @@ -878,12 +906,12 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) if (TREE_CODE (ref) == REALPART_EXPR) { ref = TREE_OPERAND (ref, 0); - VEC_safe_push (tree, heap, access_fns, integer_zero_node); + access_fns.safe_push (integer_zero_node); } else if (TREE_CODE (ref) == IMAGPART_EXPR) { ref = TREE_OPERAND (ref, 0); - VEC_safe_push (tree, heap, access_fns, integer_one_node); + access_fns.safe_push (integer_one_node); } /* Analyze access functions of dimensions we know to be independent. */ @@ -894,7 +922,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) op = TREE_OPERAND (ref, 1); access_fn = analyze_scalar_evolution (loop, op); access_fn = instantiate_scev (before_loop, loop, access_fn); - VEC_safe_push (tree, heap, access_fns, access_fn); + access_fns.safe_push (access_fn); } else if (TREE_CODE (ref) == COMPONENT_REF && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE) @@ -908,7 +936,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) fold_convert (bitsizetype, off), bitsize_int (BITS_PER_UNIT)), DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1))); - VEC_safe_push (tree, heap, access_fns, off); + access_fns.safe_push (off); } else /* If we have an unhandled component we could not translate @@ -954,8 +982,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) ref = fold_build2_loc (EXPR_LOCATION (ref), MEM_REF, TREE_TYPE (ref), base, memoff); - DR_UNCONSTRAINED_BASE (dr) = true; - VEC_safe_push (tree, heap, access_fns, access_fn); + access_fns.safe_push (access_fn); } } else if (DECL_P (ref)) @@ -992,7 +1019,7 @@ dr_analyze_alias (struct data_reference *dr) void free_data_ref (data_reference_p dr) { - VEC_free (tree, heap, DR_ACCESS_FNS (dr)); + DR_ACCESS_FNS (dr).release (); free (dr); } @@ -1097,14 +1124,13 @@ dr_equal_offsets_p (struct data_reference *dra, static bool affine_function_equal_p (affine_fn fna, affine_fn fnb) { - unsigned i, n = VEC_length (tree, fna); + unsigned i, n = fna.length (); - if (n != VEC_length (tree, fnb)) + if (n != fnb.length ()) return false; for (i = 0; i < n; i++) - if (!operand_equal_p (VEC_index (tree, fna, i), - VEC_index (tree, fnb, i), 0)) + if (!operand_equal_p (fna[i], fnb[i], 0)) return false; return true; @@ -1120,13 +1146,13 @@ common_affine_function (conflict_function *cf) affine_fn comm; if (!CF_NONTRIVIAL_P (cf)) - return NULL; + return affine_fn (); comm = cf->fns[0]; for (i = 1; i < cf->n; i++) if (!affine_function_equal_p (comm, cf->fns[i])) - return NULL; + return affine_fn (); return comm; } @@ -1136,7 +1162,7 @@ common_affine_function (conflict_function *cf) static tree affine_function_base (affine_fn fn) { - return VEC_index (tree, fn, 0); + return fn[0]; } /* Returns true if FN is a constant. */ @@ -1147,7 +1173,7 @@ affine_function_constant_p (affine_fn fn) unsigned i; tree coef; - for (i = 1; VEC_iterate (tree, fn, i, coef); i++) + for (i = 1; fn.iterate (i, &coef); i++) if (!integer_zerop (coef)) return false; @@ -1185,36 +1211,30 @@ affine_fn_op (enum tree_code op, affine_fn fna, affine_fn fnb) affine_fn ret; tree coef; - if (VEC_length (tree, fnb) > VEC_length (tree, fna)) + if (fnb.length () > fna.length ()) { - n = VEC_length (tree, fna); - m = VEC_length (tree, fnb); + n = fna.length (); + m = fnb.length (); } else { - n = VEC_length (tree, fnb); - m = VEC_length (tree, fna); + n = fnb.length (); + m = fna.length (); } - ret = VEC_alloc (tree, heap, m); + ret.create (m); for (i = 0; i < n; i++) { - tree type = signed_type_for_types (TREE_TYPE (VEC_index (tree, fna, i)), - TREE_TYPE (VEC_index (tree, fnb, i))); - - VEC_quick_push (tree, ret, - fold_build2 (op, type, - VEC_index (tree, fna, i), - VEC_index (tree, fnb, i))); + tree type = signed_type_for_types (TREE_TYPE (fna[i]), + TREE_TYPE (fnb[i])); + ret.quick_push (fold_build2 (op, type, fna[i], fnb[i])); } - for (; VEC_iterate (tree, fna, i, coef); i++) - VEC_quick_push (tree, ret, - fold_build2 (op, signed_type_for (TREE_TYPE (coef)), + for (; fna.iterate (i, &coef); i++) + ret.quick_push (fold_build2 (op, signed_type_for (TREE_TYPE (coef)), coef, integer_zero_node)); - for (; VEC_iterate (tree, fnb, i, coef); i++) - VEC_quick_push (tree, ret, - fold_build2 (op, signed_type_for (TREE_TYPE (coef)), + for (; fnb.iterate (i, &coef); i++) + ret.quick_push (fold_build2 (op, signed_type_for (TREE_TYPE (coef)), integer_zero_node, coef)); return ret; @@ -1241,7 +1261,7 @@ affine_fn_minus (affine_fn fna, affine_fn fnb) static void affine_fn_free (affine_fn fn) { - VEC_free (tree, heap, fn); + fn.release (); } /* Determine for each subscript in the data dependence relation DDR @@ -1267,7 +1287,7 @@ compute_subscript_distance (struct data_dependence_relation *ddr) fn_a = common_affine_function (cf_a); fn_b = common_affine_function (cf_b); - if (!fn_a || !fn_b) + if (!fn_a.exists () || !fn_b.exists ()) { SUB_DISTANCE (subscript) = chrec_dont_know; return; @@ -1368,14 +1388,20 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b, return false; } - /* If we had an evolution in a MEM_REF BASE_OBJECT we do not know - the size of the base-object. So we cannot do any offset/overlap - based analysis but have to rely on points-to information only. */ + /* If we had an evolution in a pointer-based MEM_REF BASE_OBJECT we + do not know the size of the base-object. So we cannot do any + offset/overlap based analysis but have to rely on points-to + information only. */ if (TREE_CODE (addr_a) == MEM_REF - && DR_UNCONSTRAINED_BASE (a)) + && TREE_CODE (TREE_OPERAND (addr_a, 0)) == SSA_NAME) { - if (TREE_CODE (addr_b) == MEM_REF - && DR_UNCONSTRAINED_BASE (b)) + /* For true dependences we can apply TBAA. */ + if (flag_strict_aliasing + && DR_IS_WRITE (a) && DR_IS_READ (b) + && !alias_sets_conflict_p (get_alias_set (DR_REF (a)), + get_alias_set (DR_REF (b)))) + return false; + if (TREE_CODE (addr_b) == MEM_REF) return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0), TREE_OPERAND (addr_b, 0)); else @@ -1383,9 +1409,21 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b, build_fold_addr_expr (addr_b)); } else if (TREE_CODE (addr_b) == MEM_REF - && DR_UNCONSTRAINED_BASE (b)) - return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a), - TREE_OPERAND (addr_b, 0)); + && TREE_CODE (TREE_OPERAND (addr_b, 0)) == SSA_NAME) + { + /* For true dependences we can apply TBAA. */ + if (flag_strict_aliasing + && DR_IS_WRITE (a) && DR_IS_READ (b) + && !alias_sets_conflict_p (get_alias_set (DR_REF (a)), + get_alias_set (DR_REF (b)))) + return false; + if (TREE_CODE (addr_a) == MEM_REF) + return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0), + TREE_OPERAND (addr_b, 0)); + else + return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a), + TREE_OPERAND (addr_b, 0)); + } /* Otherwise DR_BASE_OBJECT is an access that covers the whole object that is being subsetted in the loop nest. */ @@ -1403,7 +1441,7 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b, struct data_dependence_relation * initialize_data_dependence_relation (struct data_reference *a, struct data_reference *b, - VEC (loop_p, heap) *loop_nest) + vec<loop_p> loop_nest) { struct data_dependence_relation *res; unsigned int i; @@ -1411,11 +1449,11 @@ initialize_data_dependence_relation (struct data_reference *a, res = XNEW (struct data_dependence_relation); DDR_A (res) = a; DDR_B (res) = b; - DDR_LOOP_NEST (res) = NULL; + DDR_LOOP_NEST (res).create (0); DDR_REVERSED_P (res) = false; - DDR_SUBSCRIPTS (res) = NULL; - DDR_DIR_VECTS (res) = NULL; - DDR_DIST_VECTS (res) = NULL; + DDR_SUBSCRIPTS (res).create (0); + DDR_DIR_VECTS (res).create (0); + DDR_DIST_VECTS (res).create (0); if (a == NULL || b == NULL) { @@ -1424,7 +1462,7 @@ initialize_data_dependence_relation (struct data_reference *a, } /* If the data references do not alias, then they are independent. */ - if (!dr_may_alias_p (a, b, loop_nest != NULL)) + if (!dr_may_alias_p (a, b, loop_nest.exists ())) { DDR_ARE_DEPENDENT (res) = chrec_known; return res; @@ -1433,8 +1471,8 @@ initialize_data_dependence_relation (struct data_reference *a, /* The case where the references are exactly the same. */ if (operand_equal_p (DR_REF (a), DR_REF (b), 0)) { - if (loop_nest - && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0), + if (loop_nest.exists () + && !object_address_invariant_in_loop_p (loop_nest[0], DR_BASE_OBJECT (a))) { DDR_ARE_DEPENDENT (res) = chrec_dont_know; @@ -1442,7 +1480,7 @@ initialize_data_dependence_relation (struct data_reference *a, } DDR_AFFINE_P (res) = true; DDR_ARE_DEPENDENT (res) = NULL_TREE; - DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a)); + DDR_SUBSCRIPTS (res).create (DR_NUM_DIMENSIONS (a)); DDR_LOOP_NEST (res) = loop_nest; DDR_INNER_LOOP (res) = 0; DDR_SELF_REFERENCE (res) = true; @@ -1455,7 +1493,7 @@ initialize_data_dependence_relation (struct data_reference *a, SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known (); SUB_LAST_CONFLICT (subscript) = chrec_dont_know; SUB_DISTANCE (subscript) = chrec_dont_know; - VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript); + DDR_SUBSCRIPTS (res).safe_push (subscript); } return res; } @@ -1471,8 +1509,8 @@ initialize_data_dependence_relation (struct data_reference *a, /* If the base of the object is not invariant in the loop nest, we cannot analyze it. TODO -- in fact, it would suffice to record that there may be arbitrary dependences in the loops where the base object varies. */ - if (loop_nest - && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0), + if (loop_nest.exists () + && !object_address_invariant_in_loop_p (loop_nest[0], DR_BASE_OBJECT (a))) { DDR_ARE_DEPENDENT (res) = chrec_dont_know; @@ -1490,7 +1528,7 @@ initialize_data_dependence_relation (struct data_reference *a, DDR_AFFINE_P (res) = true; DDR_ARE_DEPENDENT (res) = NULL_TREE; - DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a)); + DDR_SUBSCRIPTS (res).create (DR_NUM_DIMENSIONS (a)); DDR_LOOP_NEST (res) = loop_nest; DDR_INNER_LOOP (res) = 0; DDR_SELF_REFERENCE (res) = false; @@ -1504,7 +1542,7 @@ initialize_data_dependence_relation (struct data_reference *a, SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known (); SUB_LAST_CONFLICT (subscript) = chrec_dont_know; SUB_DISTANCE (subscript) = chrec_dont_know; - VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript); + DDR_SUBSCRIPTS (res).safe_push (subscript); } return res; @@ -1528,18 +1566,18 @@ free_conflict_function (conflict_function *f) /* Frees memory used by SUBSCRIPTS. */ static void -free_subscripts (VEC (subscript_p, heap) *subscripts) +free_subscripts (vec<subscript_p> subscripts) { unsigned i; subscript_p s; - FOR_EACH_VEC_ELT (subscript_p, subscripts, i, s) + FOR_EACH_VEC_ELT (subscripts, i, s) { free_conflict_function (s->conflicting_iterations_in_a); free_conflict_function (s->conflicting_iterations_in_b); free (s); } - VEC_free (subscript_p, heap, subscripts); + subscripts.release (); } /* Set DDR_ARE_DEPENDENT to CHREC and finalize the subscript overlap @@ -1549,16 +1587,9 @@ static inline void finalize_ddr_dependent (struct data_dependence_relation *ddr, tree chrec) { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "(dependence classified: "); - print_generic_expr (dump_file, chrec, 0); - fprintf (dump_file, ")\n"); - } - DDR_ARE_DEPENDENT (ddr) = chrec; free_subscripts (DDR_SUBSCRIPTS (ddr)); - DDR_SUBSCRIPTS (ddr) = NULL; + DDR_SUBSCRIPTS (ddr).create (0); } /* The dependence relation DDR cannot be represented by a distance @@ -1634,12 +1665,12 @@ conflict_fn (unsigned n, ...) va_list ap; gcc_assert (0 < n && n <= MAX_DIM); - va_start(ap, n); + va_start (ap, n); ret->n = n; for (i = 0; i < n; i++) ret->fns[i] = va_arg (ap, affine_fn); - va_end(ap); + va_end (ap); return ret; } @@ -1649,8 +1680,9 @@ conflict_fn (unsigned n, ...) static affine_fn affine_fn_cst (tree cst) { - affine_fn fn = VEC_alloc (tree, heap, 1); - VEC_quick_push (tree, fn, cst); + affine_fn fn; + fn.create (1); + fn.quick_push (cst); return fn; } @@ -1659,14 +1691,15 @@ affine_fn_cst (tree cst) static affine_fn affine_fn_univar (tree cst, unsigned dim, tree coef) { - affine_fn fn = VEC_alloc (tree, heap, dim + 1); + affine_fn fn; + fn.create (dim + 1); unsigned i; gcc_assert (dim > 0); - VEC_quick_push (tree, fn, cst); + fn.quick_push (cst); for (i = 1; i < dim; i++) - VEC_quick_push (tree, fn, integer_zero_node); - VEC_quick_push (tree, fn, coef); + fn.quick_push (integer_zero_node); + fn.quick_push (coef); return fn; } @@ -1744,7 +1777,7 @@ max_stmt_executions_tree (struct loop *loop) { double_int nit; - if (!max_stmt_executions (loop, true, &nit)) + if (!max_stmt_executions (loop, &nit)) return chrec_dont_know; if (!double_int_fits_to_tree_p (unsigned_type_node, nit)) @@ -1905,7 +1938,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, /* Perform weak-zero siv test to see if overlap is outside the loop bounds. */ - numiter = max_stmt_executions_int (loop, true); + numiter = max_stmt_executions_int (loop); if (numiter >= 0 && compare_tree_int (tmp, numiter) > 0) @@ -1983,7 +2016,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, /* Perform weak-zero siv test to see if overlap is outside the loop bounds. */ - numiter = max_stmt_executions_int (loop, true); + numiter = max_stmt_executions_int (loop); if (numiter >= 0 && compare_tree_int (tmp, numiter) > 0) @@ -2163,10 +2196,9 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b, step_y = int_cst_value (CHREC_RIGHT (chrec_a)); step_z = int_cst_value (CHREC_RIGHT (chrec_b)); - niter_x = - max_stmt_executions_int (get_chrec_loop (CHREC_LEFT (chrec_a)), true); - niter_y = max_stmt_executions_int (get_chrec_loop (chrec_a), true); - niter_z = max_stmt_executions_int (get_chrec_loop (chrec_b), true); + niter_x = max_stmt_executions_int (get_chrec_loop (CHREC_LEFT (chrec_a))); + niter_y = max_stmt_executions_int (get_chrec_loop (chrec_a)); + niter_z = max_stmt_executions_int (get_chrec_loop (chrec_b)); if (niter_x < 0 || niter_y < 0 || niter_z < 0) { @@ -2491,8 +2523,8 @@ analyze_subscript_affine_affine (tree chrec_a, HOST_WIDE_INT niter, niter_a, niter_b; affine_fn ova, ovb; - niter_a = max_stmt_executions_int (get_chrec_loop (chrec_a), true); - niter_b = max_stmt_executions_int (get_chrec_loop (chrec_b), true); + niter_a = max_stmt_executions_int (get_chrec_loop (chrec_a)); + niter_b = max_stmt_executions_int (get_chrec_loop (chrec_b)); niter = MIN (niter_a, niter_b); step_a = int_cst_value (CHREC_RIGHT (chrec_a)); step_b = int_cst_value (CHREC_RIGHT (chrec_b)); @@ -2599,10 +2631,10 @@ analyze_subscript_affine_affine (tree chrec_a, if (i1 > 0 && j1 > 0) { - HOST_WIDE_INT niter_a = max_stmt_executions_int - (get_chrec_loop (chrec_a), true); - HOST_WIDE_INT niter_b = max_stmt_executions_int - (get_chrec_loop (chrec_b), true); + HOST_WIDE_INT niter_a + = max_stmt_executions_int (get_chrec_loop (chrec_a)); + HOST_WIDE_INT niter_b + = max_stmt_executions_int (get_chrec_loop (chrec_b)); HOST_WIDE_INT niter = MIN (niter_a, niter_b); /* (X0, Y0) is a solution of the Diophantine equation: @@ -2688,8 +2720,7 @@ end_analyze_subs_aa: dump_conflict_function (dump_file, *overlaps_a); fprintf (dump_file, ")\n (overlaps_b = "); dump_conflict_function (dump_file, *overlaps_b); - fprintf (dump_file, ")\n"); - fprintf (dump_file, ")\n"); + fprintf (dump_file, "))\n"); } } @@ -2810,7 +2841,7 @@ analyze_siv_subscript (tree chrec_a, { siv_subscript_dontknow:; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "siv test failed: unimplemented.\n"); + fprintf (dump_file, " siv test failed: unimplemented"); *overlaps_a = conflict_fn_not_known (); *overlaps_b = conflict_fn_not_known (); *last_conflicts = chrec_dont_know; @@ -2830,16 +2861,16 @@ gcd_of_steps_may_divide_p (const_tree chrec, const_tree cst) HOST_WIDE_INT cd = 0, val; tree step; - if (!host_integerp (cst, 0)) + if (!tree_fits_shwi_p (cst)) return true; - val = tree_low_cst (cst, 0); + val = tree_to_shwi (cst); while (TREE_CODE (chrec) == POLYNOMIAL_CHREC) { step = CHREC_RIGHT (chrec); - if (!host_integerp (step, 0)) + if (!tree_fits_shwi_p (step)) return true; - cd = gcd (cd, tree_low_cst (step, 0)); + cd = gcd (cd, tree_to_shwi (step)); chrec = CHREC_LEFT (chrec); } @@ -3035,8 +3066,7 @@ analyze_overlapping_iterations (tree chrec_a, dump_conflict_function (dump_file, *overlap_iterations_a); fprintf (dump_file, ")\n (overlap_iterations_b = "); dump_conflict_function (dump_file, *overlap_iterations_b); - fprintf (dump_file, ")\n"); - fprintf (dump_file, ")\n"); + fprintf (dump_file, "))\n"); } } @@ -3048,11 +3078,11 @@ save_dist_v (struct data_dependence_relation *ddr, lambda_vector dist_v) unsigned i; lambda_vector v; - FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, v) + FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, v) if (lambda_vector_equal (v, dist_v, DDR_NB_LOOPS (ddr))) return; - VEC_safe_push (lambda_vector, heap, DDR_DIST_VECTS (ddr), dist_v); + DDR_DIST_VECTS (ddr).safe_push (dist_v); } /* Helper function for uniquely inserting direction vectors. */ @@ -3063,11 +3093,11 @@ save_dir_v (struct data_dependence_relation *ddr, lambda_vector dir_v) unsigned i; lambda_vector v; - FOR_EACH_VEC_ELT (lambda_vector, DDR_DIR_VECTS (ddr), i, v) + FOR_EACH_VEC_ELT (DDR_DIR_VECTS (ddr), i, v) if (lambda_vector_equal (v, dir_v, DDR_NB_LOOPS (ddr))) return; - VEC_safe_push (lambda_vector, heap, DDR_DIR_VECTS (ddr), dir_v); + DDR_DIR_VECTS (ddr).safe_push (dir_v); } /* Add a distance of 1 on all the loops outer than INDEX. If we @@ -3516,7 +3546,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr) unsigned i, j; lambda_vector dist_v; - FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v) + FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v) { lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr)); @@ -3541,8 +3571,7 @@ subscript_dependence_tester_1 (struct data_dependence_relation *ddr, struct subscript *subscript; tree res = NULL_TREE; - for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript); - i++) + for (i = 0; DDR_SUBSCRIPTS (ddr).iterate (i, &subscript); i++) { conflict_function *overlaps_a, *overlaps_b; @@ -3596,19 +3625,12 @@ static void subscript_dependence_tester (struct data_dependence_relation *ddr, struct loop *loop_nest) { - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "(subscript_dependence_tester \n"); - if (subscript_dependence_tester_1 (ddr, DDR_A (ddr), DDR_B (ddr), loop_nest)) dependence_stats.num_dependence_dependent++; compute_subscript_distance (ddr); if (build_classic_dist_vector (ddr, loop_nest)) build_classic_dir_vector (ddr); - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, ")\n"); } /* Returns true when all the access functions of A are affine or @@ -3619,10 +3641,10 @@ access_functions_are_affine_or_constant_p (const struct data_reference *a, const struct loop *loop_nest) { unsigned int i; - VEC(tree,heap) *fns = DR_ACCESS_FNS (a); + vec<tree> fns = DR_ACCESS_FNS (a); tree t; - FOR_EACH_VEC_ELT (tree, fns, i, t) + FOR_EACH_VEC_ELT (fns, i, t) if (!evolution_function_is_invariant_p (t, loop_nest->num) && !evolution_function_is_affine_multivariate_p (t, loop_nest->num)) return false; @@ -3710,7 +3732,7 @@ omega_extract_distance_vectors (omega_pb pb, problem that we have initialized until now. On top of this we add new constraints. */ for (i = 0; i <= DDR_INNER_LOOP (ddr) - && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++) + && DDR_LOOP_NEST (ddr).iterate (i, &loopi); i++) { int dist = 0; omega_pb copy = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), @@ -3719,8 +3741,7 @@ omega_extract_distance_vectors (omega_pb pb, omega_copy_problem (copy, pb); /* For all the outer loops "loop_j", add "dj = 0". */ - for (j = 0; - j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++) + for (j = 0; j < i && DDR_LOOP_NEST (ddr).iterate (j, &loopj); j++) { eq = omega_add_zero_eq (copy, omega_black); copy->eqs[eq].coef[j + 1] = 1; @@ -3749,8 +3770,7 @@ omega_extract_distance_vectors (omega_pb pb, { /* Reinitialize problem... */ omega_copy_problem (copy, pb); - for (j = 0; - j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++) + for (j = 0; j < i && DDR_LOOP_NEST (ddr).iterate (j, &loopj); j++) { eq = omega_add_zero_eq (copy, omega_black); copy->eqs[eq].coef[j + 1] = 1; @@ -3894,9 +3914,9 @@ init_omega_for_ddr_1 (struct data_reference *dra, struct data_reference *drb, - coef[nb_loops + 1, 2*nb_loops] are the loop variables: "loop_x". */ for (i = 0; i <= DDR_INNER_LOOP (ddr) - && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++) + && DDR_LOOP_NEST (ddr).iterate (i, &loopi); i++) { - HOST_WIDE_INT nbi = max_stmt_executions_int (loopi, true); + HOST_WIDE_INT nbi = max_stmt_executions_int (loopi); /* 0 <= loop_x */ ineq = omega_add_zero_geq (pb, omega_black); @@ -4069,8 +4089,8 @@ init_omega_for_ddr (struct data_dependence_relation *ddr, static bool ddr_consistent_p (FILE *file, struct data_dependence_relation *ddr, - VEC (lambda_vector, heap) *dist_vects, - VEC (lambda_vector, heap) *dir_vects) + vec<lambda_vector> dist_vects, + vec<lambda_vector> dir_vects) { unsigned int i, j; @@ -4078,15 +4098,15 @@ ddr_consistent_p (FILE *file, if (dump_file && (dump_flags & TDF_DETAILS)) file = dump_file; - if (VEC_length (lambda_vector, dist_vects) != DDR_NUM_DIST_VECTS (ddr)) + if (dist_vects.length () != DDR_NUM_DIST_VECTS (ddr)) { lambda_vector b_dist_v; fprintf (file, "\n(Number of distance vectors differ: Banerjee has %d, Omega has %d.\n", - VEC_length (lambda_vector, dist_vects), + dist_vects.length (), DDR_NUM_DIST_VECTS (ddr)); fprintf (file, "Banerjee dist vectors:\n"); - FOR_EACH_VEC_ELT (lambda_vector, dist_vects, i, b_dist_v) + FOR_EACH_VEC_ELT (dist_vects, i, b_dist_v) print_lambda_vector (file, b_dist_v, DDR_NB_LOOPS (ddr)); fprintf (file, "Omega dist vectors:\n"); @@ -4100,10 +4120,10 @@ ddr_consistent_p (FILE *file, return false; } - if (VEC_length (lambda_vector, dir_vects) != DDR_NUM_DIR_VECTS (ddr)) + if (dir_vects.length () != DDR_NUM_DIR_VECTS (ddr)) { fprintf (file, "\n(Number of direction vectors differ: Banerjee has %d, Omega has %d.)\n", - VEC_length (lambda_vector, dir_vects), + dir_vects.length (), DDR_NUM_DIR_VECTS (ddr)); return false; } @@ -4115,11 +4135,11 @@ ddr_consistent_p (FILE *file, /* Distance vectors are not ordered in the same way in the DDR and in the DIST_VECTS: search for a matching vector. */ - FOR_EACH_VEC_ELT (lambda_vector, dist_vects, j, a_dist_v) + FOR_EACH_VEC_ELT (dist_vects, j, a_dist_v) if (lambda_vector_equal (a_dist_v, b_dist_v, DDR_NB_LOOPS (ddr))) break; - if (j == VEC_length (lambda_vector, dist_vects)) + if (j == dist_vects.length ()) { fprintf (file, "\n(Dist vectors from the first dependence analyzer:\n"); print_dist_vectors (file, dist_vects, DDR_NB_LOOPS (ddr)); @@ -4138,11 +4158,11 @@ ddr_consistent_p (FILE *file, /* Direction vectors are not ordered in the same way in the DDR and in the DIR_VECTS: search for a matching vector. */ - FOR_EACH_VEC_ELT (lambda_vector, dir_vects, j, a_dir_v) + FOR_EACH_VEC_ELT (dir_vects, j, a_dir_v) if (lambda_vector_equal (a_dir_v, b_dir_v, DDR_NB_LOOPS (ddr))) break; - if (j == VEC_length (lambda_vector, dist_vects)) + if (j == dist_vects.length ()) { fprintf (file, "\n(Dir vectors from the first dependence analyzer:\n"); print_dir_vectors (file, dir_vects, DDR_NB_LOOPS (ddr)); @@ -4166,7 +4186,7 @@ ddr_consistent_p (FILE *file, relation the first time we detect a CHREC_KNOWN element for a given subscript. */ -static void +void compute_affine_dependence (struct data_dependence_relation *ddr, struct loop *loop_nest) { @@ -4190,11 +4210,11 @@ compute_affine_dependence (struct data_dependence_relation *ddr, if (access_functions_are_affine_or_constant_p (dra, loop_nest) && access_functions_are_affine_or_constant_p (drb, loop_nest)) { + subscript_dependence_tester (ddr, loop_nest); + if (flag_check_data_deps) { - /* Compute the dependences using the first algorithm. */ - subscript_dependence_tester (ddr, loop_nest); - + /* Dump the dependences from the first algorithm. */ if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\n\nBanerjee Analyzer\n"); @@ -4204,15 +4224,15 @@ compute_affine_dependence (struct data_dependence_relation *ddr, if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) { bool maybe_dependent; - VEC (lambda_vector, heap) *dir_vects, *dist_vects; + vec<lambda_vector> dir_vects, dist_vects; /* Save the result of the first DD analyzer. */ dist_vects = DDR_DIST_VECTS (ddr); dir_vects = DDR_DIR_VECTS (ddr); /* Reset the information. */ - DDR_DIST_VECTS (ddr) = NULL; - DDR_DIR_VECTS (ddr) = NULL; + DDR_DIST_VECTS (ddr).create (0); + DDR_DIR_VECTS (ddr).create (0); /* Compute the same information using Omega. */ if (!init_omega_for_ddr (ddr, &maybe_dependent)) @@ -4230,8 +4250,6 @@ compute_affine_dependence (struct data_dependence_relation *ddr, dir_vects)); } } - else - subscript_dependence_tester (ddr, loop_nest); } /* As a last case, if the dependence cannot be determined, or if @@ -4272,16 +4290,16 @@ compute_affine_dependence (struct data_dependence_relation *ddr, is small enough to be handled. */ bool -compute_all_dependences (VEC (data_reference_p, heap) *datarefs, - VEC (ddr_p, heap) **dependence_relations, - VEC (loop_p, heap) *loop_nest, +compute_all_dependences (vec<data_reference_p> datarefs, + vec<ddr_p> *dependence_relations, + vec<loop_p> loop_nest, bool compute_self_and_rr) { struct data_dependence_relation *ddr; struct data_reference *a, *b; unsigned int i, j; - if ((int) VEC_length (data_reference_p, datarefs) + if ((int) datarefs.length () > PARAM_VALUE (PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS)) { struct data_dependence_relation *ddr; @@ -4289,52 +4307,87 @@ compute_all_dependences (VEC (data_reference_p, heap) *datarefs, /* Insert a single relation into dependence_relations: chrec_dont_know. */ ddr = initialize_data_dependence_relation (NULL, NULL, loop_nest); - VEC_safe_push (ddr_p, heap, *dependence_relations, ddr); + dependence_relations->safe_push (ddr); return false; } - FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, a) - for (j = i + 1; VEC_iterate (data_reference_p, datarefs, j, b); j++) + FOR_EACH_VEC_ELT (datarefs, i, a) + for (j = i + 1; datarefs.iterate (j, &b); j++) if (DR_IS_WRITE (a) || DR_IS_WRITE (b) || compute_self_and_rr) { ddr = initialize_data_dependence_relation (a, b, loop_nest); - VEC_safe_push (ddr_p, heap, *dependence_relations, ddr); - if (loop_nest) - compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0)); + dependence_relations->safe_push (ddr); + if (loop_nest.exists ()) + compute_affine_dependence (ddr, loop_nest[0]); } if (compute_self_and_rr) - FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, a) + FOR_EACH_VEC_ELT (datarefs, i, a) { ddr = initialize_data_dependence_relation (a, a, loop_nest); - VEC_safe_push (ddr_p, heap, *dependence_relations, ddr); - if (loop_nest) - compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0)); + dependence_relations->safe_push (ddr); + if (loop_nest.exists ()) + compute_affine_dependence (ddr, loop_nest[0]); } return true; } +/* Describes a location of a memory reference. */ + +typedef struct data_ref_loc_d +{ + /* The memory reference. */ + tree ref; + + /* True if the memory reference is read. */ + bool is_read; +} data_ref_loc; + + /* Stores the locations of memory references in STMT to REFERENCES. Returns true if STMT clobbers memory, false otherwise. */ -bool -get_references_in_stmt (gimple stmt, VEC (data_ref_loc, heap) **references) +static bool +get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_heap> *references) { bool clobbers_memory = false; - data_ref_loc *ref; - tree *op0, *op1; + data_ref_loc ref; + tree op0, op1; enum gimple_code stmt_code = gimple_code (stmt); - *references = NULL; - /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects. - Calls have side-effects, except those to const or pure - functions. */ - if ((stmt_code == GIMPLE_CALL - && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))) - || (stmt_code == GIMPLE_ASM - && (gimple_asm_volatile_p (stmt) || gimple_vuse (stmt)))) + As we cannot model data-references to not spelled out + accesses give up if they may occur. */ + if (stmt_code == GIMPLE_CALL + && !(gimple_call_flags (stmt) & ECF_CONST)) + { + /* Allow IFN_GOMP_SIMD_LANE in their own loops. */ + if (gimple_call_internal_p (stmt)) + switch (gimple_call_internal_fn (stmt)) + { + case IFN_GOMP_SIMD_LANE: + { + struct loop *loop = gimple_bb (stmt)->loop_father; + tree uid = gimple_call_arg (stmt, 0); + gcc_assert (TREE_CODE (uid) == SSA_NAME); + if (loop == NULL + || loop->simduid != SSA_NAME_VAR (uid)) + clobbers_memory = true; + break; + } + case IFN_MASK_LOAD: + case IFN_MASK_STORE: + break; + default: + clobbers_memory = true; + break; + } + else + clobbers_memory = true; + } + else if (stmt_code == GIMPLE_ASM + && (gimple_asm_volatile_p (stmt) || gimple_vuse (stmt))) clobbers_memory = true; if (!gimple_vuse (stmt)) @@ -4343,48 +4396,69 @@ get_references_in_stmt (gimple stmt, VEC (data_ref_loc, heap) **references) if (stmt_code == GIMPLE_ASSIGN) { tree base; - op0 = gimple_assign_lhs_ptr (stmt); - op1 = gimple_assign_rhs1_ptr (stmt); + op0 = gimple_assign_lhs (stmt); + op1 = gimple_assign_rhs1 (stmt); - if (DECL_P (*op1) - || (REFERENCE_CLASS_P (*op1) - && (base = get_base_address (*op1)) + if (DECL_P (op1) + || (REFERENCE_CLASS_P (op1) + && (base = get_base_address (op1)) && TREE_CODE (base) != SSA_NAME)) { - ref = VEC_safe_push (data_ref_loc, heap, *references, NULL); - ref->pos = op1; - ref->is_read = true; + ref.ref = op1; + ref.is_read = true; + references->safe_push (ref); } } else if (stmt_code == GIMPLE_CALL) { unsigned i, n; - op0 = gimple_call_lhs_ptr (stmt); + ref.is_read = false; + if (gimple_call_internal_p (stmt)) + switch (gimple_call_internal_fn (stmt)) + { + case IFN_MASK_LOAD: + if (gimple_call_lhs (stmt) == NULL_TREE) + break; + ref.is_read = true; + case IFN_MASK_STORE: + ref.ref = fold_build2 (MEM_REF, + ref.is_read + ? TREE_TYPE (gimple_call_lhs (stmt)) + : TREE_TYPE (gimple_call_arg (stmt, 3)), + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 1)); + references->safe_push (ref); + return false; + default: + break; + } + + op0 = gimple_call_lhs (stmt); n = gimple_call_num_args (stmt); for (i = 0; i < n; i++) { - op1 = gimple_call_arg_ptr (stmt, i); + op1 = gimple_call_arg (stmt, i); - if (DECL_P (*op1) - || (REFERENCE_CLASS_P (*op1) && get_base_address (*op1))) + if (DECL_P (op1) + || (REFERENCE_CLASS_P (op1) && get_base_address (op1))) { - ref = VEC_safe_push (data_ref_loc, heap, *references, NULL); - ref->pos = op1; - ref->is_read = true; + ref.ref = op1; + ref.is_read = true; + references->safe_push (ref); } } } else return clobbers_memory; - if (*op0 - && (DECL_P (*op0) - || (REFERENCE_CLASS_P (*op0) && get_base_address (*op0)))) + if (op0 + && (DECL_P (op0) + || (REFERENCE_CLASS_P (op0) && get_base_address (op0)))) { - ref = VEC_safe_push (data_ref_loc, heap, *references, NULL); - ref->pos = op0; - ref->is_read = false; + ref.ref = op0; + ref.is_read = false; + references->safe_push (ref); } return clobbers_memory; } @@ -4395,28 +4469,25 @@ get_references_in_stmt (gimple stmt, VEC (data_ref_loc, heap) **references) bool find_data_references_in_stmt (struct loop *nest, gimple stmt, - VEC (data_reference_p, heap) **datarefs) + vec<data_reference_p> *datarefs) { unsigned i; - VEC (data_ref_loc, heap) *references; + auto_vec<data_ref_loc, 2> references; data_ref_loc *ref; bool ret = true; data_reference_p dr; if (get_references_in_stmt (stmt, &references)) - { - VEC_free (data_ref_loc, heap, references); - return false; - } + return false; - FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref) + FOR_EACH_VEC_ELT (references, i, ref) { dr = create_data_ref (nest, loop_containing_stmt (stmt), - *ref->pos, stmt, ref->is_read); + ref->ref, stmt, ref->is_read); gcc_assert (dr != NULL); - VEC_safe_push (data_reference_p, heap, *datarefs, dr); + datarefs->safe_push (dr); } - VEC_free (data_ref_loc, heap, references); + references.release (); return ret; } @@ -4428,28 +4499,25 @@ find_data_references_in_stmt (struct loop *nest, gimple stmt, bool graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple stmt, - VEC (data_reference_p, heap) **datarefs) + vec<data_reference_p> *datarefs) { unsigned i; - VEC (data_ref_loc, heap) *references; + auto_vec<data_ref_loc, 2> references; data_ref_loc *ref; bool ret = true; data_reference_p dr; if (get_references_in_stmt (stmt, &references)) - { - VEC_free (data_ref_loc, heap, references); - return false; - } + return false; - FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref) + FOR_EACH_VEC_ELT (references, i, ref) { - dr = create_data_ref (nest, loop, *ref->pos, stmt, ref->is_read); + dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read); gcc_assert (dr != NULL); - VEC_safe_push (data_reference_p, heap, *datarefs, dr); + datarefs->safe_push (dr); } - VEC_free (data_ref_loc, heap, references); + references.release (); return ret; } @@ -4459,7 +4527,7 @@ graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple stmt, tree find_data_references_in_bb (struct loop *loop, basic_block bb, - VEC (data_reference_p, heap) **datarefs) + vec<data_reference_p> *datarefs) { gimple_stmt_iterator bsi; @@ -4471,7 +4539,7 @@ find_data_references_in_bb (struct loop *loop, basic_block bb, { struct data_reference *res; res = XCNEW (struct data_reference); - VEC_safe_push (data_reference_p, heap, *datarefs, res); + datarefs->safe_push (res); return chrec_dont_know; } @@ -4487,9 +4555,9 @@ find_data_references_in_bb (struct loop *loop, basic_block bb, TODO: This function should be made smarter so that it can handle address arithmetic as if they were array accesses, etc. */ -static tree +tree find_data_references_in_loop (struct loop *loop, - VEC (data_reference_p, heap) **datarefs) + vec<data_reference_p> *datarefs) { basic_block bb, *bbs; unsigned int i; @@ -4514,7 +4582,7 @@ find_data_references_in_loop (struct loop *loop, /* Recursive helper function. */ static bool -find_loop_nest_1 (struct loop *loop, VEC (loop_p, heap) **loop_nest) +find_loop_nest_1 (struct loop *loop, vec<loop_p> *loop_nest) { /* Inner loops of the nest should not contain siblings. Example: when there are two consecutive loops, @@ -4533,7 +4601,7 @@ find_loop_nest_1 (struct loop *loop, VEC (loop_p, heap) **loop_nest) if (loop->next) return false; - VEC_safe_push (loop_p, heap, *loop_nest, loop); + loop_nest->safe_push (loop); if (loop->inner) return find_loop_nest_1 (loop->inner, loop_nest); return true; @@ -4545,9 +4613,9 @@ find_loop_nest_1 (struct loop *loop, VEC (loop_p, heap) **loop_nest) appear in the classic distance vector. */ bool -find_loop_nest (struct loop *loop, VEC (loop_p, heap) **loop_nest) +find_loop_nest (struct loop *loop, vec<loop_p> *loop_nest) { - VEC_safe_push (loop_p, heap, *loop_nest, loop); + loop_nest->safe_push (loop); if (loop->inner) return find_loop_nest_1 (loop->inner, loop_nest); return true; @@ -4563,9 +4631,9 @@ find_loop_nest (struct loop *loop, VEC (loop_p, heap) **loop_nest) bool compute_data_dependences_for_loop (struct loop *loop, bool compute_self_and_read_read_dependences, - VEC (loop_p, heap) **loop_nest, - VEC (data_reference_p, heap) **datarefs, - VEC (ddr_p, heap) **dependence_relations) + vec<loop_p> *loop_nest, + vec<data_reference_p> *datarefs, + vec<ddr_p> *dependence_relations) { bool res = true; @@ -4641,13 +4709,13 @@ compute_data_dependences_for_loop (struct loop *loop, bool compute_data_dependences_for_bb (basic_block bb, bool compute_self_and_read_read_dependences, - VEC (data_reference_p, heap) **datarefs, - VEC (ddr_p, heap) **dependence_relations) + vec<data_reference_p> *datarefs, + vec<ddr_p> *dependence_relations) { if (find_data_references_in_bb (NULL, bb, datarefs) == chrec_dont_know) return false; - return compute_all_dependences (*datarefs, dependence_relations, NULL, + return compute_all_dependences (*datarefs, dependence_relations, vNULL, compute_self_and_read_read_dependences); } @@ -4677,11 +4745,12 @@ analyze_all_data_dependences (struct loop *loop) { unsigned int i; int nb_data_refs = 10; - VEC (data_reference_p, heap) *datarefs = - VEC_alloc (data_reference_p, heap, nb_data_refs); - VEC (ddr_p, heap) *dependence_relations = - VEC_alloc (ddr_p, heap, nb_data_refs * nb_data_refs); - VEC (loop_p, heap) *loop_nest = VEC_alloc (loop_p, heap, 3); + vec<data_reference_p> datarefs; + datarefs.create (nb_data_refs); + vec<ddr_p> dependence_relations; + dependence_relations.create (nb_data_refs * nb_data_refs); + vec<loop_p> loop_nest; + loop_nest.create (3); /* Compute DDs on the whole function. */ compute_data_dependences_for_loop (loop, false, &loop_nest, &datarefs, @@ -4702,7 +4771,7 @@ analyze_all_data_dependences (struct loop *loop) unsigned nb_chrec_relations = 0; struct data_dependence_relation *ddr; - FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr) + FOR_EACH_VEC_ELT (dependence_relations, i, ddr) { if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr))) nb_top_relations++; @@ -4718,7 +4787,7 @@ analyze_all_data_dependences (struct loop *loop) } } - VEC_free (loop_p, heap, loop_nest); + loop_nest.release (); free_dependence_relations (dependence_relations); free_data_refs (datarefs); } @@ -4729,10 +4798,9 @@ analyze_all_data_dependences (struct loop *loop) void tree_check_data_deps (void) { - loop_iterator li; struct loop *loop_nest; - FOR_EACH_LOOP (li, loop_nest, 0) + FOR_EACH_LOOP (loop_nest, 0) analyze_all_data_dependences (loop_nest); } @@ -4744,12 +4812,10 @@ free_dependence_relation (struct data_dependence_relation *ddr) if (ddr == NULL) return; - if (DDR_SUBSCRIPTS (ddr)) + if (DDR_SUBSCRIPTS (ddr).exists ()) free_subscripts (DDR_SUBSCRIPTS (ddr)); - if (DDR_DIST_VECTS (ddr)) - VEC_free (lambda_vector, heap, DDR_DIST_VECTS (ddr)); - if (DDR_DIR_VECTS (ddr)) - VEC_free (lambda_vector, heap, DDR_DIR_VECTS (ddr)); + DDR_DIST_VECTS (ddr).release (); + DDR_DIR_VECTS (ddr).release (); free (ddr); } @@ -4758,748 +4824,27 @@ free_dependence_relation (struct data_dependence_relation *ddr) DEPENDENCE_RELATIONS. */ void -free_dependence_relations (VEC (ddr_p, heap) *dependence_relations) +free_dependence_relations (vec<ddr_p> dependence_relations) { unsigned int i; struct data_dependence_relation *ddr; - FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr) + FOR_EACH_VEC_ELT (dependence_relations, i, ddr) if (ddr) free_dependence_relation (ddr); - VEC_free (ddr_p, heap, dependence_relations); + dependence_relations.release (); } /* Free the memory used by the data references from DATAREFS. */ void -free_data_refs (VEC (data_reference_p, heap) *datarefs) +free_data_refs (vec<data_reference_p> datarefs) { unsigned int i; struct data_reference *dr; - FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, dr) + FOR_EACH_VEC_ELT (datarefs, i, dr) free_data_ref (dr); - VEC_free (data_reference_p, heap, datarefs); -} - - - -/* Dump vertex I in RDG to FILE. */ - -void -dump_rdg_vertex (FILE *file, struct graph *rdg, int i) -{ - struct vertex *v = &(rdg->vertices[i]); - struct graph_edge *e; - - fprintf (file, "(vertex %d: (%s%s) (in:", i, - RDG_MEM_WRITE_STMT (rdg, i) ? "w" : "", - RDG_MEM_READS_STMT (rdg, i) ? "r" : ""); - - if (v->pred) - for (e = v->pred; e; e = e->pred_next) - fprintf (file, " %d", e->src); - - fprintf (file, ") (out:"); - - if (v->succ) - for (e = v->succ; e; e = e->succ_next) - fprintf (file, " %d", e->dest); - - fprintf (file, ")\n"); - print_gimple_stmt (file, RDGV_STMT (v), 0, TDF_VOPS|TDF_MEMSYMS); - fprintf (file, ")\n"); -} - -/* Call dump_rdg_vertex on stderr. */ - -DEBUG_FUNCTION void -debug_rdg_vertex (struct graph *rdg, int i) -{ - dump_rdg_vertex (stderr, rdg, i); -} - -/* Dump component C of RDG to FILE. If DUMPED is non-null, set the - dumped vertices to that bitmap. */ - -void dump_rdg_component (FILE *file, struct graph *rdg, int c, bitmap dumped) -{ - int i; - - fprintf (file, "(%d\n", c); - - for (i = 0; i < rdg->n_vertices; i++) - if (rdg->vertices[i].component == c) - { - if (dumped) - bitmap_set_bit (dumped, i); - - dump_rdg_vertex (file, rdg, i); - } - - fprintf (file, ")\n"); -} - -/* Call dump_rdg_vertex on stderr. */ - -DEBUG_FUNCTION void -debug_rdg_component (struct graph *rdg, int c) -{ - dump_rdg_component (stderr, rdg, c, NULL); -} - -/* Dump the reduced dependence graph RDG to FILE. */ - -void -dump_rdg (FILE *file, struct graph *rdg) -{ - int i; - bitmap dumped = BITMAP_ALLOC (NULL); - - fprintf (file, "(rdg\n"); - - for (i = 0; i < rdg->n_vertices; i++) - if (!bitmap_bit_p (dumped, i)) - dump_rdg_component (file, rdg, rdg->vertices[i].component, dumped); - - fprintf (file, ")\n"); - BITMAP_FREE (dumped); -} - -/* Call dump_rdg on stderr. */ - -DEBUG_FUNCTION void -debug_rdg (struct graph *rdg) -{ - dump_rdg (stderr, rdg); -} - -static void -dot_rdg_1 (FILE *file, struct graph *rdg) -{ - int i; - - fprintf (file, "digraph RDG {\n"); - - for (i = 0; i < rdg->n_vertices; i++) - { - struct vertex *v = &(rdg->vertices[i]); - struct graph_edge *e; - - /* Highlight reads from memory. */ - if (RDG_MEM_READS_STMT (rdg, i)) - fprintf (file, "%d [style=filled, fillcolor=green]\n", i); - - /* Highlight stores to memory. */ - if (RDG_MEM_WRITE_STMT (rdg, i)) - fprintf (file, "%d [style=filled, fillcolor=red]\n", i); - - if (v->succ) - for (e = v->succ; e; e = e->succ_next) - switch (RDGE_TYPE (e)) - { - case input_dd: - fprintf (file, "%d -> %d [label=input] \n", i, e->dest); - break; - - case output_dd: - fprintf (file, "%d -> %d [label=output] \n", i, e->dest); - break; - - case flow_dd: - /* These are the most common dependences: don't print these. */ - fprintf (file, "%d -> %d \n", i, e->dest); - break; - - case anti_dd: - fprintf (file, "%d -> %d [label=anti] \n", i, e->dest); - break; - - default: - gcc_unreachable (); - } - } - - fprintf (file, "}\n\n"); -} - -/* Display the Reduced Dependence Graph using dotty. */ -extern void dot_rdg (struct graph *); - -DEBUG_FUNCTION void -dot_rdg (struct graph *rdg) -{ - /* When debugging, enable the following code. This cannot be used - in production compilers because it calls "system". */ -#if 0 - FILE *file = fopen ("/tmp/rdg.dot", "w"); - gcc_assert (file != NULL); - - dot_rdg_1 (file, rdg); - fclose (file); - - system ("dotty /tmp/rdg.dot &"); -#else - dot_rdg_1 (stderr, rdg); -#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 - order that we keep track of in the RDG is the order in which - statements have to be executed. */ - -static void -create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr) -{ - struct graph_edge *e; - int va, vb; - data_reference_p dra = DDR_A (ddr); - data_reference_p drb = DDR_B (ddr); - unsigned level = ddr_dependence_level (ddr); - - /* For non scalar dependences, when the dependence is REVERSED, - statement B has to be executed before statement A. */ - if (level > 0 - && !DDR_REVERSED_P (ddr)) - { - data_reference_p tmp = dra; - dra = drb; - drb = tmp; - } - - va = rdg_vertex_for_stmt (rdg, DR_STMT (dra)); - vb = rdg_vertex_for_stmt (rdg, DR_STMT (drb)); - - if (va < 0 || vb < 0) - return; - - e = add_edge (rdg, va, vb); - e->data = XNEW (struct rdg_edge); - - RDGE_LEVEL (e) = level; - RDGE_RELATION (e) = ddr; - - /* Determines the type of the data dependence. */ - if (DR_IS_READ (dra) && DR_IS_READ (drb)) - RDGE_TYPE (e) = input_dd; - else if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb)) - RDGE_TYPE (e) = output_dd; - else if (DR_IS_WRITE (dra) && DR_IS_READ (drb)) - RDGE_TYPE (e) = flow_dd; - else if (DR_IS_READ (dra) && DR_IS_WRITE (drb)) - RDGE_TYPE (e) = anti_dd; -} - -/* Creates dependence edges in RDG for all the uses of DEF. IDEF is - the index of DEF in RDG. */ - -static void -create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef) -{ - use_operand_p imm_use_p; - imm_use_iterator iterator; - - FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, def) - { - struct graph_edge *e; - int use = rdg_vertex_for_stmt (rdg, USE_STMT (imm_use_p)); - - if (use < 0) - continue; - - e = add_edge (rdg, idef, use); - e->data = XNEW (struct rdg_edge); - RDGE_TYPE (e) = flow_dd; - RDGE_RELATION (e) = NULL; - } -} - -/* Creates the edges of the reduced dependence graph RDG. */ - -static void -create_rdg_edges (struct graph *rdg, VEC (ddr_p, heap) *ddrs) -{ - int i; - struct data_dependence_relation *ddr; - def_operand_p def_p; - ssa_op_iter iter; - - FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr) - if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) - create_rdg_edge_for_ddr (rdg, ddr); - - for (i = 0; i < rdg->n_vertices; i++) - FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i), - iter, SSA_OP_DEF) - create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i); -} - -/* 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; - - FOR_EACH_VEC_ELT (gimple, stmts, i, stmt) - { - 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); - } -} - -/* Initialize STMTS with all the statements of LOOP. When - INCLUDE_PHIS is true, include also the PHI nodes. The order in - which we discover statements is important as - generate_loops_for_partition is using the same traversal for - identifying statements. */ - -static void -stmts_from_loop (struct loop *loop, VEC (gimple, heap) **stmts) -{ - unsigned int i; - basic_block *bbs = get_loop_body_in_dom_order (loop); - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = bbs[i]; - gimple_stmt_iterator bsi; - gimple stmt; - - for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) - VEC_safe_push (gimple, heap, *stmts, gsi_stmt (bsi)); - - for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) - { - stmt = gsi_stmt (bsi); - if (gimple_code (stmt) != GIMPLE_LABEL && !is_gimple_debug (stmt)) - VEC_safe_push (gimple, heap, *stmts, stmt); - } - } - - free (bbs); -} - -/* Returns true when all the dependences are computable. */ - -static bool -known_dependences_p (VEC (ddr_p, heap) *dependence_relations) -{ - ddr_p ddr; - unsigned int i; - - FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr) - if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) - return false; - - 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. */ - -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; -} - -/* Build the Reduced Dependence Graph (RDG) with one vertex per - statement of the loop nest, and one edge per data dependence or - scalar dependence. */ - -struct graph * -build_rdg (struct loop *loop, - VEC (loop_p, heap) **loop_nest, - VEC (ddr_p, heap) **dependence_relations, - VEC (data_reference_p, heap) **datarefs) -{ - struct graph *rdg = NULL; - - if (compute_data_dependences_for_loop (loop, false, loop_nest, datarefs, - dependence_relations) - && known_dependences_p (*dependence_relations)) - { - 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); - } - - return rdg; -} - -/* Free the reduced dependence graph RDG. */ - -void -free_rdg (struct graph *rdg) -{ - int i; - - for (i = 0; i < rdg->n_vertices; i++) - { - struct vertex *v = &(rdg->vertices[i]); - struct graph_edge *e; - - for (e = v->succ; e; e = e->succ_next) - free (e->data); - - free (v->data); - } - - htab_delete (rdg->indices); - free_graph (rdg); -} - -/* Initialize STMTS with all the statements of LOOP that contain a - store to memory. */ - -void -stores_from_loop (struct loop *loop, VEC (gimple, heap) **stmts) -{ - unsigned int i; - basic_block *bbs = get_loop_body_in_dom_order (loop); - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = bbs[i]; - gimple_stmt_iterator bsi; - - for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) - if (gimple_vdef (gsi_stmt (bsi))) - VEC_safe_push (gimple, heap, *stmts, gsi_stmt (bsi)); - } - - free (bbs); -} - -/* Returns true when the statement at STMT is of the form "A[i] = 0" - that contains a data reference on its LHS with a stride of the same - size as its unit type. */ - -bool -stmt_with_adjacent_zero_store_dr_p (gimple stmt) -{ - tree lhs, rhs; - bool res; - struct data_reference *dr; - - if (!stmt - || !gimple_vdef (stmt) - || !gimple_assign_single_p (stmt)) - return false; - - lhs = gimple_assign_lhs (stmt); - rhs = gimple_assign_rhs1 (stmt); - - /* If this is a bitfield store bail out. */ - if (TREE_CODE (lhs) == COMPONENT_REF - && DECL_BIT_FIELD (TREE_OPERAND (lhs, 1))) - return false; - - if (!(integer_zerop (rhs) || real_zerop (rhs))) - return false; - - dr = XCNEW (struct data_reference); - - DR_STMT (dr) = stmt; - DR_REF (dr) = lhs; - - res = dr_analyze_innermost (dr, loop_containing_stmt (stmt)) - && stride_of_unit_type_p (DR_STEP (dr), TREE_TYPE (lhs)); - - free_data_ref (dr); - return res; -} - -/* Initialize STMTS with all the statements of LOOP that contain a - store to memory of the form "A[i] = 0". */ - -void -stores_zero_from_loop (struct loop *loop, VEC (gimple, heap) **stmts) -{ - unsigned int i; - basic_block bb; - gimple_stmt_iterator si; - gimple stmt; - basic_block *bbs = get_loop_body_in_dom_order (loop); - - for (i = 0; i < loop->num_nodes; i++) - for (bb = bbs[i], si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) - if ((stmt = gsi_stmt (si)) - && stmt_with_adjacent_zero_store_dr_p (stmt)) - VEC_safe_push (gimple, heap, *stmts, gsi_stmt (si)); - - 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. */ - -bool -rdg_defs_used_in_other_loops_p (struct graph *rdg, int v) -{ - gimple stmt = RDG_STMT (rdg, v); - struct loop *loop = loop_containing_stmt (stmt); - use_operand_p imm_use_p; - imm_use_iterator iterator; - ssa_op_iter it; - def_operand_p def_p; - - if (!loop) - return true; - - FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, it, SSA_OP_DEF) - { - FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, DEF_FROM_PTR (def_p)) - { - if (loop_containing_stmt (USE_STMT (imm_use_p)) != loop) - return true; - } - } - - 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; -} - -/* Helper function for the hashtab. */ - -static int -have_similar_memory_accesses_1 (const void *s1, const void *s2) -{ - return have_similar_memory_accesses (CONST_CAST_GIMPLE ((const_gimple) s1), - CONST_CAST_GIMPLE ((const_gimple) s2)); -} - -/* Helper function for the hashtab. */ - -static hashval_t -ref_base_address_1 (const void *s) -{ - gimple stmt = CONST_CAST_GIMPLE ((const_gimple) s); - unsigned i; - VEC (data_ref_loc, heap) *refs; - data_ref_loc *ref; - hashval_t res = 0; - - get_references_in_stmt (stmt, &refs); - - FOR_EACH_VEC_ELT (data_ref_loc, refs, i, ref) - if (!ref->is_read) - { - res = htab_hash_pointer (ref_base_address (stmt, ref)); - break; - } - - VEC_free (data_ref_loc, heap, refs); - return res; -} - -/* Try to remove duplicated write data references from STMTS. */ - -void -remove_similar_memory_refs (VEC (gimple, heap) **stmts) -{ - unsigned i; - gimple stmt; - htab_t seen = htab_create (VEC_length (gimple, *stmts), ref_base_address_1, - have_similar_memory_accesses_1, NULL); - - for (i = 0; VEC_iterate (gimple, *stmts, i, stmt); ) - { - void **slot; - - slot = htab_find_slot (seen, stmt, INSERT); - - if (*slot) - VEC_ordered_remove (gimple, *stmts, i); - else - { - *slot = (void *) stmt; - i++; - } - } - - htab_delete (seen); -} - -/* Returns the index of PARAMETER in the parameters vector of the - ACCESS_MATRIX. If PARAMETER does not exist return -1. */ - -int -access_matrix_get_index_for_parameter (tree parameter, - struct access_matrix *access_matrix) -{ - int i; - VEC (tree,heap) *lambda_parameters = AM_PARAMETERS (access_matrix); - tree lambda_parameter; - - FOR_EACH_VEC_ELT (tree, lambda_parameters, i, lambda_parameter) - if (lambda_parameter == parameter) - return i + AM_NB_INDUCTION_VARS (access_matrix); - - return -1; + datarefs.release (); } |