]> gcc.gnu.org Git - gcc.git/commitdiff
re PR tree-optimization/18179 (vectorizer: wrong alignment/step/initial-address compu...
authorIra Rosen <irar@il.ibm.com>
Wed, 29 Dec 2004 13:16:07 +0000 (13:16 +0000)
committerDorit Nuzman <dorit@gcc.gnu.org>
Wed, 29 Dec 2004 13:16:07 +0000 (13:16 +0000)
2004-12-29  Ira Rosen  <irar@il.ibm.com>

        PR tree-optimization/18179
        * tree-vectorizer.h (struct _stmt_vec_info): Add new fields:
        initial_offset, step, misalignment and base_aligned_p and macros
        to access them.
        * tree-vectorizer.c (vect_analyze_offset_expr): New function.
        (new_stmt_vec_info): Initialize the new fields of stmt_vec_info.

        (vect_create_data_ref_ptr): Fix printings.

From-SVN: r92701

gcc/ChangeLog
gcc/tree-vectorizer.c
gcc/tree-vectorizer.h

index 984db9a97c0536f134217fe090e0b44bbefed144..df492c52e5444e11d6c39af67963317315ee2795 100644 (file)
@@ -1,6 +1,17 @@
 2004-12-29  Ira Rosen  <irar@il.ibm.com>
 
-        PR tree-optimization/18179
+       PR tree-optimization/18179
+       * tree-vectorizer.h (struct _stmt_vec_info): Add new fields:
+       initial_offset, step, misalignment and base_aligned_p and macros
+       to access them.
+       * tree-vectorizer.c (vect_analyze_offset_expr): New function.
+       (new_stmt_vec_info): Initialize the new fields of stmt_vec_info.
+
+       (vect_create_data_ref_ptr): Fix printings.
+
+2004-12-29  Ira Rosen  <irar@il.ibm.com>
+
+       PR tree-optimization/18179
        * tree-vectorizer.c (vect_get_symbl_and_dr): Reorganize. Add memtag 
        retrieval.
        (vect_analyze_data_refs): Remove memtag retrieval.
index ab9acf7e6de530fcd0ecab29d72dfb3628999c1c..70af3e48fba535ad5d5629196115bec6d9afc4aa 100644 (file)
@@ -232,6 +232,8 @@ static tree vect_compute_array_ref_alignment
 static tree vect_get_ptr_offset (tree, tree, tree *);
 static tree vect_get_symbl_and_dr
   (tree, tree, bool, loop_vec_info, struct data_reference **);
+static bool vect_analyze_offset_expr (tree, struct loop *, tree, tree *, 
+                                     tree *, tree *);
 
 /* Utility functions for the code transformation.  */
 static tree vect_create_destination_var (tree, tree);
@@ -1139,6 +1141,10 @@ new_stmt_vec_info (tree stmt, struct loop *loop)
   STMT_VINFO_DATA_REF (res) = NULL;
   STMT_VINFO_MEMTAG (res) = NULL;
   STMT_VINFO_VECT_DR_BASE (res) = NULL;
+  STMT_VINFO_VECT_INIT_OFFSET (res) = NULL_TREE;
+  STMT_VINFO_VECT_STEP (res) = NULL_TREE;
+  STMT_VINFO_VECT_BASE_ALIGNED_P (res) = false;
+  STMT_VINFO_VECT_MISALIGNMENT (res) = NULL_TREE;
 
   return res;
 }
@@ -1338,6 +1344,189 @@ vect_get_ptr_offset (tree ref ATTRIBUTE_UNUSED,
 }
 
 
+/* Function vect_analyze_offset_expr
+
+   Given an offset expression EXPR received from get_inner_reference, analyze
+   it and create an expression for INITIAL_OFFSET by substituting the variables 
+   of EXPR with initial_condition of the corresponding access_fn in the loop. 
+   E.g., 
+      for i
+         for (j = 3; j < N; j++)
+            a[j].b[i][j] = 0;
+        
+   For a[j].b[i][j], EXPR will be 'i * C_i + j * C_j + C'. 'i' cannot be 
+   subsituted, since its access_fn in the inner loop is i. 'j' will be 
+   substituted with 3. An INITIAL_OFFSET will be 'i * C_i + C`', where
+   C` =  3 * C_j + C.
+
+   Compute MISALIGN (the misalignment of the data reference initial access from
+   its base) if possible. Misalignment can be calculated only if all the
+   variables can be substitued with constants, or if a variable is multiplied
+   by a multiple of VECTYPE_ALIGNMENT. In the above example, since 'i' cannot
+   be substituted, MISALIGN will be NULL_TREE in case that C_i is not a multiple
+   of VECTYPE_ALIGNMENT, and C` otherwise. (We perform MISALIGN modulo 
+   VECTYPE_ALIGNMENT computation in the caller of this function).
+
+   STEP is an evolution of the data reference in this loop in bytes.
+   In the above example, STEP is C_j.
+
+   Return FALSE, if the analysis fails, e.g., there is no access_fn for a 
+   variable. In this case, all the outputs (INITIAL_OFFSET, MISALIGN and STEP) 
+   are NULL_TREEs. Otherwise, return TRUE.
+
+*/
+
+static bool
+vect_analyze_offset_expr (tree expr, 
+                         struct loop *loop, 
+                         tree vectype_alignment,
+                         tree *initial_offset,
+                         tree *misalign,
+                         tree *step)
+{
+  tree oprnd0;
+  tree oprnd1;
+  tree left_offset = size_zero_node;
+  tree right_offset = size_zero_node;
+  tree left_misalign = size_zero_node;
+  tree right_misalign = size_zero_node;
+  tree left_step = size_zero_node;
+  tree right_step = size_zero_node;
+  enum tree_code code;
+  tree init, evolution, def_stmt;
+
+  STRIP_NOPS (expr);
+  
+  *step = NULL_TREE;
+  *misalign = NULL_TREE;
+  *initial_offset = NULL_TREE;
+
+  /* Stop conditions:
+     1. Constant.  */
+  if (TREE_CONSTANT (expr))
+    {
+      *initial_offset = fold_convert (sizetype, expr);
+      *misalign = fold_convert (sizetype, expr);      
+      *step = size_zero_node;
+      return true;
+    }
+
+  /* 2. Variable. Try to substitute with initial_condition of the corresponding
+     access_fn in the current loop.  */
+  if (SSA_VAR_P (expr))
+    {
+      tree access_fn = analyze_scalar_evolution (loop, expr);
+
+      if (access_fn == chrec_dont_know)
+       /* No access_fn.  */
+       return false;
+
+      init = initial_condition_in_loop_num (access_fn, loop->num);
+      if (init == expr)
+       {
+         def_stmt = SSA_NAME_DEF_STMT (init);
+         if (def_stmt 
+             && !IS_EMPTY_STMT (def_stmt)
+             && flow_bb_inside_loop_p (loop, bb_for_stmt (def_stmt)))
+           /* Not enough information: may be not loop invariant.  
+              E.g., for a[b[i]], we get a[D], where D=b[i]. EXPR is D, its 
+              initial_condition is D, but it depends on i - loop's induction
+              variable.  */      
+           return false;
+       }
+
+      evolution = evolution_part_in_loop_num (access_fn, loop->num);
+      if (evolution && TREE_CODE (evolution) != INTEGER_CST)
+       /* Evolution is not constant.  */
+       return false;
+
+      if (TREE_CONSTANT (init))
+       *misalign = fold_convert (sizetype, init);
+      else
+       /* Not constant, misalignment cannot be calculated.  */
+       *misalign = NULL_TREE;
+
+      *initial_offset = fold_convert (sizetype, init); 
+
+      *step = evolution ? fold_convert (sizetype, evolution) : size_zero_node;
+      return true;      
+    }
+
+  /* Recursive computation.  */
+  oprnd0 = TREE_OPERAND (expr, 0);
+  oprnd1 = TREE_OPERAND (expr, 1);
+
+  if (!vect_analyze_offset_expr (oprnd0, loop, vectype_alignment, &left_offset, 
+                               &left_misalign, &left_step)
+      || !vect_analyze_offset_expr (oprnd1, loop, vectype_alignment, 
+                                   &right_offset, &right_misalign, &right_step))
+      return false;
+
+  /* The type of the operation: plus, minus or mult.  */
+  code = TREE_CODE (expr);
+  switch (code)
+    {
+    case MULT_EXPR:
+      if (!TREE_CONSTANT (right_offset))
+       /* RIGHT_OFFSET can be not constant. For example, for arrays of variable 
+          sized types. 
+          FORNOW: We don't support such cases.  */
+       return false;
+
+      /* Misalignment computation.  */
+      if (SSA_VAR_P (left_offset))
+       {
+         /* If the left side contains variable that cannot be substituted with 
+            constant, we check if the right side is a multiple of ALIGNMENT.  */
+         if (integer_zerop (size_binop (TRUNC_MOD_EXPR, right_offset, 
+                                        vectype_alignment)))
+           *misalign = size_zero_node;
+         else
+           /* If the remainder is not zero or the right side isn't constant, we 
+              can't compute  misalignment.  */
+           *misalign = NULL_TREE;
+       }
+      else 
+       {
+         /* The left operand was successfully substituted with constant.  */     
+         if (left_misalign)
+           /* In case of EXPR '(i * C1 + j) * C2', LEFT_MISALIGN is 
+              NULL_TREE.  */
+           *misalign  = size_binop (code, left_misalign, right_misalign);
+         else
+           *misalign = NULL_TREE; 
+       }
+
+      /* Step calculation.  */
+      /* Multiply the step by the right operand.  */
+      *step  = size_binop (MULT_EXPR, left_step, right_offset);
+      break;
+   
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+      /* Combine the recursive calculations for step and misalignment.  */
+      *step = size_binop (code, left_step, right_step);
+   
+      if (left_misalign && right_misalign)
+       *misalign  = size_binop (code, left_misalign, right_misalign);
+      else
+       *misalign = NULL_TREE;
+    
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Compute offset.  */
+  *initial_offset = fold_convert (sizetype, 
+                                 fold (build2 (code, TREE_TYPE (left_offset), 
+                                               left_offset, 
+                                               right_offset)));
+  return true;
+}
+
+
 /* Function vect_get_base_and_bit_offset
 
    Return the BASE of the data reference EXPR.
@@ -1885,13 +2074,13 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
       fprintf (dump_file, "create array_ref of type: ");
       print_generic_expr (dump_file, vectype, TDF_SLIM);
       if (TREE_CODE (data_ref_base) == VAR_DECL)
-        fprintf (dump_file, "vectorizing a one dimensional array ref: ");
+        fprintf (dump_file, "\nvectorizing a one dimensional array ref: ");
       else if (TREE_CODE (data_ref_base) == ARRAY_REF)
-        fprintf (dump_file, "vectorizing a multidimensional array ref: ");
+        fprintf (dump_file, "\nvectorizing a multidimensional array ref: ");
       else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
-        fprintf (dump_file, "vectorizing a record based array ref: ");
+        fprintf (dump_file, "\nvectorizing a record based array ref: ");
       else if (TREE_CODE (data_ref_base) == SSA_NAME)
-        fprintf (dump_file, "vectorizing a pointer ref: ");
+        fprintf (dump_file, "\nvectorizing a pointer ref: ");
       print_generic_expr (dump_file, base_name, TDF_SLIM);
     }
 
index 20563afc625b600621047dfc70bf8637b5728208..642e3848fa9ecc0b93041859e723ad0c2f934a86 100644 (file)
@@ -85,26 +85,46 @@ typedef struct _stmt_vec_info {
   /* Aliasing information.  */
   tree memtag;
 
-  /* Data reference base. This field holds the entire invariant part of the 
-     data-reference (with respect to the relevant loop), as opposed to the 
-     field DR_BASE of the STMT_VINFO_DATA_REF struct, which holds only the 
-     initial base; e.g:
-     REF       BR_BASE     VECT_DR_BASE
-     a[i]      a               a
-     a[i][j]   a               a[i]  */
-  tree vect_dr_base;
+  /** The following fields are used to store the information about 
+      data-reference. {base + initial_offset} is the first location accessed by
+      data-ref in the loop, and step is the stride of data-ref in the loop;
+      e.g.:
+    
+                       Example 1                      Example 2
+      data-ref         a[j].b[i][j]                   a + 4B (a is int*)
+
+      base             a                              a
+      initial_offset   j_0*D_j + i_0*D_i + C          4
+      step             D_j                            4
+
+  **/
+  /* The above base, offset and step.  */
+  tree base;
+  tree initial_offset;
+  tree step;
+
+  /* Alignment information. Whether the base of the data-reference is aligned 
+     to vectype.  */
+  bool base_aligned_p;
+  /* Alignment information. The offset of the data-reference from its base 
+     in bytes.  */
+  tree misalignment;
 } *stmt_vec_info;
 
 /* Access Functions.  */
-#define STMT_VINFO_TYPE(S)          (S)->type
-#define STMT_VINFO_STMT(S)          (S)->stmt
-#define STMT_VINFO_LOOP(S)          (S)->loop
-#define STMT_VINFO_RELEVANT_P(S)    (S)->relevant
-#define STMT_VINFO_VECTYPE(S)       (S)->vectype
-#define STMT_VINFO_VEC_STMT(S)      (S)->vectorized_stmt
-#define STMT_VINFO_DATA_REF(S)      (S)->data_ref_info
-#define STMT_VINFO_MEMTAG(S)        (S)->memtag
-#define STMT_VINFO_VECT_DR_BASE(S)  (S)->vect_dr_base
+#define STMT_VINFO_TYPE(S)                (S)->type
+#define STMT_VINFO_STMT(S)                (S)->stmt
+#define STMT_VINFO_LOOP(S)                (S)->loop
+#define STMT_VINFO_RELEVANT_P(S)          (S)->relevant
+#define STMT_VINFO_VECTYPE(S)             (S)->vectype
+#define STMT_VINFO_VEC_STMT(S)            (S)->vectorized_stmt
+#define STMT_VINFO_DATA_REF(S)            (S)->data_ref_info
+#define STMT_VINFO_MEMTAG(S)              (S)->memtag
+#define STMT_VINFO_VECT_DR_BASE(S)        (S)->base
+#define STMT_VINFO_VECT_INIT_OFFSET(S)    (S)->initial_offset
+#define STMT_VINFO_VECT_STEP(S)           (S)->step
+#define STMT_VINFO_VECT_BASE_ALIGNED_P(S) (S)->base_aligned_p
+#define STMT_VINFO_VECT_MISALIGNMENT(S)   (S)->misalignment
 
 static inline void set_stmt_info (stmt_ann_t ann, stmt_vec_info stmt_info);
 static inline stmt_vec_info vinfo_for_stmt (tree stmt);
This page took 0.090327 seconds and 5 git commands to generate.