OSDN Git Service

2008-03-23 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-patterns.c
index c9e34e3..c1ce14c 100644 (file)
@@ -1,12 +1,12 @@
 /* Analysis Utilities for Loop Vectorization.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
    Contributed by Dorit Nuzman <dorit@il.ibm.com>
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -109,10 +108,6 @@ widened_name_p (tree name, tree use_stmt, tree *half_type, tree *def_stmt)
   if (!vect_is_simple_use (oprnd0, loop_vinfo, &dummy, &dummy, &dt))
     return false;
 
-  if (dt != vect_invariant_def && dt != vect_constant_def
-      && dt != vect_loop_def)
-    return false;
-
   return true;
 }
 
@@ -153,7 +148,14 @@ widened_name_p (tree name, tree use_stmt, tree *half_type, tree *def_stmt)
    * Return value: A new stmt that will be used to replace the sequence of
    stmts that constitute the pattern. In this case it will be:
         WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
-*/
+
+   Note: The dot-prod idiom is a widening reduction pattern that is
+         vectorized without preserving all the intermediate results. It
+         produces only N/2 (widened) results (by summing up pairs of
+         intermediate results) rather than all N results.  Therefore, we
+         cannot allow this pattern when we want to get all the results and in
+         the correct order (as is the case when this computation is in an
+         inner-loop nested in an outer-loop that us being vectorized).  */
 
 static tree
 vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
@@ -165,6 +167,8 @@ vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
   tree type, half_type;
   tree pattern_expr;
   tree prod_type;
+  loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+  struct loop *loop = LOOP_VINFO_LOOP (loop_info);
 
   if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
     return NULL;
@@ -242,7 +246,10 @@ vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
 
   prod_type = half_type;
   stmt = SSA_NAME_DEF_STMT (oprnd0);
-  gcc_assert (stmt);
+  /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi 
+     inside the loop (in case we are analyzing an outer-loop).  */
+  if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+    return NULL; 
   stmt_vinfo = vinfo_for_stmt (stmt);
   gcc_assert (stmt_vinfo);
   if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_loop_def)
@@ -300,6 +307,16 @@ vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
       fprintf (vect_dump, "vect_recog_dot_prod_pattern: detected: ");
       print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
     }
+
+  /* We don't allow changing the order of the computation in the inner-loop
+     when doing outer-loop vectorization.  */
+  if (nested_in_vect_loop_p (loop, last_stmt))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        fprintf (vect_dump, "vect_recog_dot_prod_pattern: not allowed.");
+      return NULL;
+    }
+
   return pattern_expr;
 }
 
@@ -386,7 +403,8 @@ vect_recog_widen_mult_pattern (tree last_stmt,
 
   /* Check target support  */
   vectype = get_vectype_for_scalar_type (half_type0);
-  if (!supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, vectype,
+  if (!vectype
+      || !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, vectype,
                                        &dummy, &dummy, &dummy_code,
                                        &dummy_code))
     return NULL;
@@ -433,7 +451,7 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out)
 {
   tree expr;
   tree type;
-  tree fn, arglist, base, exp;
+  tree fn, base, exp;
 
   if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
     return NULL;
@@ -445,15 +463,14 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out)
     return NULL_TREE;
 
   fn = get_callee_fndecl (expr);
-  arglist = TREE_OPERAND (expr, 1);
   switch (DECL_FUNCTION_CODE (fn))
     {
     case BUILT_IN_POWIF:
     case BUILT_IN_POWI:
     case BUILT_IN_POWF:
     case BUILT_IN_POW:
-      base = TREE_VALUE (arglist);
-      exp = TREE_VALUE (TREE_CHAIN (arglist));
+      base = CALL_EXPR_ARG (expr, 0);
+      exp = CALL_EXPR_ARG (expr, 1);
       if (TREE_CODE (exp) != REAL_CST
          && TREE_CODE (exp) != INTEGER_CST)
         return NULL_TREE;
@@ -483,11 +500,10 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out)
       && REAL_VALUES_EQUAL (TREE_REAL_CST (exp), dconsthalf))
     {
       tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
-      tree newarglist = build_tree_list (NULL_TREE, base);
       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
       if (*type_in)
        {
-         newfn = build_function_call_expr (newfn, newarglist);
+         newfn = build_call_expr (newfn, 1, base);
          if (vectorizable_function (newfn, *type_in, *type_in) != NULL_TREE)
            return newfn;
        }
@@ -527,7 +543,14 @@ vect_recog_pow_pattern (tree last_stmt, tree *type_in, tree *type_out)
    * Return value: A new stmt that will be used to replace the sequence of
    stmts that constitute the pattern. In this case it will be:
         WIDEN_SUM <x_t, sum_0>
-*/
+
+   Note: The widening-sum idiom is a widening reduction pattern that is 
+        vectorized without preserving all the intermediate results. It
+         produces only N/2 (widened) results (by summing up pairs of 
+        intermediate results) rather than all N results.  Therefore, we 
+        cannot allow this pattern when we want to get all the results and in 
+        the correct order (as is the case when this computation is in an 
+        inner-loop nested in an outer-loop that us being vectorized).  */
 
 static tree
 vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
@@ -537,6 +560,8 @@ vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
   tree type, half_type;
   tree pattern_expr;
+  loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+  struct loop *loop = LOOP_VINFO_LOOP (loop_info);
 
   if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
     return NULL;
@@ -586,6 +611,16 @@ vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
       fprintf (vect_dump, "vect_recog_widen_sum_pattern: detected: ");
       print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
     }
+
+  /* We don't allow changing the order of the computation in the inner-loop
+     when doing outer-loop vectorization.  */
+  if (nested_in_vect_loop_p (loop, last_stmt))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        fprintf (vect_dump, "vect_recog_widen_sum_pattern: not allowed.");
+      return NULL;
+    }
+
   return pattern_expr;
 }
 
@@ -647,14 +682,18 @@ vect_pattern_recog_1 (
 
       /* Check target support  */
       pattern_vectype = get_vectype_for_scalar_type (type_in);
+      if (!pattern_vectype)
+        return;
+
       optab = optab_for_tree_code (TREE_CODE (pattern_expr), pattern_vectype);
       vec_mode = TYPE_MODE (pattern_vectype);
       if (!optab
-          || (icode = optab->handlers[(int) vec_mode].insn_code) ==
+          || (icode = optab_handler (optab, vec_mode)->insn_code) ==
               CODE_FOR_nothing
           || (type_out
-              && (insn_data[icode].operand[0].mode !=
-                  TYPE_MODE (get_vectype_for_scalar_type (type_out)))))
+              && (!get_vectype_for_scalar_type (type_out)
+                  || (insn_data[icode].operand[0].mode !=
+                      TYPE_MODE (get_vectype_for_scalar_type (type_out))))))
        return;
     }
 
@@ -672,8 +711,7 @@ vect_pattern_recog_1 (
   var = create_tmp_var (pattern_type, "patt");
   add_referenced_var (var);
   var_name = make_ssa_name (var, NULL_TREE);
-  pattern_expr = build2 (GIMPLE_MODIFY_STMT, void_type_node, var_name,
-                        pattern_expr);
+  pattern_expr = build_gimple_modify_stmt (var_name, pattern_expr);
   SSA_NAME_DEF_STMT (var_name) = pattern_expr;
   bsi_insert_before (&si, pattern_expr, BSI_SAME_STMT);
   ann = stmt_ann (pattern_expr);