On Fri, 6 Jun 2025, Pengfei Li wrote:

> Current GCC uses either peeling or versioning, but not in combination,
> to handle unaligned data references (DRs) during vectorization. This
> limitation causes some loops with early break to fall back to scalar
> code at runtime.
> 
> Consider the following loop with DRs in its early break condition:
> 
>       for (int i = start; i < end; i++) {
>         if (a[i] == b[i])
>           break;
>         count++;
>       }
> 
> In the loop, references to a[] and b[] need to be strictly aligned for
> vectorization because speculative reads that may cross page boundaries
> are not allowed. Current GCC does versioning for this loop by creating a
> runtime check like:
> 
>       ((&a[start] | &b[start]) & mask) == 0
> 
> to see if two initial addresses both have lower bits zeros. If above
> runtime check fails, the loop will fall back to scalar code. However,
> it's often possible that DRs are all unaligned at the beginning but they
> become all aligned after a few loop iterations. We call this situation
> DRs being "mutually aligned".
> 
> This patch enables combined peeling and versioning to avoid loops with
> mutually aligned DRs falling back to scalar code. Specifically, the
> function vect_peeling_supportable is updated in this patch to return a
> three-state enum indicating how peeling can make all unsupportable DRs
> aligned. In addition to previous true/false return values, a new state
> peeling_maybe_supported is used to indicate that peeling may be able to
> make these DRs aligned but we are not sure about it at compile time. In
> this case, peeling should be combined with versioning so that a runtime
> check will be generated to guard the peeled vectorized loop.
> 
> A new type of runtime check is also introduced for combined peeling and
> versioning. It's enabled when LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT is true.
> The new check tests if all DRs recorded in LOOP_VINFO_MAY_MISALIGN_STMTS
> have the same lower address bits. For above loop case, the new test will
> generate an XOR between two addresses, like:
> 
>       ((&a[start] ^ &b[start]) & mask) == 0
> 
> Therefore, if a and b have the same alignment step (element size) and
> the same offset from an alignment boundary, a peeled vectorized loop
> will run. This new runtime check also works for >2 DRs, with the LHS
> expression being:
> 
>       ((a1 ^ a2) | (a2 ^ a3) | (a3 ^ a4) | ... | (an-1 ^ an)) & mask
> 
> where ai is the address of i'th DR.
> 
> This patch is bootstrapped and regression tested on x86_64-linux-gnu,
> arm-linux-gnueabihf and aarch64-linux-gnu.

Thanks for working on this.

The patch is OK.

Thanks,
Richard.


> gcc/ChangeLog:
> 
>       * tree-vect-data-refs.cc (vect_peeling_supportable): Return new
>       enum values to indicate if combined peeling and versioning can
>       potentially support vectorization.
>       (vect_enhance_data_refs_alignment): Support combined peeling and
>       versioning in vectorization analysis.
>       * tree-vect-loop-manip.cc (vect_create_cond_for_align_checks):
>       Add a new type of runtime check for mutually aligned DRs.
>       * tree-vect-loop.cc (_loop_vec_info::_loop_vec_info): Set
>       default value of allow_mutual_alignment in the initializer list.
>       * tree-vectorizer.h (enum peeling_support): Define type of
>       peeling support for function vect_peeling_supportable.
>       (LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT): New access macro.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/vect/vect-early-break_133_pfa6.c: Adjust test.
> ---
>  .../gcc.dg/vect/vect-early-break_133_pfa6.c   |   2 +-
>  gcc/tree-vect-data-refs.cc                    | 168 ++++++++++++++----
>  gcc/tree-vect-loop-manip.cc                   |  96 +++++++---
>  gcc/tree-vect-loop.cc                         |   1 +
>  gcc/tree-vectorizer.h                         |  16 ++
>  5 files changed, 222 insertions(+), 61 deletions(-)
> 
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_133_pfa6.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_133_pfa6.c
> index ee123df6ed2..7787d037d9d 100644
> --- a/gcc/testsuite/gcc.dg/vect/vect-early-break_133_pfa6.c
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_133_pfa6.c
> @@ -20,4 +20,4 @@ unsigned test4(char x, char *vect_a, char *vect_b, int n)
>   return ret;
>  }
>  
> -/* { dg-final { scan-tree-dump "Versioning for alignment will be applied" 
> "vect" } } */
> +/* { dg-final { scan-tree-dump "Both peeling and versioning will be applied" 
> "vect" } } */
> diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
> index 1792ee4ea05..befdbff29f3 100644
> --- a/gcc/tree-vect-data-refs.cc
> +++ b/gcc/tree-vect-data-refs.cc
> @@ -2111,9 +2111,10 @@ vect_peeling_hash_choose_best_peeling 
> (hash_table<peel_info_hasher> *peeling_hta
>     return res;
>  }
>  
> -/* Return true if the new peeling NPEEL is supported.  */
> +/* Return if vectorization is definitely, possibly, or unlikely to be
> +   supportable after loop peeling.  */
>  
> -static bool
> +static enum peeling_support
>  vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info,
>                         unsigned npeel)
>  {
> @@ -2123,8 +2124,11 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, 
> dr_vec_info *dr0_info,
>    bool dr0_alignment_known_p
>      = known_alignment_for_access_p (dr0_info,
>                                   STMT_VINFO_VECTYPE (dr0_info->stmt));
> +  bool has_unsupported_dr_p = false;
> +  unsigned int dr0_step = DR_STEP_ALIGNMENT (dr0_info->dr);
> +  int known_unsupported_misalignment = DR_MISALIGNMENT_UNKNOWN;
>  
> -  /* Ensure that all data refs can be vectorized after the peel.  */
> +  /* Check if each data ref can be vectorized after peeling.  */
>    for (data_reference *dr : datarefs)
>      {
>        if (dr == dr0_info->dr)
> @@ -2152,10 +2156,44 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, 
> dr_vec_info *dr0_info,
>       = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype,
>                                        misalignment);
>        if (supportable_dr_alignment == dr_unaligned_unsupported)
> -     return false;
> +     {
> +       has_unsupported_dr_p = true;
> +
> +       /* If unaligned unsupported DRs exist, we do following checks to see
> +          if they can be mutually aligned to support vectorization.  If yes,
> +          we can try peeling and create a runtime (mutual alignment) check
> +          to guard the peeled loop.  If no, return PEELING_UNSUPPORTED.  */
> +
> +       /* 1) If unaligned unsupported DRs have different alignment steps, the
> +             probability of DRs being mutually aligned is very low, and it's
> +             quite complex to check mutual alignment at runtime.  We return
> +             PEELING_UNSUPPORTED in this case.  */
> +       if (DR_STEP_ALIGNMENT (dr) != dr0_step)
> +         return peeling_unsupported;
> +
> +       /* 2) Based on above same alignment step condition, if one known
> +             misaligned DR has zero misalignment, or different misalignment
> +             amount from another known misaligned DR, peeling is unable to
> +             help make all these DRs aligned together.  We won't try peeling
> +             with versioning anymore.  */
> +       int curr_dr_misalignment = dr_misalignment (dr_info, vectype);
> +       if (curr_dr_misalignment == 0)
> +         return peeling_unsupported;
> +       if (known_unsupported_misalignment != DR_MISALIGNMENT_UNKNOWN)
> +         {
> +           if (curr_dr_misalignment != DR_MISALIGNMENT_UNKNOWN
> +               && curr_dr_misalignment != known_unsupported_misalignment)
> +             return peeling_unsupported;
> +         }
> +       else
> +         known_unsupported_misalignment = curr_dr_misalignment;
> +     }
>      }
>  
> -  return true;
> +  /* Vectorization is known to be supportable with peeling alone when there 
> is
> +     no unsupported DR.  */
> +  return has_unsupported_dr_p ? peeling_maybe_supported
> +                           : peeling_known_supported;
>  }
>  
>  /* Compare two data-references DRA and DRB to group them into chunks
> @@ -2264,20 +2302,20 @@ dr_align_group_sort_cmp (const void *dra_, const void 
> *drb_)
>       }
>  
>       -- Possibility 3: combination of loop peeling and versioning:
> -     for (i = 0; i < 3; i++){        # (scalar loop, not to be vectorized).
> -     x = q[i];
> -     p[i] = y;
> -     }
> -     if (p is aligned) {
> -     for (i = 3; i<N; i++){  # loop 3A
> +     if (p & q are mutually aligned) {
> +     for (i=0; i<3; i++){    # (peeled loop iterations).
> +       x = q[i];
> +       p[i] = y;
> +     }
> +     for (i=3; i<N; i++){    # loop 3A
>         x = q[i];                     # DR_MISALIGNMENT(q) = 0
>         p[i] = y;                     # DR_MISALIGNMENT(p) = 0
>       }
>       }
>       else {
> -     for (i = 3; i<N; i++){  # loop 3B
> -       x = q[i];                     # DR_MISALIGNMENT(q) = 0
> -       p[i] = y;                     # DR_MISALIGNMENT(p) = unaligned
> +     for (i=0; i<N; i++){    # (scalar loop, not to be vectorized).
> +       x = q[i];                     # DR_MISALIGNMENT(q) = 3
> +       p[i] = y;                     # DR_MISALIGNMENT(p) = unknown
>       }
>       }
>  
> @@ -2296,6 +2334,7 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>    unsigned int i;
>    bool do_peeling = false;
>    bool do_versioning = false;
> +  bool try_peeling_with_versioning = false;
>    unsigned int npeel = 0;
>    bool one_misalignment_known = false;
>    bool one_misalignment_unknown = false;
> @@ -2361,30 +2400,38 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>    /* While cost model enhancements are expected in the future, the high level
>       view of the code at this time is as follows:
>  
> -     A) If there is a misaligned access then see if peeling to align
> -        this access can make all data references satisfy
> -        vect_supportable_dr_alignment.  If so, update data structures
> -        as needed and return true.
> +     A) If there is a misaligned access then see if doing peeling alone can
> +     make all data references satisfy vect_supportable_dr_alignment.  If so,
> +     update data structures and return.
> +
> +     B) If peeling alone wasn't possible and there is a data reference with 
> an
> +     unknown misalignment that does not satisfy vect_supportable_dr_alignment
> +     then we may use either of the following two approaches.
>  
> -     B) If peeling wasn't possible and there is a data reference with an
> -        unknown misalignment that does not satisfy 
> vect_supportable_dr_alignment
> -        then see if loop versioning checks can be used to make all data
> -        references satisfy vect_supportable_dr_alignment.  If so, update
> -        data structures as needed and return true.
> +     B1) Try peeling with versioning: Add a runtime loop versioning check to
> +         see if all unsupportable data references are mutually aligned, which
> +         means they will be uniformly aligned after a certain amount of loop
> +         peeling.  If peeling and versioning can be used together, set
> +         LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT_P to TRUE and return.
>  
> -     C) If neither peeling nor versioning were successful then return false 
> if
> -        any data reference does not satisfy vect_supportable_dr_alignment.
> +     B2) Try versioning alone: Add a runtime loop versioning check to see if
> +         all unsupportable data references are already uniformly aligned
> +         without loop peeling.  If versioning can be applied alone, set
> +         LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT_P to FALSE and return.
>  
> -     D) Return true (all data references satisfy 
> vect_supportable_dr_alignment).
> +     Above B1 is more powerful and more likely to be adopted than B2.  But B2
> +     is still available and useful in some cases, for example, the cost model
> +     does not allow much peeling.
>  
> -     Note, Possibility 3 above (which is peeling and versioning together) is 
> not
> -     being done at this time.  */
> +     C) If none of above was successful then the alignment was not enhanced,
> +     just return.  */
>  
>    /* (1) Peeling to force alignment.  */
>  
> -  /* (1.1) Decide whether to perform peeling, and how many iterations to 
> peel:
> +  /* (1.1) Decide whether to perform peeling, how many iterations to peel, 
> and
> +     if vectorization may be supported by peeling with versioning.
>       Considerations:
> -     + How many accesses will become aligned due to the peeling
> +     - How many accesses will become aligned due to the peeling
>       - How many accesses will become unaligned due to the peeling,
>         and the cost of misaligned accesses.
>       - The cost of peeling (the extra runtime checks, the increase
> @@ -2732,9 +2779,27 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>                               "Try peeling by %d\n", npeel);
>          }
>  
> -      /* Ensure that all datarefs can be vectorized after the peel.  */
> -      if (!vect_peeling_supportable (loop_vinfo, dr0_info, npeel))
> -     do_peeling = false;
> +      /* Check how peeling for alignment can support vectorization.  Function
> +      vect_peeling_supportable returns one of the three possible values:
> +      - PEELING_KNOWN_SUPPORTED: indicates that we know all unsupported
> +        datarefs can be aligned after peeling.  We can use peeling alone.
> +      - PEELING_MAYBE_SUPPORTED: indicates that peeling may be able to make
> +        these datarefs aligned but we are not sure about it at compile time.
> +        We will try peeling with versioning to add a runtime check to guard
> +        the peeled loop.
> +      - PEELING_UNSUPPORTED: indicates that peeling is almost impossible to
> +        support vectorization.  We will stop trying peeling.  */
> +      switch (vect_peeling_supportable (loop_vinfo, dr0_info, npeel))
> +     {
> +     case peeling_known_supported:
> +       break;
> +     case peeling_maybe_supported:
> +       try_peeling_with_versioning = true;
> +       break;
> +     case peeling_unsupported:
> +       do_peeling = false;
> +       break;
> +     }
>  
>        /* Check if all datarefs are supportable and log.  */
>        if (do_peeling
> @@ -2811,7 +2876,11 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>  
>               vect_update_misalignment_for_peel (dr_info, dr0_info, npeel);
>             }
> +     }
>  
> +      if (do_peeling && !try_peeling_with_versioning)
> +     {
> +       /* Update data structures if peeling will be applied alone.  */
>            LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0_info;
>            if (npeel)
>              LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = npeel;
> @@ -2939,6 +3008,11 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>          LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).truncate (0);
>      }
>  
> +  /* If we are trying peeling with versioning but versioning is disabled for
> +     some reason, peeling should be turned off together.  */
> +  if (try_peeling_with_versioning && !do_versioning)
> +    do_peeling = false;
> +
>    if (do_versioning)
>      {
>        const vec<stmt_vec_info> &may_misalign_stmts
> @@ -2958,12 +3032,28 @@ vect_enhance_data_refs_alignment (loop_vec_info 
> loop_vinfo)
>                               "Alignment of access forced using 
> versioning.\n");
>          }
>  
> -      if (dump_enabled_p ())
> -        dump_printf_loc (MSG_NOTE, vect_location,
> -                         "Versioning for alignment will be applied.\n");
> -
> -      /* Peeling and versioning can't be done together at this time.  */
> -      gcc_assert (! (do_peeling && do_versioning));
> +      if (do_peeling)
> +     {
> +       /* This point is reached if peeling and versioning are used together
> +          to ensure alignment.  Update data structures to make sure the loop
> +          is correctly peeled and a right runtime check is added for loop
> +          versioning.  */
> +       gcc_assert (try_peeling_with_versioning);
> +       LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0_info;
> +       LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) = -1;
> +       LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT (loop_vinfo) = true;
> +       if (dump_enabled_p ())
> +         dump_printf_loc (MSG_NOTE, vect_location,
> +                          "Both peeling and versioning will be applied.\n");
> +     }
> +      else
> +     {
> +       /* This point is reached if versioning is used alone.  */
> +       LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT (loop_vinfo) = false;
> +       if (dump_enabled_p ())
> +         dump_printf_loc (MSG_NOTE, vect_location,
> +                          "Versioning for alignment will be applied.\n");
> +     }
>  
>        return opt_result::success ();
>      }
> diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
> index 56a4e9a8b63..18f7c1bcea6 100644
> --- a/gcc/tree-vect-loop-manip.cc
> +++ b/gcc/tree-vect-loop-manip.cc
> @@ -3787,10 +3787,11 @@ chain_cond_expr (tree *cond_expr, tree part_cond_expr)
>  
>     Input:
>     COND_EXPR  - input conditional expression.  New conditions will be chained
> -                with logical AND operation.
> -   LOOP_VINFO - two fields of the loop information are used.
> -                LOOP_VINFO_PTR_MASK is the mask used to check the alignment.
> -                LOOP_VINFO_MAY_MISALIGN_STMTS contains the refs to be 
> checked.
> +             with logical AND operation.
> +   LOOP_VINFO - three fields of the loop information are used.
> +             LOOP_VINFO_PTR_MASK is the mask used to check the alignment.
> +             LOOP_VINFO_MAY_MISALIGN_STMTS contains the refs to be checked.
> +             LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT indicates which check applies.
>  
>     Output:
>     COND_EXPR_STMT_LIST - statements needed to construct the conditional
> @@ -3798,7 +3799,20 @@ chain_cond_expr (tree *cond_expr, tree part_cond_expr)
>     The returned value is the conditional expression to be used in the if
>     statement that controls which version of the loop gets executed at 
> runtime.
>  
> -   The algorithm makes two assumptions:
> +   Based on the boolean value of LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT, we decide
> +   which type of check should be applied and create two different expressions
> +   accordingly.
> +     1) When LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT is false, we see if all data 
> refs
> +     to be checked are already aligned to an alignment boundary.  We create
> +     an expression of "(a_1 | a_2 | a_3 | ... | a_n) & mask", where "a_i" is
> +     the address of i'th data reference.
> +     2) When LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT is true, we see if all data 
> refs
> +     can be aligned to a boundary after a certain amount of peeling, in other
> +     words, their addresses have the same bottom bits according to the mask.
> +     We create "((a_1 ^ a_2) | (a_2 ^ a_3) | ... | (a_n-1 ^ a_n)) & mask",
> +     where "a_i" is the address of i'th data reference.
> +
> +   Both algorithms make two assumptions:
>       1) The number of bytes "n" in a vector is a power of 2.
>       2) An address "a" is aligned if a%n is zero and that this
>          test can be done as a&(n-1) == 0.  For example, for 16
> @@ -3818,6 +3832,7 @@ vect_create_cond_for_align_checks (loop_vec_info 
> loop_vinfo,
>    tree int_ptrsize_type;
>    char tmp_name[20];
>    tree or_tmp_name = NULL_TREE;
> +  tree prev_addr_tmp_name = NULL_TREE;
>    tree and_tmp_name;
>    gimple *and_stmt;
>    tree ptrsize_zero;
> @@ -3829,16 +3844,19 @@ vect_create_cond_for_align_checks (loop_vec_info 
> loop_vinfo,
>  
>    int_ptrsize_type = signed_type_for (ptr_type_node);
>  
> -  /* Create expression (mask & (dr_1 || ... || dr_n)) where dr_i is the 
> address
> -     of the first vector of the i'th data reference. */
> +  /* If LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT is true, we should have at least 
> two
> +     datarefs to check the mutual alignment.  */
> +  gcc_assert (may_misalign_stmts.length () > 1
> +           || !LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT (loop_vinfo));
>  
>    FOR_EACH_VEC_ELT (may_misalign_stmts, i, stmt_info)
>      {
>        gimple_seq new_stmt_list = NULL;
>        tree addr_base;
>        tree addr_tmp_name;
> +      tree xor_tmp_name;
>        tree new_or_tmp_name;
> -      gimple *addr_stmt, *or_stmt;
> +      gimple *addr_stmt, *or_stmt, *xor_stmt;
>        tree vectype = STMT_VINFO_VECTYPE (stmt_info);
>        bool negative = tree_int_cst_compare
>       (DR_STEP (STMT_VINFO_DATA_REF (stmt_info)), size_zero_node) < 0;
> @@ -3860,20 +3878,56 @@ vect_create_cond_for_align_checks (loop_vec_info 
> loop_vinfo,
>        addr_stmt = gimple_build_assign (addr_tmp_name, NOP_EXPR, addr_base);
>        gimple_seq_add_stmt (cond_expr_stmt_list, addr_stmt);
>  
> -      /* The addresses are OR together.  */
> -
> -      if (or_tmp_name != NULL_TREE)
> -        {
> -          /* create: or_tmp = or_tmp | addr_tmp */
> -          sprintf (tmp_name, "orptrs%d", i);
> -       new_or_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL, 
> tmp_name);
> -       or_stmt = gimple_build_assign (new_or_tmp_name, BIT_IOR_EXPR,
> -                                      or_tmp_name, addr_tmp_name);
> -       gimple_seq_add_stmt (cond_expr_stmt_list, or_stmt);
> -          or_tmp_name = new_or_tmp_name;
> -        }
> +      if (LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT (loop_vinfo))
> +     {
> +       /* Create "((a_1 ^ a_2) | (a_2 ^ a_3) | ... | (a_n-1 ^ a_n)) & mask"
> +          to check mutual alignment.  */
> +       if (prev_addr_tmp_name != NULL_TREE)
> +         {
> +           sprintf (tmp_name, "xorptrs%d_%d", i - 1, i);
> +           xor_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL,
> +                                              tmp_name);
> +           xor_stmt = gimple_build_assign (xor_tmp_name, BIT_XOR_EXPR,
> +                                           prev_addr_tmp_name,
> +                                           addr_tmp_name);
> +           gimple_seq_add_stmt (cond_expr_stmt_list, xor_stmt);
> +           if (or_tmp_name == NULL_TREE)
> +             {
> +               /* Create the 1st XOR when the 2nd data ref is seen.  */
> +               or_tmp_name = xor_tmp_name;
> +             }
> +           else
> +             {
> +               /* Create: or_tmp = or_tmp | new_xor_tmp.  */
> +               sprintf (tmp_name, "orxors%d", i - 1);
> +               new_or_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL,
> +                                                     tmp_name);
> +               or_stmt = gimple_build_assign (new_or_tmp_name, BIT_IOR_EXPR,
> +                                              or_tmp_name, xor_tmp_name);
> +               gimple_seq_add_stmt (cond_expr_stmt_list, or_stmt);
> +               or_tmp_name = new_or_tmp_name;
> +             }
> +         }
> +       prev_addr_tmp_name = addr_tmp_name;
> +     }
>        else
> -        or_tmp_name = addr_tmp_name;
> +     {
> +       /* Create: "(a_1 | a_2 | a_3 | ... | a_n) & mask" to check if all
> +          addresses are already aligned.  */
> +       if (or_tmp_name != NULL_TREE)
> +         {
> +           /* Create: or_tmp = or_tmp | addr_tmp.  */
> +           sprintf (tmp_name, "orptrs%d", i);
> +           new_or_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL,
> +                                                 tmp_name);
> +           or_stmt = gimple_build_assign (new_or_tmp_name, BIT_IOR_EXPR,
> +                                          or_tmp_name, addr_tmp_name);
> +           gimple_seq_add_stmt (cond_expr_stmt_list, or_stmt);
> +           or_tmp_name = new_or_tmp_name;
> +         }
> +       else
> +         or_tmp_name = addr_tmp_name;
> +     }
>  
>      } /* end for i */
>  
> diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
> index 8c5761d3c55..76c17e75f2e 100644
> --- a/gcc/tree-vect-loop.cc
> +++ b/gcc/tree-vect-loop.cc
> @@ -1069,6 +1069,7 @@ _loop_vec_info::_loop_vec_info (class loop *loop_in, 
> vec_info_shared *shared)
>      using_decrementing_iv_p (false),
>      using_select_vl_p (false),
>      epil_using_partial_vectors_p (false),
> +    allow_mutual_alignment (false),
>      partial_load_store_bias (0),
>      peeling_for_gaps (false),
>      peeling_for_niter (false),
> diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
> index 7aa2b02b63c..6ccafaf18e6 100644
> --- a/gcc/tree-vectorizer.h
> +++ b/gcc/tree-vectorizer.h
> @@ -56,6 +56,14 @@ enum dr_alignment_support {
>    dr_aligned
>  };
>  
> +/* Define type of peeling support to indicate how peeling for alignment can 
> help
> +   make vectorization supported.  */
> +enum peeling_support {
> +  peeling_known_supported,
> +  peeling_maybe_supported,
> +  peeling_unsupported
> +};
> +
>  /* Define type of def-use cross-iteration cycle.  */
>  enum vect_def_type {
>    vect_uninitialized_def = 0,
> @@ -946,6 +954,13 @@ public:
>       epilogue of loop.  */
>    bool epil_using_partial_vectors_p;
>  
> +  /* True if we've decided to use peeling with versioning together, which 
> allows
> +     unaligned unsupported data refs to be uniformly aligned after a certain
> +     amount of peeling (mutual alignment).  Otherwise, we use versioning 
> alone
> +     so these data refs must be already aligned to a power-of-two boundary
> +     without peeling.  */
> +  bool allow_mutual_alignment;
> +
>    /* The bias for len_load and len_store.  For now, only 0 and -1 are
>       supported.  -1 must be used when a backend does not support
>       len_load/len_store with a length of zero.  */
> @@ -1070,6 +1085,7 @@ public:
>  #define LOOP_VINFO_USING_SELECT_VL_P(L) (L)->using_select_vl_p
>  #define LOOP_VINFO_EPIL_USING_PARTIAL_VECTORS_P(L)                           
>   \
>    (L)->epil_using_partial_vectors_p
> +#define LOOP_VINFO_ALLOW_MUTUAL_ALIGNMENT(L) (L)->allow_mutual_alignment
>  #define LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS(L) (L)->partial_load_store_bias
>  #define LOOP_VINFO_VECT_FACTOR(L)          (L)->vectorization_factor
>  #define LOOP_VINFO_MAX_VECT_FACTOR(L)      (L)->max_vectorization_factor
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
HRB 36809 (AG Nuernberg)

Reply via email to