[4/7] Add DR_STEP_ALIGNMENT

Message ID 87shiex9a5.fsf@linaro.org
State New
Headers show
Series
  • Untitled series #2691
Related show

Commit Message

Richard Sandiford July 3, 2017, 7:35 a.m.
A later patch adds base alignment information to innermost_loop_behavior.
After that, the only remaining piece of alignment information that wasn't
immediately obvious was the step alignment.  Adding that allows a minor
simplification to vect_compute_data_ref_alignment, and also potentially
improves the handling of variable strides for outer loop vectorisation.
A later patch will also use it to give the alignment of the DR as a whole.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


2017-07-03  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* tree-data-ref.h (innermost_loop_behavior): Add a step_alignment
	field.
	(DR_STEP_ALIGNMENT): New macro.
	* tree-vectorizer.h (STMT_VINFO_DR_STEP_ALIGNMENT): Likewise.
	* tree-data-ref.c (dr_analyze_innermost): Initalize step_alignment.
	(create_data_ref): Print it.
	* tree-vect-stmts.c (vectorizable_load): Use the step alignment
	to tell whether the step preserves vector (mis)alignment.
	* tree-vect-data-refs.c (vect_compute_data_ref_alignment): Likewise.
	Move the check for an integer step and generalise to all INTEGER_CST.
	(vect_analyze_data_refs): Set DR_STEP_ALIGNMENT when setting DR_STEP.
	Print the outer step alignment.

Comments

Richard Biener July 3, 2017, 9:55 a.m. | #1
On Mon, Jul 3, 2017 at 9:35 AM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> A later patch adds base alignment information to innermost_loop_behavior.

> After that, the only remaining piece of alignment information that wasn't

> immediately obvious was the step alignment.  Adding that allows a minor

> simplification to vect_compute_data_ref_alignment, and also potentially

> improves the handling of variable strides for outer loop vectorisation.

> A later patch will also use it to give the alignment of the DR as a whole.

>

> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?


Ok.

> Richard

>

>

> 2017-07-03  Richard Sandiford  <richard.sandiford@linaro.org>

>

> gcc/

>         * tree-data-ref.h (innermost_loop_behavior): Add a step_alignment

>         field.

>         (DR_STEP_ALIGNMENT): New macro.

>         * tree-vectorizer.h (STMT_VINFO_DR_STEP_ALIGNMENT): Likewise.

>         * tree-data-ref.c (dr_analyze_innermost): Initalize step_alignment.

>         (create_data_ref): Print it.

>         * tree-vect-stmts.c (vectorizable_load): Use the step alignment

>         to tell whether the step preserves vector (mis)alignment.

>         * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Likewise.

>         Move the check for an integer step and generalise to all INTEGER_CST.

>         (vect_analyze_data_refs): Set DR_STEP_ALIGNMENT when setting DR_STEP.

>         Print the outer step alignment.

>

> Index: gcc/tree-data-ref.h

> ===================================================================

> --- gcc/tree-data-ref.h 2017-07-03 07:51:31.005161213 +0100

> +++ gcc/tree-data-ref.h 2017-07-03 07:52:14.194782203 +0100

> @@ -56,6 +56,9 @@ struct innermost_loop_behavior

>       high value if the offset is zero.  This is a byte rather than a bit

>       quantity.  */

>    unsigned int offset_alignment;

> +

> +  /* Likewise for STEP.  */

> +  unsigned int step_alignment;

>  };

>

>  /* Describes the evolutions of indices of the memory reference.  The indices

> @@ -145,6 +148,7 @@ #define DR_INIT(DR)                (DR)-

>  #define DR_STEP(DR)                (DR)->innermost.step

>  #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info

>  #define DR_OFFSET_ALIGNMENT(DR)    (DR)->innermost.offset_alignment

> +#define DR_STEP_ALIGNMENT(DR)      (DR)->innermost.step_alignment

>  #define DR_INNERMOST(DR)           (DR)->innermost

>

>  typedef struct data_reference *data_reference_p;

> Index: gcc/tree-vectorizer.h

> ===================================================================

> --- gcc/tree-vectorizer.h       2017-07-03 07:51:31.006161241 +0100

> +++ gcc/tree-vectorizer.h       2017-07-03 07:52:14.196782157 +0100

> @@ -709,6 +709,8 @@ #define STMT_VINFO_DR_OFFSET(S)

>  #define STMT_VINFO_DR_STEP(S)              (S)->dr_wrt_vec_loop.step

>  #define STMT_VINFO_DR_OFFSET_ALIGNMENT(S) \

>    (S)->dr_wrt_vec_loop.offset_alignment

> +#define STMT_VINFO_DR_STEP_ALIGNMENT(S) \

> +  (S)->dr_wrt_vec_loop.step_alignment

>

>  #define STMT_VINFO_IN_PATTERN_P(S)         (S)->in_pattern_p

>  #define STMT_VINFO_RELATED_STMT(S)         (S)->related_stmt

> Index: gcc/tree-data-ref.c

> ===================================================================

> --- gcc/tree-data-ref.c 2017-07-03 07:51:31.004161185 +0100

> +++ gcc/tree-data-ref.c 2017-07-03 07:52:14.193782226 +0100

> @@ -870,6 +870,7 @@ dr_analyze_innermost (struct data_refere

>    drb->init = init;

>    drb->step = step;

>    drb->offset_alignment = highest_pow2_factor (offset_iv.base);

> +  drb->step_alignment = highest_pow2_factor (step);

>

>    if (dump_file && (dump_flags & TDF_DETAILS))

>      fprintf (dump_file, "success.\n");

> @@ -1085,6 +1086,7 @@ create_data_ref (loop_p nest, loop_p loo

>        print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);

>        fprintf (dump_file, "\n\toffset alignment: %d",

>                DR_OFFSET_ALIGNMENT (dr));

> +      fprintf (dump_file, "\n\tstep alignment: %d", DR_STEP_ALIGNMENT (dr));

>        fprintf (dump_file, "\n\tbase_object: ");

>        print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);

>        fprintf (dump_file, "\n");

> Index: gcc/tree-vect-stmts.c

> ===================================================================

> --- gcc/tree-vect-stmts.c       2017-07-03 07:51:05.480852682 +0100

> +++ gcc/tree-vect-stmts.c       2017-07-03 07:52:14.195782180 +0100

> @@ -7294,8 +7294,7 @@ vectorizable_load (gimple *stmt, gimple_

>       nested within an outer-loop that is being vectorized.  */

>

>    if (nested_in_vect_loop

> -      && (TREE_INT_CST_LOW (DR_STEP (dr))

> -         % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))

> +      && (DR_STEP_ALIGNMENT (dr) % GET_MODE_SIZE (TYPE_MODE (vectype))) != 0)

>      {

>        gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);

>        compute_in_loop = true;

> Index: gcc/tree-vect-data-refs.c

> ===================================================================

> --- gcc/tree-vect-data-refs.c   2017-07-03 07:51:31.006161241 +0100

> +++ gcc/tree-vect-data-refs.c   2017-07-03 07:52:14.194782203 +0100

> @@ -698,10 +698,9 @@ vect_compute_data_ref_alignment (struct

>       divides by the vector size.  */

>    else if (nested_in_vect_loop_p (loop, stmt))

>      {

> -      tree step = DR_STEP (dr);

>        step_preserves_misalignment_p

> -       = (tree_fits_shwi_p (step)

> -          && tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0);

> +       = (DR_STEP_ALIGNMENT (dr)

> +          % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;

>

>        if (dump_enabled_p ())

>         {

> @@ -720,12 +719,10 @@ vect_compute_data_ref_alignment (struct

>       the dataref evenly divides by the vector size.  */

>    else

>      {

> -      tree step = DR_STEP (dr);

>        unsigned vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);

>        step_preserves_misalignment_p

> -       = (tree_fits_shwi_p (step)

> -          && ((tree_to_shwi (step) * vf)

> -              % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0));

> +       = ((DR_STEP_ALIGNMENT (dr) * vf)

> +          % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;

>

>        if (!step_preserves_misalignment_p && dump_enabled_p ())

>         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,

> @@ -773,7 +770,10 @@ vect_compute_data_ref_alignment (struct

>    alignment = TYPE_ALIGN_UNIT (vectype);

>

>    if (drb->offset_alignment < alignment

> -      || !step_preserves_misalignment_p)

> +      || !step_preserves_misalignment_p

> +      /* We need to know whether the step wrt the vectorized loop is

> +        negative when computing the starting misalignment below.  */

> +      || TREE_CODE (drb->step) != INTEGER_CST)

>      {

>        if (dump_enabled_p ())

>         {

> @@ -3414,6 +3414,8 @@ vect_analyze_data_refs (vec_info *vinfo,

>                                       DR_STEP (newdr) = step;

>                                       DR_OFFSET_ALIGNMENT (newdr)

>                                         = BIGGEST_ALIGNMENT;

> +                                     DR_STEP_ALIGNMENT (newdr)

> +                                       = highest_pow2_factor (step);

>                                       dr = newdr;

>                                       simd_lane_access = true;

>                                     }

> @@ -3665,6 +3667,8 @@ vect_analyze_data_refs (vec_info *vinfo,

>                                   STMT_VINFO_DR_STEP (stmt_info));

>               dump_printf (MSG_NOTE, "\n\touter offset alignment: %d\n",

>                            STMT_VINFO_DR_OFFSET_ALIGNMENT (stmt_info));

> +             dump_printf (MSG_NOTE, "\n\touter step alignment: %d\n",

> +                          STMT_VINFO_DR_STEP_ALIGNMENT (stmt_info));

>             }

>         }

>

Patch

Index: gcc/tree-data-ref.h
===================================================================
--- gcc/tree-data-ref.h	2017-07-03 07:51:31.005161213 +0100
+++ gcc/tree-data-ref.h	2017-07-03 07:52:14.194782203 +0100
@@ -56,6 +56,9 @@  struct innermost_loop_behavior
      high value if the offset is zero.  This is a byte rather than a bit
      quantity.  */
   unsigned int offset_alignment;
+
+  /* Likewise for STEP.  */
+  unsigned int step_alignment;
 };
 
 /* Describes the evolutions of indices of the memory reference.  The indices
@@ -145,6 +148,7 @@  #define DR_INIT(DR)                (DR)-
 #define DR_STEP(DR)                (DR)->innermost.step
 #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info
 #define DR_OFFSET_ALIGNMENT(DR)    (DR)->innermost.offset_alignment
+#define DR_STEP_ALIGNMENT(DR)      (DR)->innermost.step_alignment
 #define DR_INNERMOST(DR)           (DR)->innermost
 
 typedef struct data_reference *data_reference_p;
Index: gcc/tree-vectorizer.h
===================================================================
--- gcc/tree-vectorizer.h	2017-07-03 07:51:31.006161241 +0100
+++ gcc/tree-vectorizer.h	2017-07-03 07:52:14.196782157 +0100
@@ -709,6 +709,8 @@  #define STMT_VINFO_DR_OFFSET(S)
 #define STMT_VINFO_DR_STEP(S)              (S)->dr_wrt_vec_loop.step
 #define STMT_VINFO_DR_OFFSET_ALIGNMENT(S) \
   (S)->dr_wrt_vec_loop.offset_alignment
+#define STMT_VINFO_DR_STEP_ALIGNMENT(S) \
+  (S)->dr_wrt_vec_loop.step_alignment
 
 #define STMT_VINFO_IN_PATTERN_P(S)         (S)->in_pattern_p
 #define STMT_VINFO_RELATED_STMT(S)         (S)->related_stmt
Index: gcc/tree-data-ref.c
===================================================================
--- gcc/tree-data-ref.c	2017-07-03 07:51:31.004161185 +0100
+++ gcc/tree-data-ref.c	2017-07-03 07:52:14.193782226 +0100
@@ -870,6 +870,7 @@  dr_analyze_innermost (struct data_refere
   drb->init = init;
   drb->step = step;
   drb->offset_alignment = highest_pow2_factor (offset_iv.base);
+  drb->step_alignment = highest_pow2_factor (step);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "success.\n");
@@ -1085,6 +1086,7 @@  create_data_ref (loop_p nest, loop_p loo
       print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);
       fprintf (dump_file, "\n\toffset alignment: %d",
 	       DR_OFFSET_ALIGNMENT (dr));
+      fprintf (dump_file, "\n\tstep alignment: %d", DR_STEP_ALIGNMENT (dr));
       fprintf (dump_file, "\n\tbase_object: ");
       print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
       fprintf (dump_file, "\n");
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c	2017-07-03 07:51:05.480852682 +0100
+++ gcc/tree-vect-stmts.c	2017-07-03 07:52:14.195782180 +0100
@@ -7294,8 +7294,7 @@  vectorizable_load (gimple *stmt, gimple_
      nested within an outer-loop that is being vectorized.  */
 
   if (nested_in_vect_loop
-      && (TREE_INT_CST_LOW (DR_STEP (dr))
-	  % GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
+      && (DR_STEP_ALIGNMENT (dr) % GET_MODE_SIZE (TYPE_MODE (vectype))) != 0)
     {
       gcc_assert (alignment_support_scheme != dr_explicit_realign_optimized);
       compute_in_loop = true;
Index: gcc/tree-vect-data-refs.c
===================================================================
--- gcc/tree-vect-data-refs.c	2017-07-03 07:51:31.006161241 +0100
+++ gcc/tree-vect-data-refs.c	2017-07-03 07:52:14.194782203 +0100
@@ -698,10 +698,9 @@  vect_compute_data_ref_alignment (struct
      divides by the vector size.  */
   else if (nested_in_vect_loop_p (loop, stmt))
     {
-      tree step = DR_STEP (dr);
       step_preserves_misalignment_p
-	= (tree_fits_shwi_p (step)
-	   && tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0);
+	= (DR_STEP_ALIGNMENT (dr)
+	   % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;
 
       if (dump_enabled_p ())
 	{
@@ -720,12 +719,10 @@  vect_compute_data_ref_alignment (struct
      the dataref evenly divides by the vector size.  */
   else
     {
-      tree step = DR_STEP (dr);
       unsigned vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
       step_preserves_misalignment_p
-	= (tree_fits_shwi_p (step)
-	   && ((tree_to_shwi (step) * vf)
-	       % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0));
+	= ((DR_STEP_ALIGNMENT (dr) * vf)
+	   % GET_MODE_SIZE (TYPE_MODE (vectype))) == 0;
 
       if (!step_preserves_misalignment_p && dump_enabled_p ())
 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -773,7 +770,10 @@  vect_compute_data_ref_alignment (struct
   alignment = TYPE_ALIGN_UNIT (vectype);
 
   if (drb->offset_alignment < alignment
-      || !step_preserves_misalignment_p)
+      || !step_preserves_misalignment_p
+      /* We need to know whether the step wrt the vectorized loop is
+	 negative when computing the starting misalignment below.  */
+      || TREE_CODE (drb->step) != INTEGER_CST)
     {
       if (dump_enabled_p ())
 	{
@@ -3414,6 +3414,8 @@  vect_analyze_data_refs (vec_info *vinfo,
 				      DR_STEP (newdr) = step;
 				      DR_OFFSET_ALIGNMENT (newdr)
 					= BIGGEST_ALIGNMENT;
+				      DR_STEP_ALIGNMENT (newdr)
+					= highest_pow2_factor (step);
 				      dr = newdr;
 				      simd_lane_access = true;
 				    }
@@ -3665,6 +3667,8 @@  vect_analyze_data_refs (vec_info *vinfo,
                                  STMT_VINFO_DR_STEP (stmt_info));
 	      dump_printf (MSG_NOTE, "\n\touter offset alignment: %d\n",
 			   STMT_VINFO_DR_OFFSET_ALIGNMENT (stmt_info));
+	      dump_printf (MSG_NOTE, "\n\touter step alignment: %d\n",
+			   STMT_VINFO_DR_STEP_ALIGNMENT (stmt_info));
 	    }
 	}