OSDN Git Service

Changlog libcpp
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-stmts.c
index be6e2c6..7e45123 100644 (file)
@@ -145,6 +145,9 @@ vect_stmt_relevant_p (gimple stmt, loop_vec_info loop_vinfo,
              if (vect_print_dump_info (REPORT_DETAILS))
                fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
 
+             if (is_gimple_debug (USE_STMT (use_p)))
+               continue;
+
              /* We expect all such uses to be in the loop exit phis
                 (because of loop closed form)   */
              gcc_assert (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI);
@@ -300,19 +303,24 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "outer-loop def-stmt defining inner-loop stmt.");
+
       switch (relevant)
        {
        case vect_unused_in_scope:
-         relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def) ?
-                       vect_used_by_reduction : vect_unused_in_scope;
+         relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_nested_cycle) ?
+                     vect_used_in_scope : vect_unused_in_scope;
          break;
+
        case vect_used_in_outer_by_reduction:
+          gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
          relevant = vect_used_by_reduction;
          break;
+
        case vect_used_in_outer:
+          gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def);
          relevant = vect_used_in_scope;
          break;
-       case vect_used_by_reduction: 
+
        case vect_used_in_scope:
          break;
 
@@ -326,23 +334,21 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
                ...
        inner-loop:
                d = def_stmt
-       outer-loop-tail-bb:
+       outer-loop-tail-bb (or outer-loop-exit-bb in double reduction):
                stmt # use (d)          */
   else if (flow_loop_nested_p (bb->loop_father, def_bb->loop_father))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "inner-loop def-stmt defining outer-loop stmt.");
+
       switch (relevant)
         {
         case vect_unused_in_scope:
-          relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def) ?
+          relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def 
+            || STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_double_reduction_def) ?
                       vect_used_in_outer_by_reduction : vect_unused_in_scope;
           break;
 
-        case vect_used_in_outer_by_reduction:
-        case vect_used_in_outer:
-          break;
-
         case vect_used_by_reduction:
           relevant = vect_used_in_outer_by_reduction;
           break;
@@ -391,7 +397,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
   basic_block bb;
   gimple phi;
   bool live_p;
-  enum vect_relevant relevant;
+  enum vect_relevant relevant, tmp_relevant;
+  enum vect_def_type def_type;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "=== vect_mark_stmts_to_be_vectorized ===");
@@ -461,52 +468,68 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
         those that are used by a reduction computation, and those that are 
         (also) used by a regular computation. This allows us later on to 
         identify stmts that are used solely by a reduction, and therefore the 
-        order of the results that they produce does not have to be kept.
-
-        Reduction phis are expected to be used by a reduction stmt, or by
-        in an outer loop;  Other reduction stmts are expected to be
-        in the loop, and possibly used by a stmt in an outer loop. 
-        Here are the expected values of "relevant" for reduction phis/stmts:
+        order of the results that they produce does not have to be kept.  */
 
-        relevance:                             phi     stmt
-        vect_unused_in_scope                           ok
-        vect_used_in_outer_by_reduction        ok      ok
-        vect_used_in_outer                     ok      ok
-        vect_used_by_reduction                 ok
-        vect_used_in_scope                                           */
-
-      if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def)
+      def_type = STMT_VINFO_DEF_TYPE (stmt_vinfo);
+      tmp_relevant = relevant;
+      switch (def_type)
         {
-         enum vect_relevant tmp_relevant = relevant;
-         switch (tmp_relevant)
-           {
-           case vect_unused_in_scope:
-             gcc_assert (gimple_code (stmt) != GIMPLE_PHI);
-             relevant = vect_used_by_reduction;
-             break;
+          case vect_reduction_def:
+           switch (tmp_relevant)
+             {
+               case vect_unused_in_scope:
+                 relevant = vect_used_by_reduction;
+                 break;
 
-           case vect_used_in_outer_by_reduction:
-           case vect_used_in_outer:
-             gcc_assert (gimple_code (stmt) != GIMPLE_ASSIGN
-                          || (gimple_assign_rhs_code (stmt) != WIDEN_SUM_EXPR
-                              && (gimple_assign_rhs_code (stmt)
-                                  != DOT_PROD_EXPR)));
-             break;
+               case vect_used_by_reduction:
+                 if (gimple_code (stmt) == GIMPLE_PHI)
+                    break;
+                 /* fall through */
 
-           case vect_used_by_reduction:
-             if (gimple_code (stmt) == GIMPLE_PHI)
-               break;
-             /* fall through */
-           case vect_used_in_scope:
-           default:
-             if (vect_print_dump_info (REPORT_DETAILS))
-               fprintf (vect_dump, "unsupported use of reduction.");
-             VEC_free (gimple, heap, worklist);
-             return false;
-           }
-         live_p = false;       
-       }
+               default:
+                 if (vect_print_dump_info (REPORT_DETAILS))
+                   fprintf (vect_dump, "unsupported use of reduction.");
 
+                 VEC_free (gimple, heap, worklist);
+                 return false;
+             }
+
+           live_p = false;     
+           break;
+          case vect_nested_cycle:
+            if (tmp_relevant != vect_unused_in_scope
+                && tmp_relevant != vect_used_in_outer_by_reduction
+                && tmp_relevant != vect_used_in_outer)
+              {
+                if (vect_print_dump_info (REPORT_DETAILS))
+                  fprintf (vect_dump, "unsupported use of nested cycle.");
+
+                VEC_free (gimple, heap, worklist);
+                return false;
+              }
+
+            live_p = false; 
+            break; 
+      
+          case vect_double_reduction_def:
+            if (tmp_relevant != vect_unused_in_scope
+                && tmp_relevant != vect_used_by_reduction)
+              {
+                if (vect_print_dump_info (REPORT_DETAILS))
+                  fprintf (vect_dump, "unsupported use of double reduction.");
+
+                VEC_free (gimple, heap, worklist);
+                return false;
+              }
+
+            live_p = false;
+            break; 
+
+          default:
+            break;
+        }
       FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
        {
          tree op = USE_FROM_PTR (use_p);
@@ -971,6 +994,8 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
 
     /* Case 4: operand is defined by a loop header phi - reduction  */
     case vect_reduction_def:
+    case vect_double_reduction_def:
+    case vect_nested_cycle:
       {
        struct loop *loop;
 
@@ -1205,7 +1230,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
   tree fndecl, new_temp, def, rhs_type, lhs_type;
   gimple def_stmt;
   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
-  gimple new_stmt;
+  gimple new_stmt = NULL;
   int ncopies, j;
   VEC(tree, heap) *vargs = NULL;
   enum { NARROW, NONE, WIDEN } modifier;
@@ -1345,8 +1370,11 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
                vec_oprnd0
                  = vect_get_vec_def_for_operand (op, stmt, NULL);
              else
-               vec_oprnd0
-                 = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
+               {
+                 vec_oprnd0 = gimple_call_arg (new_stmt, i);
+                 vec_oprnd0
+                    = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
+               }
 
              VEC_quick_push (tree, vargs, vec_oprnd0);
            }
@@ -1384,14 +1412,15 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
                  vec_oprnd0
                    = vect_get_vec_def_for_operand (op, stmt, NULL);
                  vec_oprnd1
-                   = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
+                   = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
                }
              else
                {
+                 vec_oprnd1 = gimple_call_arg (new_stmt, 2*i);
                  vec_oprnd0
-                   = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd1);
+                   = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd1);
                  vec_oprnd1
-                   = vect_get_vec_def_for_stmt_copy (dt[nargs], vec_oprnd0);
+                   = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
                }
 
              VEC_quick_push (tree, vargs, vec_oprnd0);
@@ -3018,7 +3047,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 
   alignment_support_scheme = vect_supportable_dr_alignment (first_dr);
   gcc_assert (alignment_support_scheme);
-  gcc_assert (alignment_support_scheme == dr_aligned);  /* FORNOW */
 
   /* In case the vectorization factor (VF) is bigger than the number
      of elements that we can fit in a vectype (nunits), we have to generate
@@ -3157,7 +3185,16 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
               vect_permute_store_chain().  */
            vec_oprnd = VEC_index (tree, result_chain, i);
 
-         data_ref = build_fold_indirect_ref (dataref_ptr);
+          if (aligned_access_p (first_dr))
+            data_ref = build_fold_indirect_ref (dataref_ptr);
+          else
+          {
+            int mis = DR_MISALIGNMENT (first_dr);
+            tree tmis = (mis == -1 ? size_zero_node : size_int (mis));
+            tmis = size_binop (MULT_EXPR, tmis, size_int (BITS_PER_UNIT));
+            data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, dataref_ptr, tmis);
+           }
+
          /* If accesses through a pointer to vectype do not alias the original
             memory reference we have a problem.  This should never happen.  */
          gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
@@ -3605,7 +3642,8 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                {
                  gcc_assert (phi);
                  if (i == vec_num - 1 && j == ncopies - 1)
-                   add_phi_arg (phi, lsq, loop_latch_edge (containing_loop));
+                   add_phi_arg (phi, lsq, loop_latch_edge (containing_loop),
+                                UNKNOWN_LOCATION);
                  msq = lsq;
                }
            }
@@ -3745,13 +3783,17 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
    Check if STMT is conditional modify expression that can be vectorized. 
    If VEC_STMT is also passed, vectorize the STMT: create a vectorized 
    stmt using VEC_COND_EXPR  to replace it, put it in VEC_STMT, and insert it 
-   at BSI.
+   at GSI.
+
+   When STMT is vectorized as nested cycle, REDUC_DEF is the vector variable
+   to be used at REDUC_INDEX (in then clause if REDUC_INDEX is 1, and in
+   else caluse if it is 2).
 
    Return FALSE if not a vectorizable STMT, TRUE otherwise.  */
 
-static bool
+bool
 vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
-                       gimple *vec_stmt)
+                       gimple *vec_stmt, tree reduc_def, int reduc_index)
 {
   tree scalar_dest = NULL_TREE;
   tree vec_dest = NULL_TREE;
@@ -3780,7 +3822,9 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
   if (!STMT_VINFO_RELEVANT_P (stmt_info))
     return false;
 
-  if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
+  if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
+      && !(STMT_VINFO_DEF_TYPE (stmt_info) == vect_nested_cycle
+           && reduc_def))
     return false;
 
   /* FORNOW: SLP not supported.  */
@@ -3788,7 +3832,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
     return false;
 
   /* FORNOW: not yet supported.  */
-  if (STMT_VINFO_LIVE_P (stmt_info))
+  if (STMT_VINFO_LIVE_P (stmt_info)) 
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "value used after loop.");
@@ -3848,7 +3892,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
   if (!vec_stmt) 
     {
       STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
-      return expand_vec_cond_expr_p (op, vec_mode);
+      return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
     }
 
   /* Transform */
@@ -3862,8 +3906,14 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
     vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
   vec_cond_rhs = 
     vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
-  vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
-  vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
+  if (reduc_index == 1)
+    vec_then_clause = reduc_def;
+  else
+    vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
+  if (reduc_index == 2)
+    vec_else_clause = reduc_def;
+  else
+    vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
 
   /* Arguments are ready. Create the new vector stmt.  */
   vec_compare = build2 (TREE_CODE (cond_expr), vectype, 
@@ -3898,6 +3948,14 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
       print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
     }
 
+  if (gimple_has_volatile_ops (stmt))
+    {    
+      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+        fprintf (vect_dump, "not vectorized: stmt has volatile operands");
+
+      return false;
+    }
   /* Skip stmts that do not need to be vectorized. In loops this is expected 
      to include:
      - the COND_EXPR which is the loop exit condition
@@ -3921,6 +3979,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
         break;
 
       case vect_reduction_def:
+      case vect_nested_cycle:
          gcc_assert (!bb_vinfo && (relevance == vect_used_in_outer
                      || relevance == vect_used_in_outer_by_reduction
                      || relevance == vect_unused_in_scope));
@@ -3984,8 +4043,8 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
             || vectorizable_load (stmt, NULL, NULL, NULL, NULL)
             || vectorizable_call (stmt, NULL, NULL)
             || vectorizable_store (stmt, NULL, NULL, NULL)
-            || vectorizable_condition (stmt, NULL, NULL)
-            || vectorizable_reduction (stmt, NULL, NULL));
+            || vectorizable_reduction (stmt, NULL, NULL)
+            || vectorizable_condition (stmt, NULL, NULL, NULL, 0));
     else
       {
         if (bb_vinfo)
@@ -4126,7 +4185,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
 
     case condition_vec_info_type:
       gcc_assert (!slp_node);
-      done = vectorizable_condition (stmt, gsi, &vec_stmt);
+      done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0);
       gcc_assert (done);
       break;