This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][1/n] Vectorizer TLC: re-organize data dependence checking
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 21 Mar 2013 13:45:13 +0100
- Subject: Re: [PATCH][1/n] Vectorizer TLC: re-organize data dependence checking
- References: <alpine dot LNX dot 2 dot 00 dot 1302271645240 dot 3543 at zhemvz dot fhfr dot qr> <CAFiYyc11ykbvmsfeaXcaSDg+a1oa1Mm_NJtb202M_mGmgOGC_Q at mail dot gmail dot com>
On Mon, Mar 18, 2013 at 11:25 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, Feb 27, 2013 at 4:49 PM, Richard Biener <rguenther@suse.de> wrote:
>>
>> This splits data reference group analysis away from data dependence
>> checking and splits the latter into loop and a BB vectorization
>> functions. This allows us to perform the now no longer quadratic
>> but O(n * log (n)) data reference group analysis right after
>> data reference gathering, pushing the quadratic data dependence
>> testing down the vectorization analysis pipeline.
>>
>> Bootstrap and regtest running on x86_64-unknown-linux-gnu, queued for 4.9.
>
> Committed as r196775.
Actually I committed the prerequesite as that revision,
2013-03-18 Richard Biener <rguenther@suse.de>
* tree-data-ref.h (find_data_references_in_loop): Declare.
* tree-data-ref.c (get_references_in_stmt): Use a stack
vector pre-allocated in the callers.
(find_data_references_in_stmt): Adjust.
(graphite_find_data_references_in_stmt): Likewise.
(create_rdg_vertices): Likewise.
(find_data_references_in_loop): Export.
* tree-vect-data-refs.c (vect_analyze_data_ref_dependences):
Compute dependences here...
(vect_analyze_data_refs): ...not here. When we encounter
a non-vectorizable data reference in basic-block vectorization
truncate the data reference vector. Do not bother to
fixup data-dependence information for gather loads.
* tree-vect-slp.c (vect_slp_analyze_bb_1): Check the number
of data references, as reported.
and now this patch, after re-testing it and clearing the FAILs of
gcc.dg/vect/vect-outer-3a-big-array.c and gcc.dg/vect/vect-outer-3a.c
by adjusting the expected output in dumps.
r196872.
Richard.
> Richard.
>
>> Richard.
>>
>> 2013-02-27 Richard Biener <rguenther@suse.de>
>>
>> * tree-vect-data-refs.c (vect_update_interleaving_chain): Remove.
>> (vect_insert_into_interleaving_chain): Likewise.
>> (vect_drs_dependent_in_basic_block): Inline ...
>> (vect_slp_analyze_data_ref_dependence): ... here. New function,
>> split out from ...
>> (vect_analyze_data_ref_dependence): ... here. Simplify.
>> (vect_check_interleaving): Simplify.
>> (vect_analyze_data_ref_dependences): Likewise. Split out ...
>> (vect_slp_analyze_data_ref_dependences): ... this new function.
>> (dr_group_sort_cmp): New function.
>> (vect_analyze_data_ref_accesses): Compute data-reference groups
>> here instead of in vect_analyze_data_ref_dependence. Use
>> a more efficient algorithm.
>> * tree-vect-slp.c (vect_slp_analyze_bb_1): Use
>> vect_slp_analyze_data_ref_dependences. Call
>> vect_analyze_data_ref_accesses earlier.
>> * tree-vect-loop.c (vect_analyze_loop_2): Likewise.
>> * tree-vectorizer.h (vect_analyze_data_ref_dependences): Adjust.
>> (vect_slp_analyze_data_ref_dependences): New prototype.
>>
>> Index: trunk/gcc/tree-vect-data-refs.c
>> ===================================================================
>> *** trunk.orig/gcc/tree-vect-data-refs.c 2013-02-27 14:53:36.000000000 +0100
>> --- trunk/gcc/tree-vect-data-refs.c 2013-02-27 16:45:58.969861004 +0100
>> *************** vect_get_place_in_interleaving_chain (gi
>> *** 154,394 ****
>> }
>>
>>
>> - /* Function vect_insert_into_interleaving_chain.
>> -
>> - Insert DRA into the interleaving chain of DRB according to DRA's INIT. */
>> -
>> - static void
>> - vect_insert_into_interleaving_chain (struct data_reference *dra,
>> - struct data_reference *drb)
>> - {
>> - gimple prev, next;
>> - tree next_init;
>> - stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
>> - stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
>> -
>> - prev = GROUP_FIRST_ELEMENT (stmtinfo_b);
>> - next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev));
>> - while (next)
>> - {
>> - next_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
>> - if (tree_int_cst_compare (next_init, DR_INIT (dra)) > 0)
>> - {
>> - /* Insert here. */
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev)) = DR_STMT (dra);
>> - GROUP_NEXT_ELEMENT (stmtinfo_a) = next;
>> - return;
>> - }
>> - prev = next;
>> - next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev));
>> - }
>> -
>> - /* We got to the end of the list. Insert here. */
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev)) = DR_STMT (dra);
>> - GROUP_NEXT_ELEMENT (stmtinfo_a) = NULL;
>> - }
>> -
>> -
>> - /* Function vect_update_interleaving_chain.
>> -
>> - For two data-refs DRA and DRB that are a part of a chain interleaved data
>> - accesses, update the interleaving chain. DRB's INIT is smaller than DRA's.
>> -
>> - There are four possible cases:
>> - 1. New stmts - both DRA and DRB are not a part of any chain:
>> - FIRST_DR = DRB
>> - NEXT_DR (DRB) = DRA
>> - 2. DRB is a part of a chain and DRA is not:
>> - no need to update FIRST_DR
>> - no need to insert DRB
>> - insert DRA according to init
>> - 3. DRA is a part of a chain and DRB is not:
>> - if (init of FIRST_DR > init of DRB)
>> - FIRST_DR = DRB
>> - NEXT(FIRST_DR) = previous FIRST_DR
>> - else
>> - insert DRB according to its init
>> - 4. both DRA and DRB are in some interleaving chains:
>> - choose the chain with the smallest init of FIRST_DR
>> - insert the nodes of the second chain into the first one. */
>> -
>> - static void
>> - vect_update_interleaving_chain (struct data_reference *drb,
>> - struct data_reference *dra)
>> - {
>> - stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
>> - stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
>> - tree next_init, init_dra_chain, init_drb_chain;
>> - gimple first_a, first_b;
>> - tree node_init;
>> - gimple node, prev, next, first_stmt;
>> -
>> - /* 1. New stmts - both DRA and DRB are not a part of any chain. */
>> - if (!GROUP_FIRST_ELEMENT (stmtinfo_a) && !GROUP_FIRST_ELEMENT (stmtinfo_b))
>> - {
>> - GROUP_FIRST_ELEMENT (stmtinfo_a) = DR_STMT (drb);
>> - GROUP_FIRST_ELEMENT (stmtinfo_b) = DR_STMT (drb);
>> - GROUP_NEXT_ELEMENT (stmtinfo_b) = DR_STMT (dra);
>> - return;
>> - }
>> -
>> - /* 2. DRB is a part of a chain and DRA is not. */
>> - if (!GROUP_FIRST_ELEMENT (stmtinfo_a) && GROUP_FIRST_ELEMENT (stmtinfo_b))
>> - {
>> - GROUP_FIRST_ELEMENT (stmtinfo_a) = GROUP_FIRST_ELEMENT (stmtinfo_b);
>> - /* Insert DRA into the chain of DRB. */
>> - vect_insert_into_interleaving_chain (dra, drb);
>> - return;
>> - }
>> -
>> - /* 3. DRA is a part of a chain and DRB is not. */
>> - if (GROUP_FIRST_ELEMENT (stmtinfo_a) && !GROUP_FIRST_ELEMENT (stmtinfo_b))
>> - {
>> - gimple old_first_stmt = GROUP_FIRST_ELEMENT (stmtinfo_a);
>> - tree init_old = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (
>> - old_first_stmt)));
>> - gimple tmp;
>> -
>> - if (tree_int_cst_compare (init_old, DR_INIT (drb)) > 0)
>> - {
>> - /* DRB's init is smaller than the init of the stmt previously marked
>> - as the first stmt of the interleaving chain of DRA. Therefore, we
>> - update FIRST_STMT and put DRB in the head of the list. */
>> - GROUP_FIRST_ELEMENT (stmtinfo_b) = DR_STMT (drb);
>> - GROUP_NEXT_ELEMENT (stmtinfo_b) = old_first_stmt;
>> -
>> - /* Update all the stmts in the list to point to the new FIRST_STMT. */
>> - tmp = old_first_stmt;
>> - while (tmp)
>> - {
>> - GROUP_FIRST_ELEMENT (vinfo_for_stmt (tmp)) = DR_STMT (drb);
>> - tmp = GROUP_NEXT_ELEMENT (vinfo_for_stmt (tmp));
>> - }
>> - }
>> - else
>> - {
>> - /* Insert DRB in the list of DRA. */
>> - vect_insert_into_interleaving_chain (drb, dra);
>> - GROUP_FIRST_ELEMENT (stmtinfo_b) = GROUP_FIRST_ELEMENT (stmtinfo_a);
>> - }
>> - return;
>> - }
>> -
>> - /* 4. both DRA and DRB are in some interleaving chains. */
>> - first_a = GROUP_FIRST_ELEMENT (stmtinfo_a);
>> - first_b = GROUP_FIRST_ELEMENT (stmtinfo_b);
>> - if (first_a == first_b)
>> - return;
>> - init_dra_chain = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_a)));
>> - init_drb_chain = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_b)));
>> -
>> - if (tree_int_cst_compare (init_dra_chain, init_drb_chain) > 0)
>> - {
>> - /* Insert the nodes of DRA chain into the DRB chain.
>> - After inserting a node, continue from this node of the DRB chain (don't
>> - start from the beginning. */
>> - node = GROUP_FIRST_ELEMENT (stmtinfo_a);
>> - prev = GROUP_FIRST_ELEMENT (stmtinfo_b);
>> - first_stmt = first_b;
>> - }
>> - else
>> - {
>> - /* Insert the nodes of DRB chain into the DRA chain.
>> - After inserting a node, continue from this node of the DRA chain (don't
>> - start from the beginning. */
>> - node = GROUP_FIRST_ELEMENT (stmtinfo_b);
>> - prev = GROUP_FIRST_ELEMENT (stmtinfo_a);
>> - first_stmt = first_a;
>> - }
>> -
>> - while (node)
>> - {
>> - node_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (node)));
>> - next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev));
>> - while (next)
>> - {
>> - next_init = DR_INIT (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
>> - if (tree_int_cst_compare (next_init, node_init) > 0)
>> - {
>> - /* Insert here. */
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev)) = node;
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (node)) = next;
>> - prev = node;
>> - break;
>> - }
>> - prev = next;
>> - next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev));
>> - }
>> - if (!next)
>> - {
>> - /* We got to the end of the list. Insert here. */
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (prev)) = node;
>> - GROUP_NEXT_ELEMENT (vinfo_for_stmt (node)) = NULL;
>> - prev = node;
>> - }
>> - GROUP_FIRST_ELEMENT (vinfo_for_stmt (node)) = first_stmt;
>> - node = GROUP_NEXT_ELEMENT (vinfo_for_stmt (node));
>> - }
>> - }
>> -
>> - /* Check dependence between DRA and DRB for basic block vectorization.
>> - If the accesses share same bases and offsets, we can compare their initial
>> - constant offsets to decide whether they differ or not. In case of a read-
>> - write dependence we check that the load is before the store to ensure that
>> - vectorization will not change the order of the accesses. */
>> -
>> - static bool
>> - vect_drs_dependent_in_basic_block (struct data_reference *dra,
>> - struct data_reference *drb)
>> - {
>> - HOST_WIDE_INT type_size_a, type_size_b, init_a, init_b;
>> - gimple earlier_stmt;
>> -
>> - /* We only call this function for pairs of loads and stores, but we verify
>> - it here. */
>> - if (DR_IS_READ (dra) == DR_IS_READ (drb))
>> - {
>> - if (DR_IS_READ (dra))
>> - return false;
>> - else
>> - return true;
>> - }
>> -
>> - /* Check that the data-refs have same bases and offsets. If not, we can't
>> - determine if they are dependent. */
>> - if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> - || !dr_equal_offsets_p (dra, drb))
>> - return true;
>> -
>> - /* Check the types. */
>> - type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
>> - type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
>> -
>> - if (type_size_a != type_size_b
>> - || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
>> - TREE_TYPE (DR_REF (drb))))
>> - return true;
>> -
>> - init_a = TREE_INT_CST_LOW (DR_INIT (dra));
>> - init_b = TREE_INT_CST_LOW (DR_INIT (drb));
>> -
>> - /* Two different locations - no dependence. */
>> - if (init_a != init_b)
>> - return false;
>> -
>> - /* We have a read-write dependence. Check that the load is before the store.
>> - When we vectorize basic blocks, vector load can be only before
>> - corresponding scalar load, and vector store can be only after its
>> - corresponding scalar store. So the order of the acceses is preserved in
>> - case the load is before the store. */
>> - earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
>> - if (DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
>> - return false;
>> -
>> - return true;
>> - }
>> -
>> -
>> /* Function vect_check_interleaving.
>>
>> Check if DRA and DRB are a part of interleaving. In case they are, insert
>> --- 154,159 ----
>> *************** static bool
>> *** 398,479 ****
>> vect_check_interleaving (struct data_reference *dra,
>> struct data_reference *drb)
>> {
>> ! HOST_WIDE_INT type_size_a, type_size_b, diff_mod_size, step, init_a, init_b;
>>
>> ! /* Check that the data-refs have same first location (except init) and they
>> ! are both either store or load (not load and store). */
>> if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> || !dr_equal_offsets_p (dra, drb)
>> - || !tree_int_cst_compare (DR_INIT (dra), DR_INIT (drb))
>> || DR_IS_READ (dra) != DR_IS_READ (drb))
>> ! return false;
>>
>> ! /* Check:
>> ! 1. data-refs are of the same type
>> ! 2. their steps are equal
>> ! 3. the step (if greater than zero) is greater than the difference between
>> ! data-refs' inits. */
>> type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
>> type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
>> -
>> if (type_size_a != type_size_b
>> ! || tree_int_cst_compare (DR_STEP (dra), DR_STEP (drb))
>> ! || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
>> ! TREE_TYPE (DR_REF (drb))))
>> return false;
>>
>> init_a = TREE_INT_CST_LOW (DR_INIT (dra));
>> init_b = TREE_INT_CST_LOW (DR_INIT (drb));
>> step = TREE_INT_CST_LOW (DR_STEP (dra));
>>
>> ! if (init_a > init_b)
>> ! {
>> ! /* If init_a == init_b + the size of the type * k, we have an interleaving,
>> ! and DRB is accessed before DRA. */
>> ! diff_mod_size = (init_a - init_b) % type_size_a;
>> !
>> ! if (step && (init_a - init_b) > step)
>> ! return false;
>>
>> ! if (diff_mod_size == 0)
>> ! {
>> ! vect_update_interleaving_chain (drb, dra);
>> ! if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "Detected interleaving ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_NOTE, " and ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
>> ! }
>> ! return true;
>> ! }
>> ! }
>> ! else
>> ! {
>> ! /* If init_b == init_a + the size of the type * k, we have an
>> ! interleaving, and DRA is accessed before DRB. */
>> ! diff_mod_size = (init_b - init_a) % type_size_a;
>>
>> ! if (step && (init_b - init_a) > step)
>> ! return false;
>>
>> ! if (diff_mod_size == 0)
>> ! {
>> ! vect_update_interleaving_chain (dra, drb);
>> ! if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "Detected interleaving ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_NOTE, " and ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
>> ! }
>> ! return true;
>> ! }
>> }
>>
>> ! return false;
>> }
>>
>> /* Check if data references pointed by DR_I and DR_J are same or
>> --- 163,220 ----
>> vect_check_interleaving (struct data_reference *dra,
>> struct data_reference *drb)
>> {
>> ! HOST_WIDE_INT type_size_a, type_size_b, step, init_a, init_b;
>>
>> ! /* The caller has ensured that the data-refs have same first location
>> ! (except init) and they are both either store or load. */
>> if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> || !dr_equal_offsets_p (dra, drb)
>> || DR_IS_READ (dra) != DR_IS_READ (drb))
>> ! gcc_unreachable ();
>>
>> ! /* The caller has ensured type sizes and steps are equal. */
>> type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
>> type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
>> if (type_size_a != type_size_b
>> ! || tree_int_cst_compare (DR_STEP (dra), DR_STEP (drb)) != 0)
>> ! gcc_unreachable ();
>> !
>> ! /* Do not place the same access in the interleaving chain twice. */
>> ! if (tree_int_cst_compare (DR_INIT (dra), DR_INIT (drb)) == 0)
>> ! return false;
>> !
>> ! /* Check the types are compatible. */
>> ! if (!types_compatible_p (TREE_TYPE (DR_REF (dra)),
>> ! TREE_TYPE (DR_REF (drb))))
>> return false;
>>
>> init_a = TREE_INT_CST_LOW (DR_INIT (dra));
>> init_b = TREE_INT_CST_LOW (DR_INIT (drb));
>> step = TREE_INT_CST_LOW (DR_STEP (dra));
>>
>> ! /* The caller has ensured that DR_INIT (dra) <= DR_INIT (drb). */
>> ! gcc_assert (init_a < init_b);
>>
>> ! /* If init_b == init_a + the size of the type * k, we have an
>> ! interleaving, and DRA is accessed before DRB. */
>> ! if ((init_b - init_a) % type_size_a != 0)
>> ! return false;
>>
>> ! /* The step (if not zero) is greater than the difference between
>> ! data-refs' inits. This splits groups into suitable sizes. */
>> ! if (step != 0 && step <= (init_b - init_a))
>> ! return false;
>>
>> ! if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "Detected interleaving ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_NOTE, " and ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
>> }
>>
>> ! return true;
>> }
>>
>> /* Check if data references pointed by DR_I and DR_J are same or
>> *************** vect_analyze_data_ref_dependence (struct
>> *** 578,584 ****
>> loop_vec_info loop_vinfo, int *max_vf)
>> {
>> unsigned int i;
>> ! struct loop *loop = NULL;
>> struct data_reference *dra = DDR_A (ddr);
>> struct data_reference *drb = DDR_B (ddr);
>> stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
>> --- 319,325 ----
>> loop_vec_info loop_vinfo, int *max_vf)
>> {
>> unsigned int i;
>> ! struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
>> struct data_reference *dra = DDR_A (ddr);
>> struct data_reference *drb = DDR_B (ddr);
>> stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
>> *************** vect_analyze_data_ref_dependence (struct
>> *** 586,688 ****
>> lambda_vector dist_v;
>> unsigned int loop_depth;
>>
>> ! /* Don't bother to analyze statements marked as unvectorizable. */
>> if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
>> || !STMT_VINFO_VECTORIZABLE (stmtinfo_b))
>> ! return false;
>>
>> if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
>> ! {
>> ! /* Independent data accesses. */
>> ! vect_check_interleaving (dra, drb);
>> ! return false;
>> ! }
>> !
>> ! if (loop_vinfo)
>> ! loop = LOOP_VINFO_LOOP (loop_vinfo);
>>
>> ! if ((DR_IS_READ (dra) && DR_IS_READ (drb) && loop_vinfo) || dra == drb)
>> return false;
>>
>> if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
>> {
>> - gimple earlier_stmt;
>> -
>> - if (loop_vinfo)
>> - {
>> - if (dump_enabled_p ())
>> - {
>> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> - "versioning for alias required: "
>> - "can't determine dependence between ");
>> - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
>> - DR_REF (dra));
>> - dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
>> - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
>> - DR_REF (drb));
>> - }
>> -
>> - /* Add to list of ddrs that need to be tested at run-time. */
>> - return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
>> - }
>> -
>> - /* When vectorizing a basic block unknown depnedence can still mean
>> - grouped access. */
>> - if (vect_check_interleaving (dra, drb))
>> - return false;
>> -
>> - /* Read-read is OK (we need this check here, after checking for
>> - interleaving). */
>> - if (DR_IS_READ (dra) && DR_IS_READ (drb))
>> - return false;
>> -
>> - if (dump_enabled_p ())
>> - {
>> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> - "can't determine dependence between ");
>> - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
>> - dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
>> - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
>> - }
>> -
>> - /* We do not vectorize basic blocks with write-write dependencies. */
>> - if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
>> - return true;
>> -
>> - /* Check that it's not a load-after-store dependence. */
>> - earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
>> - if (DR_IS_WRITE (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
>> - return true;
>> -
>> - return false;
>> - }
>> -
>> - /* Versioning for alias is not yet supported for basic block SLP, and
>> - dependence distance is unapplicable, hence, in case of known data
>> - dependence, basic block vectorization is impossible for now. */
>> - if (!loop_vinfo)
>> - {
>> - if (dra != drb && vect_check_interleaving (dra, drb))
>> - return false;
>> -
>> if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "determined dependence between ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_NOTE, " and ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
>> ! }
>> !
>> ! /* Do not vectorize basic blcoks with write-write dependences. */
>> ! if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
>> ! return true;
>>
>> ! /* Check if this dependence is allowed in basic block vectorization. */
>> ! return vect_drs_dependent_in_basic_block (dra, drb);
>> }
>>
>> ! /* Loop-based vectorization and known data dependence. */
>> if (DDR_NUM_DIST_VECTS (ddr) == 0)
>> {
>> if (dump_enabled_p ())
>> --- 327,365 ----
>> lambda_vector dist_v;
>> unsigned int loop_depth;
>>
>> ! /* In loop analysis all data references should be vectorizable. */
>> if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
>> || !STMT_VINFO_VECTORIZABLE (stmtinfo_b))
>> ! gcc_unreachable ();
>>
>> + /* Independent data accesses. */
>> if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
>> ! return false;
>>
>> ! if (dra == drb
>> ! || (DR_IS_READ (dra) && DR_IS_READ (drb)))
>> return false;
>>
>> + /* Unknown data dependence. */
>> if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
>> {
>> if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> ! "versioning for alias required: "
>> ! "can't determine dependence between ");
>> ! dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
>> ! DR_REF (dra));
>> ! dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
>> ! dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
>> ! DR_REF (drb));
>> ! }
>>
>> ! /* Add to list of ddrs that need to be tested at run-time. */
>> ! return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
>> }
>>
>> ! /* Known data dependence. */
>> if (DDR_NUM_DIST_VECTS (ddr) == 0)
>> {
>> if (dump_enabled_p ())
>> *************** vect_analyze_data_ref_dependence (struct
>> *** 719,725 ****
>> }
>>
>> /* For interleaving, mark that there is a read-write dependency if
>> ! necessary. We check before that one of the data-refs is store. */
>> if (DR_IS_READ (dra))
>> GROUP_READ_WRITE_DEPENDENCE (stmtinfo_a) = true;
>> else
>> --- 396,402 ----
>> }
>>
>> /* For interleaving, mark that there is a read-write dependency if
>> ! necessary. We check before that one of the data-refs is store. */
>> if (DR_IS_READ (dra))
>> GROUP_READ_WRITE_DEPENDENCE (stmtinfo_a) = true;
>> else
>> *************** vect_analyze_data_ref_dependence (struct
>> *** 787,821 ****
>> the maximum vectorization factor the data dependences allow. */
>>
>> bool
>> ! vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
>> ! bb_vec_info bb_vinfo, int *max_vf)
>> {
>> unsigned int i;
>> - vec<ddr_p> ddrs = vNULL;
>> struct data_dependence_relation *ddr;
>>
>> if (dump_enabled_p ())
>> dump_printf_loc (MSG_NOTE, vect_location,
>> ! "=== vect_analyze_dependences ===");
>> ! if (loop_vinfo)
>> {
>> ! if (!compute_all_dependences (LOOP_VINFO_DATAREFS (loop_vinfo),
>> ! &LOOP_VINFO_DDRS (loop_vinfo),
>> ! LOOP_VINFO_LOOP_NEST (loop_vinfo), true))
>> ! return false;
>> ! ddrs = LOOP_VINFO_DDRS (loop_vinfo);
>> }
>> ! else
>> {
>> ! if (!compute_all_dependences (BB_VINFO_DATAREFS (bb_vinfo),
>> ! &BB_VINFO_DDRS (bb_vinfo),
>> ! vNULL, true))
>> ! return false;
>> ! ddrs = BB_VINFO_DDRS (bb_vinfo);
>> }
>>
>> ! FOR_EACH_VEC_ELT (ddrs, i, ddr)
>> ! if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
>> return false;
>>
>> return true;
>> --- 464,624 ----
>> the maximum vectorization factor the data dependences allow. */
>>
>> bool
>> ! vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo, int *max_vf)
>> {
>> unsigned int i;
>> struct data_dependence_relation *ddr;
>>
>> if (dump_enabled_p ())
>> dump_printf_loc (MSG_NOTE, vect_location,
>> ! "=== vect_analyze_data_ref_dependences ===");
>> !
>> ! if (!compute_all_dependences (LOOP_VINFO_DATAREFS (loop_vinfo),
>> ! &LOOP_VINFO_DDRS (loop_vinfo),
>> ! LOOP_VINFO_LOOP_NEST (loop_vinfo), true))
>> ! return false;
>> !
>> ! FOR_EACH_VEC_ELT (LOOP_VINFO_DDRS (loop_vinfo), i, ddr)
>> ! if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
>> ! return false;
>> !
>> ! return true;
>> ! }
>> !
>> !
>> ! /* Function vect_slp_analyze_data_ref_dependence.
>> !
>> ! Return TRUE if there (might) exist a dependence between a memory-reference
>> ! DRA and a memory-reference DRB. When versioning for alias may check a
>> ! dependence at run-time, return FALSE. Adjust *MAX_VF according to
>> ! the data dependence. */
>> !
>> ! static bool
>> ! vect_slp_analyze_data_ref_dependence (struct data_dependence_relation *ddr)
>> ! {
>> ! struct data_reference *dra = DDR_A (ddr);
>> ! struct data_reference *drb = DDR_B (ddr);
>> !
>> ! /* We need to check dependences of statements marked as unvectorizable
>> ! as well, they still can prohibit vectorization. */
>> !
>> ! /* Independent data accesses. */
>> ! if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
>> ! return false;
>> !
>> ! if (dra == drb)
>> ! return false;
>> !
>> ! /* Read-read is OK. */
>> ! if (DR_IS_READ (dra) && DR_IS_READ (drb))
>> ! return false;
>> !
>> ! /* Unknown data dependence. */
>> ! if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
>> {
>> ! gimple earlier_stmt;
>> !
>> ! if (dump_enabled_p ())
>> ! {
>> ! dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> ! "can't determine dependence between ");
>> ! dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_MISSED_OPTIMIZATION, " and ");
>> ! dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
>> ! }
>> !
>> ! /* We do not vectorize basic blocks with write-write dependencies. */
>> ! if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
>> ! return true;
>> !
>> ! /* Check that it's not a load-after-store dependence. */
>> ! earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
>> ! if (DR_IS_WRITE (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
>> ! return true;
>> !
>> ! return false;
>> }
>> !
>> ! if (dump_enabled_p ())
>> {
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "determined dependence between ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dra));
>> ! dump_printf (MSG_NOTE, " and ");
>> ! dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb));
>> }
>>
>> ! /* Do not vectorize basic blocks with write-write dependences. */
>> ! if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
>> ! return true;
>> !
>> ! /* Check dependence between DRA and DRB for basic block vectorization.
>> ! If the accesses share same bases and offsets, we can compare their initial
>> ! constant offsets to decide whether they differ or not. In case of a read-
>> ! write dependence we check that the load is before the store to ensure that
>> ! vectorization will not change the order of the accesses. */
>> !
>> ! HOST_WIDE_INT type_size_a, type_size_b, init_a, init_b;
>> ! gimple earlier_stmt;
>> !
>> ! /* Check that the data-refs have same bases and offsets. If not, we can't
>> ! determine if they are dependent. */
>> ! if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> ! || !dr_equal_offsets_p (dra, drb))
>> ! return true;
>> !
>> ! /* Check the types. */
>> ! type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
>> ! type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
>> !
>> ! if (type_size_a != type_size_b
>> ! || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
>> ! TREE_TYPE (DR_REF (drb))))
>> ! return true;
>> !
>> ! init_a = TREE_INT_CST_LOW (DR_INIT (dra));
>> ! init_b = TREE_INT_CST_LOW (DR_INIT (drb));
>> !
>> ! /* Two different locations - no dependence. */
>> ! if (init_a != init_b)
>> ! return false;
>> !
>> ! /* We have a read-write dependence. Check that the load is before the store.
>> ! When we vectorize basic blocks, vector load can be only before
>> ! corresponding scalar load, and vector store can be only after its
>> ! corresponding scalar store. So the order of the acceses is preserved in
>> ! case the load is before the store. */
>> ! earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
>> ! if (DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
>> ! return false;
>> !
>> ! return true;
>> ! }
>> !
>> !
>> ! /* Function vect_analyze_data_ref_dependences.
>> !
>> ! Examine all the data references in the basic-block, and make sure there
>> ! do not exist any data dependences between them. Set *MAX_VF according to
>> ! the maximum vectorization factor the data dependences allow. */
>> !
>> ! bool
>> ! vect_slp_analyze_data_ref_dependences (bb_vec_info bb_vinfo)
>> ! {
>> ! struct data_dependence_relation *ddr;
>> ! unsigned int i;
>> !
>> ! if (dump_enabled_p ())
>> ! dump_printf_loc (MSG_NOTE, vect_location,
>> ! "=== vect_slp_analyze_data_ref_dependences ===");
>> !
>> ! if (!compute_all_dependences (BB_VINFO_DATAREFS (bb_vinfo),
>> ! &BB_VINFO_DDRS (bb_vinfo),
>> ! vNULL, true))
>> ! return false;
>> !
>> ! FOR_EACH_VEC_ELT (BB_VINFO_DDRS (bb_vinfo), i, ddr)
>> ! if (vect_slp_analyze_data_ref_dependence (ddr))
>> return false;
>>
>> return true;
>> *************** vect_analyze_data_ref_access (struct dat
>> *** 2567,2572 ****
>> --- 2370,2425 ----
>> return vect_analyze_group_access (dr);
>> }
>>
>> + /* Compare two data-references DRA and DRB to group them into chunks
>> + suitable for grouping. */
>> +
>> + static int
>> + dr_group_sort_cmp (const void *dra_, const void *drb_)
>> + {
>> + data_reference_p dra = *(data_reference_p *)const_cast<void *>(dra_);
>> + data_reference_p drb = *(data_reference_p *)const_cast<void *>(drb_);
>> + int cmp;
>> +
>> + /* Stabilize sort. */
>> + if (dra == drb)
>> + return 0;
>> +
>> + /* Ordering of DRs with unequal base or offset according to a hash. */
>> + if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> + || !dr_equal_offsets_p (dra, drb))
>> + {
>> + hashval_t h1
>> + = iterative_hash_expr (DR_BASE_ADDRESS (dra),
>> + iterative_hash_expr (DR_OFFSET (dra), 0));
>> + hashval_t h2
>> + = iterative_hash_expr (DR_BASE_ADDRESS (drb),
>> + iterative_hash_expr (DR_OFFSET (drb), 0));
>> + if (h1 == h2)
>> + gcc_unreachable ();
>> + return h1 < h2 ? -1 : 1;
>> + }
>> +
>> + /* Else put reads first. */
>> + if (DR_IS_READ (dra) != DR_IS_READ (drb))
>> + return DR_IS_READ (dra) ? -1 : 1;
>> +
>> + /* Then sort after access size. */
>> + cmp = tree_int_cst_compare (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))),
>> + TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
>> + if (cmp != 0)
>> + return cmp;
>> +
>> + /* And after step. */
>> + cmp = tree_int_cst_compare (DR_STEP (dra), DR_STEP (drb));
>> + if (cmp != 0)
>> + return cmp;
>> +
>> + /* Then sort after DR_INIT. In case of identical DRs sort after stmt UID. */
>> + cmp = tree_int_cst_compare (DR_INIT (dra), DR_INIT (drb));
>> + if (cmp == 0)
>> + return gimple_uid (DR_STMT (dra)) < gimple_uid (DR_STMT (drb)) ? -1 : 1;
>> + return cmp;
>> + }
>>
>> /* Function vect_analyze_data_ref_accesses.
>>
>> *************** vect_analyze_data_ref_accesses (loop_vec
>> *** 2593,2598 ****
>> --- 2446,2497 ----
>> else
>> datarefs = BB_VINFO_DATAREFS (bb_vinfo);
>>
>> + if (datarefs.is_empty ())
>> + return true;
>> +
>> + /* Sort the array of datarefs to make building the interleaving chains
>> + linear. */
>> + qsort (datarefs.address(), datarefs.length (),
>> + sizeof (data_reference_p), dr_group_sort_cmp);
>> +
>> + /* Build the interleaving chains. */
>> + for (i = 0; i < datarefs.length () - 1;)
>> + {
>> + data_reference_p dra = datarefs[i];
>> + stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
>> + stmt_vec_info lastinfo = NULL;
>> + for (i = i + 1; i < datarefs.length (); ++i)
>> + {
>> + data_reference_p drb = datarefs[i];
>> + stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
>> + /* Check that the data-refs have same first location (except init)
>> + and they are both either store or load (not load and store).
>> + Check that the data-refs have the same size and step. */
>> + if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> + || !dr_equal_offsets_p (dra, drb)
>> + || DR_IS_READ (dra) != DR_IS_READ (drb)
>> + || tree_int_cst_compare (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))),
>> + TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))))
>> + || tree_int_cst_compare (DR_STEP (dra), DR_STEP (drb)))
>> + break;
>> + /* ??? Imperfect sorting (non-compatible types, non-modulo
>> + accesses, same accesses) can lead to a group to be artificially
>> + split here as we don't just skip over those. If it really
>> + matters we can push those to a worklist and re-iterate
>> + over them. The we can just skip ahead to the next DR here. */
>> + if (!vect_check_interleaving (dra, drb))
>> + break;
>> + if (!GROUP_FIRST_ELEMENT (stmtinfo_a))
>> + {
>> + GROUP_FIRST_ELEMENT (stmtinfo_a) = DR_STMT (dra);
>> + lastinfo = stmtinfo_a;
>> + }
>> + GROUP_FIRST_ELEMENT (stmtinfo_b) = DR_STMT (dra);
>> + GROUP_NEXT_ELEMENT (lastinfo) = DR_STMT (drb);
>> + lastinfo = stmtinfo_b;
>> + }
>> + }
>> +
>> FOR_EACH_VEC_ELT (datarefs, i, dr)
>> if (STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dr)))
>> && !vect_analyze_data_ref_access (dr))
>> Index: trunk/gcc/tree-vect-slp.c
>> ===================================================================
>> *** trunk.orig/gcc/tree-vect-slp.c 2013-02-27 14:53:36.000000000 +0100
>> --- trunk/gcc/tree-vect-slp.c 2013-02-27 14:57:30.977783197 +0100
>> *************** vect_slp_analyze_bb_1 (basic_block bb)
>> *** 2089,2095 ****
>> slp_instance instance;
>> int i;
>> int min_vf = 2;
>> - int max_vf = MAX_VECTORIZATION_FACTOR;
>>
>> bb_vinfo = new_bb_vec_info (bb);
>> if (!bb_vinfo)
>> --- 2089,2094 ----
>> *************** vect_slp_analyze_bb_1 (basic_block bb)
>> *** 2117,2126 ****
>> return NULL;
>> }
>>
>> vect_pattern_recog (NULL, bb_vinfo);
>>
>> ! if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo, &max_vf)
>> ! || min_vf > max_vf)
>> {
>> if (dump_enabled_p ())
>> dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> --- 2116,2135 ----
>> return NULL;
>> }
>>
>> + if (!vect_analyze_data_ref_accesses (NULL, bb_vinfo))
>> + {
>> + if (dump_enabled_p ())
>> + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> + "not vectorized: unhandled data access in "
>> + "basic block.\n");
>> +
>> + destroy_bb_vec_info (bb_vinfo);
>> + return NULL;
>> + }
>> +
>> vect_pattern_recog (NULL, bb_vinfo);
>>
>> ! if (!vect_slp_analyze_data_ref_dependences (bb_vinfo))
>> {
>> if (dump_enabled_p ())
>> dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> *************** vect_slp_analyze_bb_1 (basic_block bb)
>> *** 2140,2156 ****
>>
>> destroy_bb_vec_info (bb_vinfo);
>> return NULL;
>> - }
>> -
>> - if (!vect_analyze_data_ref_accesses (NULL, bb_vinfo))
>> - {
>> - if (dump_enabled_p ())
>> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> - "not vectorized: unhandled data access in "
>> - "basic block.\n");
>> -
>> - destroy_bb_vec_info (bb_vinfo);
>> - return NULL;
>> }
>>
>> /* Check the SLP opportunities in the basic block, analyze and build SLP
>> --- 2149,2154 ----
>> Index: trunk/gcc/tree-vect-loop.c
>> ===================================================================
>> *** trunk.orig/gcc/tree-vect-loop.c 2013-02-27 14:53:36.000000000 +0100
>> --- trunk/gcc/tree-vect-loop.c 2013-02-27 14:57:30.978783208 +0100
>> *************** vect_analyze_loop_2 (loop_vec_info loop_
>> *** 1603,1608 ****
>> --- 1603,1620 ----
>> return false;
>> }
>>
>> + /* Analyze the access patterns of the data-refs in the loop (consecutive,
>> + complex, etc.). FORNOW: Only handle consecutive access pattern. */
>> +
>> + ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
>> + if (!ok)
>> + {
>> + if (dump_enabled_p ())
>> + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> + "bad data access.");
>> + return false;
>> + }
>> +
>> /* Classify all cross-iteration scalar data-flow cycles.
>> Cross-iteration cycles caused by virtual phis are analyzed separately. */
>>
>> *************** vect_analyze_loop_2 (loop_vec_info loop_
>> *** 1626,1632 ****
>> the dependences.
>> FORNOW: fail at the first data dependence that we encounter. */
>>
>> ! ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf);
>> if (!ok
>> || max_vf < min_vf)
>> {
>> --- 1638,1644 ----
>> the dependences.
>> FORNOW: fail at the first data dependence that we encounter. */
>>
>> ! ok = vect_analyze_data_ref_dependences (loop_vinfo, &max_vf);
>> if (!ok
>> || max_vf < min_vf)
>> {
>> *************** vect_analyze_loop_2 (loop_vec_info loop_
>> *** 1664,1681 ****
>> return false;
>> }
>>
>> - /* Analyze the access patterns of the data-refs in the loop (consecutive,
>> - complex, etc.). FORNOW: Only handle consecutive access pattern. */
>> -
>> - ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
>> - if (!ok)
>> - {
>> - if (dump_enabled_p ())
>> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
>> - "bad data access.");
>> - return false;
>> - }
>> -
>> /* Prune the list of ddrs to be tested at run-time by versioning for alias.
>> It is important to call pruning after vect_analyze_data_ref_accesses,
>> since we use grouping information gathered by interleaving analysis. */
>> --- 1676,1681 ----
>> Index: trunk/gcc/tree-vectorizer.h
>> ===================================================================
>> *** trunk.orig/gcc/tree-vectorizer.h 2013-02-27 14:53:36.000000000 +0100
>> --- trunk/gcc/tree-vectorizer.h 2013-02-27 14:57:30.978783208 +0100
>> *************** extern enum dr_alignment_support vect_su
>> *** 914,921 ****
>> (struct data_reference *, bool);
>> extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *,
>> HOST_WIDE_INT *);
>> ! extern bool vect_analyze_data_ref_dependences (loop_vec_info, bb_vec_info,
>> ! int *);
>> extern bool vect_enhance_data_refs_alignment (loop_vec_info);
>> extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
>> extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);
>> --- 914,921 ----
>> (struct data_reference *, bool);
>> extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *,
>> HOST_WIDE_INT *);
>> ! extern bool vect_analyze_data_ref_dependences (loop_vec_info, int *);
>> ! extern bool vect_slp_analyze_data_ref_dependences (bb_vec_info);
>> extern bool vect_enhance_data_refs_alignment (loop_vec_info);
>> extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
>> extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);