This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR81136: ICE from inconsistent DR_MISALIGNMENTs
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Richard Sandiford <richard dot sandiford at linaro dot org>
- Date: Fri, 23 Jun 2017 13:24:23 +0200
- Subject: Re: PR81136: ICE from inconsistent DR_MISALIGNMENTs
- Authentication-results: sourceware.org; auth=none
- References: <87k244z2c5.fsf@linaro.org> <CAFiYyc015ZVKVk0qegFFBhgzkOjSuoC6=iznQzju41uyiW9XtQ@mail.gmail.com>
On Fri, Jun 23, 2017 at 1:19 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Jun 22, 2017 at 1:30 PM, Richard Sandiford
> <richard.sandiford@linaro.org> wrote:
>> The test case triggered this assert in vect_update_misalignment_for_peel:
>>
>> gcc_assert (DR_MISALIGNMENT (dr) / dr_size ==
>> DR_MISALIGNMENT (dr_peel) / dr_peel_size);
>>
>> We knew that the two DRs had the same misalignment at runtime, but when
>> considered in isolation, one data reference guaranteed a higher compile-time
>> base alignment than the other.
>>
>> In the test case this looks like a missed opportunity. Both references
>> are unconditional, so it should be possible to use the highest of the
>> available base alignment guarantees when analyzing each reference.
>> The patch does this.
>>
>> However, as the comment in the patch says, the base alignment guarantees
>> provided by a conditional reference only apply if the reference occurs
>> at least once. In this case it would be legitimate for two references
>> to have the same runtime misalignment and for one reference to provide a
>> stronger compile-time guarantee than the other about what the misalignment
>> actually is. The patch therefore relaxes the assert to handle that case.
>
> Hmm, but you don't actually check whether a reference occurs only conditional,
> do you? You just seem to say that for masked loads/stores the reference
> is conditional (I believe that's not true). But for a loop like
>
> for (;;)
> if (a[i])
> sum += b[j];
>
> you still assume b[j] executes unconditionally?
>
> The vectorizer of course only sees unconditionally executed stmts.
>
> So - I'd simply not add this DR_IS_CONDITIONAL. Did you run into
> any real-world (testsuite) issues without this?
+ for (int i = 0; i < n; ++i)
+ ptr[i] = c[i] ? ((struct s *) (ptr - 1))->array[i] : 0;
+
note that this example shows an if-conversion bug as if-conversion
makes the access to ((struct s *) (ptr - 1))->array[i] unconditional
if it may not trap (or the trap helper doesn't consider alignment-related
traps).
I'm not convinced we should worry ... (ok, I didn't say that).
Richard.
> Note that the assert is to prevent bogus information. Iff we aligned
> DR with base alignment 8 and misalign 3 then if another same-align
> DR has base alignment 16 we can't simply zero its DR_MISALIGNMENT
> as it still can be 8 after aligning DR.
>
> So I think it's wrong to put DRs with differing base-alignment into
> the same-align-refs chain, those should get their DR_MISALIGNMENT
> updated independenlty after peeling.
>
> I'd rather not mix fixing this with the improvement to eventuall use a
> larger align for the other DR if possible.
>
> Thanks,
> Richard.
>
>> Tested on powerpc64-linux-gnu, aarch64-linux-gnu and x86_64-linux-gnu.
>> OK to instal?
>>
>> Richard
>>
>>
>> 2017-06-22 Richard Sandiford <richard.sandiford@linaro.org>
>>
>> gcc/
>> PR tree-optimization/81136
>> * tree-vectorizer.h: Include tree-hash-traits.h.
>> (vec_base_alignments): New typedef.
>> (vec_info): Add a base_alignments field.
>> (vect_compute_base_alignments: Declare.
>> * tree-data-ref.h (data_reference): Add an is_conditional field.
>> (DR_IS_CONDITIONAL): New macro.
>> (create_data_ref): Add an is_conditional argument.
>> * tree-data-ref.c (create_data_ref): Likewise. Use it to initialize
>> the is_conditional field.
>> (data_ref_loc): Add an is_conditional field.
>> (get_references_in_stmt): Set the is_conditional field.
>> (find_data_references_in_stmt): Update call to create_data_ref.
>> (graphite_find_data_references_in_stmt): Likewise.
>> * tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Likewise.
>> * tree-vect-data-refs.c (vect_analyze_data_refs): Likewise.
>> (vect_get_base_address): New function.
>> (vect_compute_base_alignments): Likewise.
>> (vect_compute_base_alignment): Likewise, split out from...
>> (vect_compute_data_ref_alignment): ...here. Use precomputed
>> base alignments. Only compute a new base alignment here if the
>> reference is conditional.
>> (vect_update_misalignment_for_peel): Allow the compile-time
>> DR_MISALIGNMENTs of two references with the same runtime alignment
>> to be different if one of the references is conditional.
>> (vect_find_same_alignment_drs): Compare base addresses instead
>> of base objects.
>> (vect_compute_data_ref_alignment): Call vect_compute_base_alignments.
>> * tree-vect-slp.c (vect_slp_analyze_bb_1): Likewise.
>> (new_bb_vec_info): Initialize base_alignments.
>> * tree-vect-loop.c (new_loop_vec_info): Likewise.
>> * tree-vectorizer.c (vect_destroy_datarefs): Release base_alignments.
>>
>> gcc/testsuite/
>> PR tree-optimization/81136
>> * gcc.dg/vect/pr81136.c: New test.
>>
>> Index: gcc/tree-vectorizer.h
>> ===================================================================
>> --- gcc/tree-vectorizer.h 2017-06-08 08:51:43.347264181 +0100
>> +++ gcc/tree-vectorizer.h 2017-06-22 12:23:21.288421018 +0100
>> @@ -22,6 +22,7 @@ Software Foundation; either version 3, o
>> #define GCC_TREE_VECTORIZER_H
>>
>> #include "tree-data-ref.h"
>> +#include "tree-hash-traits.h"
>> #include "target.h"
>>
>> /* Used for naming of new temporaries. */
>> @@ -84,6 +85,10 @@ struct stmt_info_for_cost {
>>
>> typedef vec<stmt_info_for_cost> stmt_vector_for_cost;
>>
>> +/* Maps base addresses to the largest alignment that we've been able
>> + to calculate for them. */
>> +typedef hash_map<tree_operand_hash, unsigned int> vec_base_alignments;
>> +
>> /************************************************************************
>> SLP
>> ************************************************************************/
>> @@ -156,6 +161,10 @@ struct vec_info {
>> /* All data references. */
>> vec<data_reference_p> datarefs;
>>
>> + /* Maps the base addresses of all data references in DATAREFS to the
>> + largest alignment that we've been able to calculate for them. */
>> + vec_base_alignments base_alignments;
>> +
>> /* All data dependences. */
>> vec<ddr_p> ddrs;
>>
>> @@ -1117,6 +1126,7 @@ extern bool vect_prune_runtime_alias_tes
>> extern bool vect_check_gather_scatter (gimple *, loop_vec_info,
>> gather_scatter_info *);
>> extern bool vect_analyze_data_refs (vec_info *, int *);
>> +extern void vect_compute_base_alignments (vec_info *);
>> extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
>> tree *, gimple_stmt_iterator *,
>> gimple **, bool, bool *,
>> Index: gcc/tree-data-ref.h
>> ===================================================================
>> --- gcc/tree-data-ref.h 2017-06-08 08:51:43.349263895 +0100
>> +++ gcc/tree-data-ref.h 2017-06-22 12:23:21.285421180 +0100
>> @@ -119,6 +119,10 @@ struct data_reference
>> /* True when the data reference is in RHS of a stmt. */
>> bool is_read;
>>
>> + /* True when the data reference is conditional, i.e. if it might not
>> + occur even when the statement runs to completion. */
>> + bool is_conditional;
>> +
>> /* Behavior of the memory reference in the innermost loop. */
>> struct innermost_loop_behavior innermost;
>>
>> @@ -138,6 +142,7 @@ #define DR_ACCESS_FN(DR, I) DR_AC
>> #define DR_NUM_DIMENSIONS(DR) DR_ACCESS_FNS (DR).length ()
>> #define DR_IS_READ(DR) (DR)->is_read
>> #define DR_IS_WRITE(DR) (!DR_IS_READ (DR))
>> +#define DR_IS_CONDITIONAL(DR) (DR)->is_conditional
>> #define DR_BASE_ADDRESS(DR) (DR)->innermost.base_address
>> #define DR_OFFSET(DR) (DR)->innermost.offset
>> #define DR_INIT(DR) (DR)->innermost.init
>> @@ -350,7 +355,8 @@ extern bool graphite_find_data_reference
>> vec<data_reference_p> *);
>> tree find_data_references_in_loop (struct loop *, vec<data_reference_p> *);
>> bool loop_nest_has_data_refs (loop_p loop);
>> -struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple *, bool);
>> +struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple *, bool,
>> + bool);
>> extern bool find_loop_nest (struct loop *, vec<loop_p> *);
>> extern struct data_dependence_relation *initialize_data_dependence_relation
>> (struct data_reference *, struct data_reference *, vec<loop_p>);
>> Index: gcc/tree-data-ref.c
>> ===================================================================
>> --- gcc/tree-data-ref.c 2017-06-08 08:51:43.349263895 +0100
>> +++ gcc/tree-data-ref.c 2017-06-22 12:23:21.284421233 +0100
>> @@ -1053,15 +1053,18 @@ free_data_ref (data_reference_p dr)
>> free (dr);
>> }
>>
>> -/* Analyzes memory reference MEMREF accessed in STMT. The reference
>> - is read if IS_READ is true, write otherwise. Returns the
>> - data_reference description of MEMREF. NEST is the outermost loop
>> - in which the reference should be instantiated, LOOP is the loop in
>> - which the data reference should be analyzed. */
>> +/* Analyze memory reference MEMREF, which is accessed in STMT. The reference
>> + is a read if IS_READ is true, otherwise it is a write. IS_CONDITIONAL
>> + indicates that the reference is conditional, i.e. that it might not
>> + occur every time that STMT runs to completion.
>> +
>> + Return the data_reference description of MEMREF. NEST is the outermost
>> + loop in which the reference should be instantiated, LOOP is the loop
>> + in which the data reference should be analyzed. */
>>
>> struct data_reference *
>> create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt,
>> - bool is_read)
>> + bool is_read, bool is_conditional)
>> {
>> struct data_reference *dr;
>>
>> @@ -1076,6 +1079,7 @@ create_data_ref (loop_p nest, loop_p loo
>> DR_STMT (dr) = stmt;
>> DR_REF (dr) = memref;
>> DR_IS_READ (dr) = is_read;
>> + DR_IS_CONDITIONAL (dr) = is_conditional;
>>
>> dr_analyze_innermost (dr, nest);
>> dr_analyze_indices (dr, nest, loop);
>> @@ -4446,6 +4450,10 @@ struct data_ref_loc
>>
>> /* True if the memory reference is read. */
>> bool is_read;
>> +
>> + /* True if the data reference is conditional, i.e. if it might not
>> + occur even when the statement runs to completion. */
>> + bool is_conditional;
>> };
>>
>>
>> @@ -4512,6 +4520,7 @@ get_references_in_stmt (gimple *stmt, ve
>> {
>> ref.ref = op1;
>> ref.is_read = true;
>> + ref.is_conditional = false;
>> references->safe_push (ref);
>> }
>> }
>> @@ -4539,6 +4548,7 @@ get_references_in_stmt (gimple *stmt, ve
>> type = TREE_TYPE (gimple_call_arg (stmt, 3));
>> if (TYPE_ALIGN (type) != align)
>> type = build_aligned_type (type, align);
>> + ref.is_conditional = true;
>> ref.ref = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0),
>> ptr);
>> references->safe_push (ref);
>> @@ -4558,6 +4568,7 @@ get_references_in_stmt (gimple *stmt, ve
>> {
>> ref.ref = op1;
>> ref.is_read = true;
>> + ref.is_conditional = false;
>> references->safe_push (ref);
>> }
>> }
>> @@ -4571,6 +4582,7 @@ get_references_in_stmt (gimple *stmt, ve
>> {
>> ref.ref = op0;
>> ref.is_read = false;
>> + ref.is_conditional = false;
>> references->safe_push (ref);
>> }
>> return clobbers_memory;
>> @@ -4635,8 +4647,8 @@ find_data_references_in_stmt (struct loo
>>
>> FOR_EACH_VEC_ELT (references, i, ref)
>> {
>> - dr = create_data_ref (nest, loop_containing_stmt (stmt),
>> - ref->ref, stmt, ref->is_read);
>> + dr = create_data_ref (nest, loop_containing_stmt (stmt), ref->ref,
>> + stmt, ref->is_read, ref->is_conditional);
>> gcc_assert (dr != NULL);
>> datarefs->safe_push (dr);
>> }
>> @@ -4665,7 +4677,8 @@ graphite_find_data_references_in_stmt (l
>>
>> FOR_EACH_VEC_ELT (references, i, ref)
>> {
>> - dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read);
>> + dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read,
>> + ref->is_conditional);
>> gcc_assert (dr != NULL);
>> datarefs->safe_push (dr);
>> }
>> Index: gcc/tree-ssa-loop-prefetch.c
>> ===================================================================
>> --- gcc/tree-ssa-loop-prefetch.c 2017-06-07 21:58:55.928557601 +0100
>> +++ gcc/tree-ssa-loop-prefetch.c 2017-06-22 12:23:21.285421180 +0100
>> @@ -1633,7 +1633,7 @@ determine_loop_nest_reuse (struct loop *
>> for (ref = gr->refs; ref; ref = ref->next)
>> {
>> dr = create_data_ref (nest, loop_containing_stmt (ref->stmt),
>> - ref->mem, ref->stmt, !ref->write_p);
>> + ref->mem, ref->stmt, !ref->write_p, false);
>>
>> if (dr)
>> {
>> Index: gcc/tree-vect-data-refs.c
>> ===================================================================
>> --- gcc/tree-vect-data-refs.c 2017-06-08 08:51:43.350263752 +0100
>> +++ gcc/tree-vect-data-refs.c 2017-06-22 12:23:21.286421126 +0100
>> @@ -646,6 +646,102 @@ vect_slp_analyze_instance_dependence (sl
>> return res;
>> }
>>
>> +/* If DR is nested in a loop that is being vectorized, return the base
>> + address in the context of the vectorized loop (rather than the
>> + nested loop). Otherwise return the base address in the context
>> + of the containing statement. */
>> +
>> +static tree
>> +vect_get_base_address (data_reference *dr)
>> +{
>> + gimple *stmt = DR_STMT (dr);
>> + stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
>> + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
>> + struct loop *loop = loop_vinfo != NULL ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
>> + if (loop && nested_in_vect_loop_p (loop, stmt))
>> + return STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
>> + else
>> + return DR_BASE_ADDRESS (dr);
>> +}
>> +
>> +/* Compute and return the alignment of base address BASE_ADDR in DR. */
>> +
>> +static unsigned int
>> +vect_compute_base_alignment (data_reference *dr, tree base_addr)
>> +{
>> + /* To look at the alignment of the base we have to preserve an inner
>> + MEM_REF as that carries the alignment information of the actual
>> + access. */
>> + tree base = DR_REF (dr);
>> + while (handled_component_p (base))
>> + base = TREE_OPERAND (base, 0);
>> + unsigned int base_alignment = 0;
>> + unsigned HOST_WIDE_INT base_bitpos;
>> + get_object_alignment_1 (base, &base_alignment, &base_bitpos);
>> +
>> + /* As data-ref analysis strips the MEM_REF down to its base operand
>> + to form DR_BASE_ADDRESS and adds the offset to DR_INIT we have to
>> + adjust things to make base_alignment valid as the alignment of
>> + DR_BASE_ADDRESS. */
>> + if (TREE_CODE (base) == MEM_REF)
>> + {
>> + /* Note all this only works if DR_BASE_ADDRESS is the same as
>> + MEM_REF operand zero, otherwise DR/SCEV analysis might have factored
>> + in other offsets. We need to rework DR to compute the alingment
>> + of DR_BASE_ADDRESS as long as all information is still available. */
>> + if (operand_equal_p (TREE_OPERAND (base, 0), base_addr, 0))
>> + {
>> + base_bitpos -= mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
>> + base_bitpos &= (base_alignment - 1);
>> + }
>> + else
>> + base_bitpos = BITS_PER_UNIT;
>> + }
>> + if (base_bitpos != 0)
>> + base_alignment = base_bitpos & -base_bitpos;
>> +
>> + /* Also look at the alignment of the base address DR analysis
>> + computed. */
>> + unsigned int base_addr_alignment = get_pointer_alignment (base_addr);
>> + if (base_addr_alignment > base_alignment)
>> + base_alignment = base_addr_alignment;
>> +
>> + return base_alignment;
>> +}
>> +
>> +/* Compute alignments for the base addresses of all datarefs in VINFO. */
>> +
>> +void
>> +vect_compute_base_alignments (vec_info *vinfo)
>> +{
>> + /* If the region we're going to vectorize is reached, all unconditional
>> + data references occur at least once. We can therefore pool the base
>> + alignment guarantees from each unconditional reference. */
>> + data_reference *dr;
>> + unsigned int i;
>> + FOR_EACH_VEC_ELT (vinfo->datarefs, i, dr)
>> + if (!DR_IS_CONDITIONAL (dr))
>> + {
>> + tree base_addr = vect_get_base_address (dr);
>> + unsigned int alignment = vect_compute_base_alignment (dr, base_addr);
>> + bool existed;
>> + unsigned int &entry
>> + = vinfo->base_alignments.get_or_insert (base_addr, &existed);
>> + if (!existed || entry < alignment)
>> + {
>> + entry = alignment;
>> + if (dump_enabled_p ())
>> + {
>> + dump_printf_loc (MSG_NOTE, vect_location,
>> + "setting base alignment for ");
>> + dump_generic_expr (MSG_NOTE, TDF_SLIM, base_addr);
>> + dump_printf (MSG_NOTE, " to %d, based on ", alignment);
>> + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, DR_STMT (dr), 0);
>> + }
>> + }
>> + }
>> +}
>> +
>> /* Function vect_compute_data_ref_alignment
>>
>> Compute the misalignment of the data reference DR.
>> @@ -663,6 +759,7 @@ vect_compute_data_ref_alignment (struct
>> {
>> gimple *stmt = DR_STMT (dr);
>> stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
>> + vec_base_alignments *base_alignments = &stmt_info->vinfo->base_alignments;
>> loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
>> struct loop *loop = NULL;
>> tree ref = DR_REF (dr);
>> @@ -699,6 +796,8 @@ vect_compute_data_ref_alignment (struct
>> {
>> tree step = DR_STEP (dr);
>>
>> + base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
>> + aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
>> if (tree_fits_shwi_p (step)
>> && tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0)
>> {
>> @@ -706,8 +805,6 @@ vect_compute_data_ref_alignment (struct
>> dump_printf_loc (MSG_NOTE, vect_location,
>> "inner step divides the vector-size.\n");
>> misalign = STMT_VINFO_DR_INIT (stmt_info);
>> - aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
>> - base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
>> }
>> else
>> {
>> @@ -738,39 +835,15 @@ vect_compute_data_ref_alignment (struct
>> }
>> }
>>
>> - /* To look at alignment of the base we have to preserve an inner MEM_REF
>> - as that carries alignment information of the actual access. */
>> - base = ref;
>> - while (handled_component_p (base))
>> - base = TREE_OPERAND (base, 0);
>> + /* Calculate the maximum of the pooled base address alignment and the
>> + alignment that we can compute for DR itself. The latter should
>> + already be included in the former for unconditional references. */
>> unsigned int base_alignment = 0;
>> - unsigned HOST_WIDE_INT base_bitpos;
>> - get_object_alignment_1 (base, &base_alignment, &base_bitpos);
>> - /* As data-ref analysis strips the MEM_REF down to its base operand
>> - to form DR_BASE_ADDRESS and adds the offset to DR_INIT we have to
>> - adjust things to make base_alignment valid as the alignment of
>> - DR_BASE_ADDRESS. */
>> - if (TREE_CODE (base) == MEM_REF)
>> - {
>> - /* Note all this only works if DR_BASE_ADDRESS is the same as
>> - MEM_REF operand zero, otherwise DR/SCEV analysis might have factored
>> - in other offsets. We need to rework DR to compute the alingment
>> - of DR_BASE_ADDRESS as long as all information is still available. */
>> - if (operand_equal_p (TREE_OPERAND (base, 0), base_addr, 0))
>> - {
>> - base_bitpos -= mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
>> - base_bitpos &= (base_alignment - 1);
>> - }
>> - else
>> - base_bitpos = BITS_PER_UNIT;
>> - }
>> - if (base_bitpos != 0)
>> - base_alignment = base_bitpos & -base_bitpos;
>> - /* Also look at the alignment of the base address DR analysis
>> - computed. */
>> - unsigned int base_addr_alignment = get_pointer_alignment (base_addr);
>> - if (base_addr_alignment > base_alignment)
>> - base_alignment = base_addr_alignment;
>> + if (DR_IS_CONDITIONAL (dr))
>> + base_alignment = vect_compute_base_alignment (dr, base_addr);
>> + if (unsigned int *entry = base_alignments->get (base_addr))
>> + base_alignment = MAX (base_alignment, *entry);
>> + gcc_assert (base_alignment != 0);
>>
>> if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype)))
>> DR_VECT_AUX (dr)->base_element_aligned = true;
>> @@ -906,8 +979,29 @@ vect_update_misalignment_for_peel (struc
>> {
>> if (current_dr != dr)
>> continue;
>> - gcc_assert (DR_MISALIGNMENT (dr) / dr_size ==
>> - DR_MISALIGNMENT (dr_peel) / dr_peel_size);
>> + /* Any alignment guarantees provided by a reference only apply if
>> + the reference actually occurs. For example, in:
>> +
>> + struct s __attribute__((aligned(32))) {
>> + int misaligner;
>> + int array[N];
>> + };
>> +
>> + int *ptr;
>> + for (int i = 0; i < n; ++i)
>> + ptr[i] = c[i] ? ((struct s *) (ptr - 1))->array[i] : 0;
>> +
>> + we can only assume that ptr is part of a struct s if at least one
>> + c[i] is true. This in turn means that we have a higher base
>> + alignment guarantee for the read from ptr (if it occurs) than for
>> + the write to ptr, and we cannot unconditionally carry the former
>> + over to the latter. We still know that the two address values
>> + have the same misalignment, so if peeling has forced one of them
>> + to be aligned, the other must be too. */
>> + gcc_assert (DR_IS_CONDITIONAL (dr_peel)
>> + || DR_IS_CONDITIONAL (dr)
>> + || (DR_MISALIGNMENT (dr) / dr_size
>> + == DR_MISALIGNMENT (dr_peel) / dr_peel_size));
>> SET_DR_MISALIGNMENT (dr, 0);
>> return;
>> }
>> @@ -2117,8 +2211,7 @@ vect_find_same_alignment_drs (struct dat
>> if (dra == drb)
>> return;
>>
>> - if (!operand_equal_p (DR_BASE_OBJECT (dra), DR_BASE_OBJECT (drb),
>> - OEP_ADDRESS_OF)
>> + if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
>> || !operand_equal_p (DR_OFFSET (dra), DR_OFFSET (drb), 0)
>> || !operand_equal_p (DR_STEP (dra), DR_STEP (drb), 0))
>> return;
>> @@ -2176,6 +2269,7 @@ vect_analyze_data_refs_alignment (loop_v
>> vec<data_reference_p> datarefs = vinfo->datarefs;
>> struct data_reference *dr;
>>
>> + vect_compute_base_alignments (vinfo);
>> FOR_EACH_VEC_ELT (datarefs, i, dr)
>> {
>> stmt_vec_info stmt_info = vinfo_for_stmt (DR_STMT (dr));
>> @@ -3374,7 +3468,8 @@ vect_analyze_data_refs (vec_info *vinfo,
>> {
>> struct data_reference *newdr
>> = create_data_ref (NULL, loop_containing_stmt (stmt),
>> - DR_REF (dr), stmt, maybe_scatter ? false : true);
>> + DR_REF (dr), stmt, !maybe_scatter,
>> + DR_IS_CONDITIONAL (dr));
>> gcc_assert (newdr != NULL && DR_REF (newdr));
>> if (DR_BASE_ADDRESS (newdr)
>> && DR_OFFSET (newdr)
>> Index: gcc/tree-vect-slp.c
>> ===================================================================
>> --- gcc/tree-vect-slp.c 2017-06-07 21:58:56.336475882 +0100
>> +++ gcc/tree-vect-slp.c 2017-06-22 12:23:21.288421018 +0100
>> @@ -2367,6 +2367,7 @@ new_bb_vec_info (gimple_stmt_iterator re
>> gimple_stmt_iterator gsi;
>>
>> res = (bb_vec_info) xcalloc (1, sizeof (struct _bb_vec_info));
>> + new (&res->base_alignments) vec_base_alignments ();
>> res->kind = vec_info::bb;
>> BB_VINFO_BB (res) = bb;
>> res->region_begin = region_begin;
>> @@ -2741,6 +2742,8 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>> return NULL;
>> }
>>
>> + vect_compute_base_alignments (bb_vinfo);
>> +
>> /* Analyze and verify the alignment of data references and the
>> dependence in the SLP instances. */
>> for (i = 0; BB_VINFO_SLP_INSTANCES (bb_vinfo).iterate (i, &instance); )
>> Index: gcc/tree-vect-loop.c
>> ===================================================================
>> --- gcc/tree-vect-loop.c 2017-06-22 12:22:57.734313143 +0100
>> +++ gcc/tree-vect-loop.c 2017-06-22 12:23:21.287421072 +0100
>> @@ -1157,6 +1157,7 @@ new_loop_vec_info (struct loop *loop)
>> LOOP_VINFO_VECT_FACTOR (res) = 0;
>> LOOP_VINFO_LOOP_NEST (res) = vNULL;
>> LOOP_VINFO_DATAREFS (res) = vNULL;
>> + new (&res->base_alignments) vec_base_alignments ();
>> LOOP_VINFO_DDRS (res) = vNULL;
>> LOOP_VINFO_UNALIGNED_DR (res) = NULL;
>> LOOP_VINFO_MAY_MISALIGN_STMTS (res) = vNULL;
>> Index: gcc/tree-vectorizer.c
>> ===================================================================
>> --- gcc/tree-vectorizer.c 2017-06-22 12:22:57.732313220 +0100
>> +++ gcc/tree-vectorizer.c 2017-06-22 12:23:21.288421018 +0100
>> @@ -370,6 +370,8 @@ vect_destroy_datarefs (vec_info *vinfo)
>> }
>>
>> free_data_refs (vinfo->datarefs);
>> +
>> + vinfo->base_alignments.~vec_base_alignments ();
>> }
>>
>> /* A helper function to free scev and LOOP niter information, as well as
>> Index: gcc/testsuite/gcc.dg/vect/pr81136.c
>> ===================================================================
>> --- /dev/null 2017-06-22 07:43:14.805493307 +0100
>> +++ gcc/testsuite/gcc.dg/vect/pr81136.c 2017-06-22 12:23:21.283421287 +0100
>> @@ -0,0 +1,16 @@
>> +/* { dg-do compile } */
>> +
>> +struct __attribute__((aligned (32)))
>> +{
>> + char misaligner;
>> + int foo[100];
>> + int bar[100];
>> +} *a;
>> +
>> +void
>> +fn1 (int n)
>> +{
>> + int *b = a->foo;
>> + for (int i = 0; i < n; i++)
>> + a->bar[i] = b[i];
>> +}