+2017-05-26 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-vect-data-refs.c (Operator==, comp_dr_with_seg_len_pair):
+ Move from ...
+ * tree-data-ref.c (Operator==, comp_dr_with_seg_len_pair): To here.
+ * tree-vect-data-refs.c (vect_prune_runtime_alias_test_list): Factor
+ out code pruning runtime alias checks.
+ * tree-data-ref.c (prune_runtime_alias_test_list): New function
+ factored out from above.
+ * tree-vectorizer.h (struct dr_with_seg_len, dr_with_seg_len_pair_t):
+ Move from ...
+ * tree-data-ref.h (struct dr_with_seg_len, dr_with_seg_len_pair_t):
+ ... to here.
+ (prune_runtime_alias_test_list): New decalaration.
+
2017-05-26 Bin Cheng <bin.cheng@arm.com>
* tree-vect-data-refs.c (compare_tree): Rename and move ...
return 0;
}
+/* Operator == between two dr_with_seg_len objects.
+
+ This equality operator is used to make sure two data refs
+ are the same one so that we will consider to combine the
+ aliasing checks of those two pairs of data dependent data
+ refs. */
+
+static bool
+operator == (const dr_with_seg_len& d1,
+ const dr_with_seg_len& d2)
+{
+ return operand_equal_p (DR_BASE_ADDRESS (d1.dr),
+ DR_BASE_ADDRESS (d2.dr), 0)
+ && data_ref_compare_tree (DR_OFFSET (d1.dr), DR_OFFSET (d2.dr)) == 0
+ && data_ref_compare_tree (DR_INIT (d1.dr), DR_INIT (d2.dr)) == 0
+ && data_ref_compare_tree (d1.seg_len, d2.seg_len) == 0;
+}
+
+/* Comparison function for sorting objects of dr_with_seg_len_pair_t
+ so that we can combine aliasing checks in one scan. */
+
+static int
+comp_dr_with_seg_len_pair (const void *pa_, const void *pb_)
+{
+ const dr_with_seg_len_pair_t* pa = (const dr_with_seg_len_pair_t *) pa_;
+ const dr_with_seg_len_pair_t* pb = (const dr_with_seg_len_pair_t *) pb_;
+ const dr_with_seg_len &a1 = pa->first, &a2 = pa->second;
+ const dr_with_seg_len &b1 = pb->first, &b2 = pb->second;
+
+ /* For DR pairs (a, b) and (c, d), we only consider to merge the alias checks
+ if a and c have the same basic address snd step, and b and d have the same
+ address and step. Therefore, if any a&c or b&d don't have the same address
+ and step, we don't care the order of those two pairs after sorting. */
+ int comp_res;
+
+ if ((comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (a1.dr),
+ DR_BASE_ADDRESS (b1.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (a2.dr),
+ DR_BASE_ADDRESS (b2.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_STEP (a1.dr),
+ DR_STEP (b1.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_STEP (a2.dr),
+ DR_STEP (b2.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_OFFSET (a1.dr),
+ DR_OFFSET (b1.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_INIT (a1.dr),
+ DR_INIT (b1.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_OFFSET (a2.dr),
+ DR_OFFSET (b2.dr))) != 0)
+ return comp_res;
+ if ((comp_res = data_ref_compare_tree (DR_INIT (a2.dr),
+ DR_INIT (b2.dr))) != 0)
+ return comp_res;
+
+ return 0;
+}
+
+/* Merge alias checks recorded in ALIAS_PAIRS and remove redundant ones.
+ FACTOR is number of iterations that each data reference is accessed.
+
+ Basically, for each pair of dependent data refs store_ptr_0 & load_ptr_0,
+ we create an expression:
+
+ ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+ || (load_ptr_0 + load_segment_length_0) <= store_ptr_0))
+
+ for aliasing checks. However, in some cases we can decrease the number
+ of checks by combining two checks into one. For example, suppose we have
+ another pair of data refs store_ptr_0 & load_ptr_1, and if the following
+ condition is satisfied:
+
+ load_ptr_0 < load_ptr_1 &&
+ load_ptr_1 - load_ptr_0 - load_segment_length_0 < store_segment_length_0
+
+ (this condition means, in each iteration of vectorized loop, the accessed
+ memory of store_ptr_0 cannot be between the memory of load_ptr_0 and
+ load_ptr_1.)
+
+ we then can use only the following expression to finish the alising checks
+ between store_ptr_0 & load_ptr_0 and store_ptr_0 & load_ptr_1:
+
+ ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+ || (load_ptr_1 + load_segment_length_1 <= store_ptr_0))
+
+ Note that we only consider that load_ptr_0 and load_ptr_1 have the same
+ basic address. */
+
+void
+prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
+ unsigned HOST_WIDE_INT factor)
+{
+ /* Sort the collected data ref pairs so that we can scan them once to
+ combine all possible aliasing checks. */
+ alias_pairs->qsort (comp_dr_with_seg_len_pair);
+
+ /* Scan the sorted dr pairs and check if we can combine alias checks
+ of two neighboring dr pairs. */
+ for (size_t i = 1; i < alias_pairs->length (); ++i)
+ {
+ /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2). */
+ dr_with_seg_len *dr_a1 = &(*alias_pairs)[i-1].first,
+ *dr_b1 = &(*alias_pairs)[i-1].second,
+ *dr_a2 = &(*alias_pairs)[i].first,
+ *dr_b2 = &(*alias_pairs)[i].second;
+
+ /* Remove duplicate data ref pairs. */
+ if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2)
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf (MSG_NOTE, "found equal ranges ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
+ dump_printf (MSG_NOTE, " and ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
+ dump_printf (MSG_NOTE, "\n");
+ }
+ alias_pairs->ordered_remove (i--);
+ continue;
+ }
+
+ if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2)
+ {
+ /* We consider the case that DR_B1 and DR_B2 are same memrefs,
+ and DR_A1 and DR_A2 are two consecutive memrefs. */
+ if (*dr_a1 == *dr_a2)
+ {
+ std::swap (dr_a1, dr_b1);
+ std::swap (dr_a2, dr_b2);
+ }
+
+ if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
+ DR_BASE_ADDRESS (dr_a2->dr), 0)
+ || !operand_equal_p (DR_OFFSET (dr_a1->dr),
+ DR_OFFSET (dr_a2->dr), 0)
+ || !tree_fits_shwi_p (DR_INIT (dr_a1->dr))
+ || !tree_fits_shwi_p (DR_INIT (dr_a2->dr)))
+ continue;
+
+ /* Only merge const step data references. */
+ if (TREE_CODE (DR_STEP (dr_a1->dr)) != INTEGER_CST
+ || TREE_CODE (DR_STEP (dr_a2->dr)) != INTEGER_CST)
+ continue;
+
+ /* DR_A1 and DR_A2 must goes in the same direction. */
+ if (tree_int_cst_compare (DR_STEP (dr_a1->dr), size_zero_node)
+ != tree_int_cst_compare (DR_STEP (dr_a2->dr), size_zero_node))
+ continue;
+
+ /* Make sure dr_a1 starts left of dr_a2. */
+ if (tree_int_cst_lt (DR_INIT (dr_a2->dr), DR_INIT (dr_a1->dr)))
+ std::swap (*dr_a1, *dr_a2);
+
+ bool do_remove = false;
+ unsigned HOST_WIDE_INT diff
+ = (tree_to_shwi (DR_INIT (dr_a2->dr))
+ - tree_to_shwi (DR_INIT (dr_a1->dr)));
+
+ /* If the left segment does not extend beyond the start of the
+ right segment the new segment length is that of the right
+ plus the segment distance. */
+ if (tree_fits_uhwi_p (dr_a1->seg_len)
+ && compare_tree_int (dr_a1->seg_len, diff) <= 0)
+ {
+ dr_a1->seg_len = size_binop (PLUS_EXPR, dr_a2->seg_len,
+ size_int (diff));
+ do_remove = true;
+ }
+ /* Generally the new segment length is the maximum of the
+ left segment size and the right segment size plus the distance.
+ ??? We can also build tree MAX_EXPR here but it's not clear this
+ is profitable. */
+ else if (tree_fits_uhwi_p (dr_a1->seg_len)
+ && tree_fits_uhwi_p (dr_a2->seg_len))
+ {
+ unsigned HOST_WIDE_INT seg_len_a1 = tree_to_uhwi (dr_a1->seg_len);
+ unsigned HOST_WIDE_INT seg_len_a2 = tree_to_uhwi (dr_a2->seg_len);
+ dr_a1->seg_len = size_int (MAX (seg_len_a1, diff + seg_len_a2));
+ do_remove = true;
+ }
+ /* Now we check if the following condition is satisfied:
+
+ DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
+
+ where DIFF = DR_A2_INIT - DR_A1_INIT. However,
+ SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we
+ have to make a best estimation. We can get the minimum value
+ of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,
+ then either of the following two conditions can guarantee the
+ one above:
+
+ 1: DIFF <= MIN_SEG_LEN_B
+ 2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B */
+ else
+ {
+ unsigned HOST_WIDE_INT min_seg_len_b
+ = (tree_fits_uhwi_p (dr_b1->seg_len)
+ ? tree_to_uhwi (dr_b1->seg_len)
+ : factor);
+
+ if (diff <= min_seg_len_b
+ || (tree_fits_uhwi_p (dr_a1->seg_len)
+ && diff - tree_to_uhwi (dr_a1->seg_len) < min_seg_len_b))
+ {
+ dr_a1->seg_len = size_binop (PLUS_EXPR,
+ dr_a2->seg_len, size_int (diff));
+ do_remove = true;
+ }
+ }
+
+ if (do_remove)
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf (MSG_NOTE, "merging ranges for ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
+ dump_printf (MSG_NOTE, " and ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
+ dump_printf (MSG_NOTE, "\n");
+ }
+ alias_pairs->ordered_remove (i--);
+ }
+ }
+ }
+}
+
/* Check if OFFSET1 and OFFSET2 (DR_OFFSETs of some data-refs) are identical
expressions. */
static bool
typedef struct data_reference *data_reference_p;
+/* This struct is used to store the information of a data reference,
+ including the data ref itself and the segment length for aliasing
+ checks. This is used to merge alias checks. */
+
+struct dr_with_seg_len
+{
+ dr_with_seg_len (data_reference_p d, tree len)
+ : dr (d), seg_len (len) {}
+
+ data_reference_p dr;
+ tree seg_len;
+};
+
+/* This struct contains two dr_with_seg_len objects with aliasing data
+ refs. Two comparisons are generated from them. */
+
+struct dr_with_seg_len_pair_t
+{
+ dr_with_seg_len_pair_t (const dr_with_seg_len& d1,
+ const dr_with_seg_len& d2)
+ : first (d1), second (d2) {}
+
+ dr_with_seg_len first;
+ dr_with_seg_len second;
+};
+
enum data_dependence_direction {
dir_positive,
dir_negative,
struct data_reference *);
extern int data_ref_compare_tree (tree, tree);
+extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
+ unsigned HOST_WIDE_INT);
/* Return true when the base objects of data references A and B are
the same memory object. */
return true;
}
-
-/* Operator == between two dr_with_seg_len objects.
-
- This equality operator is used to make sure two data refs
- are the same one so that we will consider to combine the
- aliasing checks of those two pairs of data dependent data
- refs. */
-
-static bool
-operator == (const dr_with_seg_len& d1,
- const dr_with_seg_len& d2)
-{
- return operand_equal_p (DR_BASE_ADDRESS (d1.dr),
- DR_BASE_ADDRESS (d2.dr), 0)
- && data_ref_compare_tree (DR_OFFSET (d1.dr), DR_OFFSET (d2.dr)) == 0
- && data_ref_compare_tree (DR_INIT (d1.dr), DR_INIT (d2.dr)) == 0
- && data_ref_compare_tree (d1.seg_len, d2.seg_len) == 0;
-}
-
-/* Function comp_dr_with_seg_len_pair.
-
- Comparison function for sorting objects of dr_with_seg_len_pair_t
- so that we can combine aliasing checks in one scan. */
-
-static int
-comp_dr_with_seg_len_pair (const void *pa_, const void *pb_)
-{
- const dr_with_seg_len_pair_t* pa = (const dr_with_seg_len_pair_t *) pa_;
- const dr_with_seg_len_pair_t* pb = (const dr_with_seg_len_pair_t *) pb_;
- const dr_with_seg_len &a1 = pa->first, &a2 = pa->second;
- const dr_with_seg_len &b1 = pb->first, &b2 = pb->second;
-
- /* For DR pairs (a, b) and (c, d), we only consider to merge the alias checks
- if a and c have the same basic address snd step, and b and d have the same
- address and step. Therefore, if any a&c or b&d don't have the same address
- and step, we don't care the order of those two pairs after sorting. */
- int comp_res;
-
- if ((comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (a1.dr),
- DR_BASE_ADDRESS (b1.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_BASE_ADDRESS (a2.dr),
- DR_BASE_ADDRESS (b2.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_STEP (a1.dr),
- DR_STEP (b1.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_STEP (a2.dr),
- DR_STEP (b2.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_OFFSET (a1.dr),
- DR_OFFSET (b1.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_INIT (a1.dr),
- DR_INIT (b1.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_OFFSET (a2.dr),
- DR_OFFSET (b2.dr))) != 0)
- return comp_res;
- if ((comp_res = data_ref_compare_tree (DR_INIT (a2.dr),
- DR_INIT (b2.dr))) != 0)
- return comp_res;
-
- return 0;
-}
-
/* Function vect_vfa_segment_size.
Create an expression that computes the size of segment
if (may_alias_ddrs.is_empty ())
return true;
- /* Basically, for each pair of dependent data refs store_ptr_0
- and load_ptr_0, we create an expression:
-
- ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
- || (load_ptr_0 + load_segment_length_0) <= store_ptr_0))
-
- for aliasing checks. However, in some cases we can decrease
- the number of checks by combining two checks into one. For
- example, suppose we have another pair of data refs store_ptr_0
- and load_ptr_1, and if the following condition is satisfied:
-
- load_ptr_0 < load_ptr_1 &&
- load_ptr_1 - load_ptr_0 - load_segment_length_0 < store_segment_length_0
-
- (this condition means, in each iteration of vectorized loop,
- the accessed memory of store_ptr_0 cannot be between the memory
- of load_ptr_0 and load_ptr_1.)
-
- we then can use only the following expression to finish the
- alising checks between store_ptr_0 & load_ptr_0 and
- store_ptr_0 & load_ptr_1:
-
- ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
- || (load_ptr_1 + load_segment_length_1 <= store_ptr_0))
-
- Note that we only consider that load_ptr_0 and load_ptr_1 have the
- same basic address. */
-
comp_alias_ddrs.create (may_alias_ddrs.length ());
/* First, we collect all data ref pairs for aliasing checks. */
comp_alias_ddrs.safe_push (dr_with_seg_len_pair);
}
- /* Second, we sort the collected data ref pairs so that we can scan
- them once to combine all possible aliasing checks. */
- comp_alias_ddrs.qsort (comp_dr_with_seg_len_pair);
-
- /* Third, we scan the sorted dr pairs and check if we can combine
- alias checks of two neighboring dr pairs. */
- for (size_t i = 1; i < comp_alias_ddrs.length (); ++i)
- {
- /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2). */
- dr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first,
- *dr_b1 = &comp_alias_ddrs[i-1].second,
- *dr_a2 = &comp_alias_ddrs[i].first,
- *dr_b2 = &comp_alias_ddrs[i].second;
-
- /* Remove duplicate data ref pairs. */
- if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2)
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "found equal ranges ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (dr_a1->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (dr_b1->dr));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (dr_a2->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (dr_b2->dr));
- dump_printf (MSG_NOTE, "\n");
- }
-
- comp_alias_ddrs.ordered_remove (i--);
- continue;
- }
-
- if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2)
- {
- /* We consider the case that DR_B1 and DR_B2 are same memrefs,
- and DR_A1 and DR_A2 are two consecutive memrefs. */
- if (*dr_a1 == *dr_a2)
- {
- std::swap (dr_a1, dr_b1);
- std::swap (dr_a2, dr_b2);
- }
-
- if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
- DR_BASE_ADDRESS (dr_a2->dr), 0)
- || !operand_equal_p (DR_OFFSET (dr_a1->dr),
- DR_OFFSET (dr_a2->dr), 0)
- || !tree_fits_shwi_p (DR_INIT (dr_a1->dr))
- || !tree_fits_shwi_p (DR_INIT (dr_a2->dr)))
- continue;
-
- /* Make sure dr_a1 starts left of dr_a2. */
- if (tree_int_cst_lt (DR_INIT (dr_a2->dr), DR_INIT (dr_a1->dr)))
- std::swap (*dr_a1, *dr_a2);
-
- bool do_remove = false;
- unsigned HOST_WIDE_INT diff
- = (tree_to_shwi (DR_INIT (dr_a2->dr))
- - tree_to_shwi (DR_INIT (dr_a1->dr)));
-
- /* If the left segment does not extend beyond the start of the
- right segment the new segment length is that of the right
- plus the segment distance. */
- if (tree_fits_uhwi_p (dr_a1->seg_len)
- && compare_tree_int (dr_a1->seg_len, diff) <= 0)
- {
- dr_a1->seg_len = size_binop (PLUS_EXPR, dr_a2->seg_len,
- size_int (diff));
- do_remove = true;
- }
- /* Generally the new segment length is the maximum of the
- left segment size and the right segment size plus the distance.
- ??? We can also build tree MAX_EXPR here but it's not clear this
- is profitable. */
- else if (tree_fits_uhwi_p (dr_a1->seg_len)
- && tree_fits_uhwi_p (dr_a2->seg_len))
- {
- unsigned HOST_WIDE_INT seg_len_a1 = tree_to_uhwi (dr_a1->seg_len);
- unsigned HOST_WIDE_INT seg_len_a2 = tree_to_uhwi (dr_a2->seg_len);
- dr_a1->seg_len = size_int (MAX (seg_len_a1, diff + seg_len_a2));
- do_remove = true;
- }
- /* Now we check if the following condition is satisfied:
-
- DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
-
- where DIFF = DR_A2_INIT - DR_A1_INIT. However,
- SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we
- have to make a best estimation. We can get the minimum value
- of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,
- then either of the following two conditions can guarantee the
- one above:
-
- 1: DIFF <= MIN_SEG_LEN_B
- 2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B */
- else
- {
- unsigned HOST_WIDE_INT min_seg_len_b
- = (tree_fits_uhwi_p (dr_b1->seg_len)
- ? tree_to_uhwi (dr_b1->seg_len)
- : vect_factor);
-
- if (diff <= min_seg_len_b
- || (tree_fits_uhwi_p (dr_a1->seg_len)
- && diff - tree_to_uhwi (dr_a1->seg_len) < min_seg_len_b))
- {
- dr_a1->seg_len = size_binop (PLUS_EXPR,
- dr_a2->seg_len, size_int (diff));
- do_remove = true;
- }
- }
-
- if (do_remove)
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "merging ranges for ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
- dump_printf (MSG_NOTE, "\n");
- }
- comp_alias_ddrs.ordered_remove (i--);
- }
- }
- }
-
+ prune_runtime_alias_test_list (&comp_alias_ddrs,
+ (unsigned HOST_WIDE_INT) vect_factor);
dump_printf_loc (MSG_NOTE, vect_location,
"improved number of alias checks from %d to %d\n",
may_alias_ddrs.length (), comp_alias_ddrs.length ());
-/* This struct is used to store the information of a data reference,
- including the data ref itself and the segment length for aliasing
- checks. This is used to merge alias checks. */
-
-struct dr_with_seg_len
-{
- dr_with_seg_len (data_reference_p d, tree len)
- : dr (d), seg_len (len) {}
-
- data_reference_p dr;
- tree seg_len;
-};
-
-/* This struct contains two dr_with_seg_len objects with aliasing data
- refs. Two comparisons are generated from them. */
-
-struct dr_with_seg_len_pair_t
-{
- dr_with_seg_len_pair_t (const dr_with_seg_len& d1,
- const dr_with_seg_len& d2)
- : first (d1), second (d2) {}
-
- dr_with_seg_len first;
- dr_with_seg_len second;
-};
-
-
-
/* Vectorizer state common between loop and basic-block vectorization. */
struct vec_info {
enum { bb, loop } kind;