OSDN Git Service

Changlog libcpp
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-stmts.c
index 586e906..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);
@@ -331,7 +334,7 @@ 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))
     {
@@ -341,7 +344,8 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
       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;
 
@@ -393,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 ===");
@@ -465,49 +470,64 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
         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.  */
 
-      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_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 */
 
-           default:
-             if (vect_print_dump_info (REPORT_DETAILS))
-               fprintf (vect_dump, "unsupported use of reduction.");
-             VEC_free (gimple, heap, worklist);
-             return false;
-           }
+               default:
+                 if (vect_print_dump_info (REPORT_DETAILS))
+                   fprintf (vect_dump, "unsupported use of reduction.");
 
-         live_p = false;       
-       }
-      else if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_nested_cycle)
-        {
-          enum vect_relevant tmp_relevant = relevant;
-          switch (tmp_relevant)
-            {
-              case vect_unused_in_scope:
-              case vect_used_in_outer_by_reduction:
-              case vect_used_in_outer:
-                break;
+                 VEC_free (gimple, heap, worklist);
+                 return false;
+             }
 
-              default:
+           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.");
 
-          live_p = false; 
+                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)
@@ -974,6 +994,7 @@ 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;
@@ -1209,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;
@@ -1349,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);
            }
@@ -1388,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);
@@ -3617,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;
                }
            }
@@ -3757,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;
@@ -3792,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.  */
@@ -3800,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.");
@@ -3860,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 */
@@ -3874,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, 
@@ -3910,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
@@ -3997,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)
@@ -4139,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;