While trying to remove some restrictions I came along more TLC
opportunities.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2013-04-18  Richard Biener  <rguent...@suse.de>

        * tree-vect-data-refs.c (vect_analyze_group_access): Properly
        handle negative step.  Remove redundant checks.
        (vect_create_data_ref_ptr): Avoid ICEs with non-constant steps.
        * tree-vect-stmts.c (vectorizable_load): Instead of asserting
        for negative step and grouped loads fail to vectorize.

Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c.orig      2013-04-18 12:17:03.000000000 +0200
--- gcc/tree-vect-data-refs.c   2013-04-18 12:17:14.430103903 +0200
*************** vect_analyze_group_access (struct data_r
*** 2024,2030 ****
  
    /* For interleaving, GROUPSIZE is STEP counted in elements, i.e., the
       size of the interleaving group (including gaps).  */
!   groupsize = dr_step / type_size;
  
    /* Not consecutive access is possible only if it is a part of interleaving. 
 */
    if (!GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
--- 2024,2030 ----
  
    /* For interleaving, GROUPSIZE is STEP counted in elements, i.e., the
       size of the interleaving group (including gaps).  */
!   groupsize = absu_hwi (dr_step) / type_size;
  
    /* Not consecutive access is possible only if it is a part of interleaving. 
 */
    if (!GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
*************** vect_analyze_group_access (struct data_r
*** 2094,2103 ****
        gimple next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
        struct data_reference *data_ref = dr;
        unsigned int count = 1;
-       tree next_step;
        tree prev_init = DR_INIT (data_ref);
        gimple prev = stmt;
!       HOST_WIDE_INT diff, count_in_bytes, gaps = 0;
  
        while (next)
          {
--- 2094,2103 ----
        gimple next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (stmt));
        struct data_reference *data_ref = dr;
        unsigned int count = 1;
        tree prev_init = DR_INIT (data_ref);
        gimple prev = stmt;
!       HOST_WIDE_INT diff, gaps = 0;
!       unsigned HOST_WIDE_INT count_in_bytes;
  
        while (next)
          {
*************** vect_analyze_group_access (struct data_r
*** 2126,2143 ****
              }
  
            prev = next;
  
!           /* Check that all the accesses have the same STEP.  */
!           next_step = DR_STEP (STMT_VINFO_DATA_REF (vinfo_for_stmt (next)));
!           if (tree_int_cst_compare (step, next_step))
!             {
!               if (dump_enabled_p ())
!                 dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, 
!                                  "not consecutive access in interleaving");
!               return false;
!             }
  
-           data_ref = STMT_VINFO_DATA_REF (vinfo_for_stmt (next));
            /* Check that the distance between two accesses is equal to the type
               size. Otherwise, we have gaps.  */
            diff = (TREE_INT_CST_LOW (DR_INIT (data_ref))
--- 2126,2136 ----
              }
  
            prev = next;
+           data_ref = STMT_VINFO_DATA_REF (vinfo_for_stmt (next));
  
!         /* All group members have the same STEP by construction.  */
!         gcc_checking_assert (operand_equal_p (DR_STEP (data_ref), step, 0));
  
            /* Check that the distance between two accesses is equal to the type
               size. Otherwise, we have gaps.  */
            diff = (TREE_INT_CST_LOW (DR_INIT (data_ref))
*************** vect_analyze_group_access (struct data_r
*** 2175,2181 ****
  
        /* Check that the size of the interleaving (including gaps) is not
           greater than STEP.  */
!       if (dr_step && dr_step < count_in_bytes + gaps * type_size)
          {
            if (dump_enabled_p ())
              {
--- 2168,2175 ----
  
        /* Check that the size of the interleaving (including gaps) is not
           greater than STEP.  */
!       if (dr_step != 0
!         && absu_hwi (dr_step) < count_in_bytes + gaps * type_size)
          {
            if (dump_enabled_p ())
              {
*************** vect_analyze_group_access (struct data_r
*** 2188,2194 ****
  
        /* Check that the size of the interleaving is equal to STEP for stores,
           i.e., that there are no gaps.  */
!       if (dr_step && dr_step != count_in_bytes)
          {
            if (DR_IS_READ (dr))
              {
--- 2182,2189 ----
  
        /* Check that the size of the interleaving is equal to STEP for stores,
           i.e., that there are no gaps.  */
!       if (dr_step != 0
!         && absu_hwi (dr_step) != count_in_bytes)
          {
            if (DR_IS_READ (dr))
              {
*************** vect_analyze_group_access (struct data_r
*** 2208,2214 ****
          }
  
        /* Check that STEP is a multiple of type size.  */
!       if (dr_step && (dr_step % type_size) != 0)
          {
            if (dump_enabled_p ())
              {
--- 2203,2210 ----
          }
  
        /* Check that STEP is a multiple of type size.  */
!       if (dr_step != 0
!         && (dr_step % type_size) != 0)
          {
            if (dump_enabled_p ())
              {
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 3520,3526 ****
    tree aptr;
    gimple_stmt_iterator incr_gsi;
    bool insert_after;
-   bool negative;
    tree indx_before_incr, indx_after_incr;
    gimple incr;
    tree step;
--- 3520,3525 ----
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 3550,3560 ****
    else
      step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
  
!   if (tree_int_cst_compare (step, size_zero_node) == 0)
      *inv_p = true;
    else
      *inv_p = false;
-   negative = tree_int_cst_compare (step, size_zero_node) < 0;
  
    /* Create an expression for the first address accessed by this load
       in LOOP.  */
--- 3549,3558 ----
    else
      step = DR_STEP (STMT_VINFO_DATA_REF (stmt_info));
  
!   if (integer_zerop (step))
      *inv_p = true;
    else
      *inv_p = false;
  
    /* Create an expression for the first address accessed by this load
       in LOOP.  */
*************** vect_create_data_ref_ptr (gimple stmt, t
*** 3693,3710 ****
    else
      {
        /* The step of the aggregate pointer is the type size.  */
!       tree step = TYPE_SIZE_UNIT (aggr_type);
        /* One exception to the above is when the scalar step of the load in
         LOOP is zero. In this case the step here is also zero.  */
        if (*inv_p)
!       step = size_zero_node;
!       else if (negative)
!       step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step);
  
        standard_iv_increment_position (loop, &incr_gsi, &insert_after);
  
        create_iv (aggr_ptr_init,
!                fold_convert (aggr_ptr_type, step),
                 aggr_ptr, loop, &incr_gsi, insert_after,
                 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
--- 3691,3708 ----
    else
      {
        /* The step of the aggregate pointer is the type size.  */
!       tree iv_step = TYPE_SIZE_UNIT (aggr_type);
        /* One exception to the above is when the scalar step of the load in
         LOOP is zero. In this case the step here is also zero.  */
        if (*inv_p)
!       iv_step = size_zero_node;
!       else if (tree_int_cst_sgn (step) == -1)
!       iv_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (iv_step), iv_step);
  
        standard_iv_increment_position (loop, &incr_gsi, &insert_after);
  
        create_iv (aggr_ptr_init,
!                fold_convert (aggr_ptr_type, iv_step),
                 aggr_ptr, loop, &incr_gsi, insert_after,
                 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
Index: gcc/tree-vect-stmts.c
===================================================================
*** gcc/tree-vect-stmts.c.orig  2013-04-18 12:17:03.000000000 +0200
--- gcc/tree-vect-stmts.c       2013-04-18 12:18:47.745157947 +0200
*************** vectorizable_load (gimple stmt, gimple_s
*** 4465,4471 ****
  
        if (negative)
        {
!         gcc_assert (!grouped_load);
          alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
          if (alignment_support_scheme != dr_aligned
              && alignment_support_scheme != dr_unaligned_supported)
--- 4479,4491 ----
  
        if (negative)
        {
!         if (grouped_load)
!           {
!             if (dump_enabled_p ())
!               dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                                "negative step for group load not supported");
!             return false;
!           }
          alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
          if (alignment_support_scheme != dr_aligned
              && alignment_support_scheme != dr_unaligned_supported)

Reply via email to