OSDN Git Service

PR target/45250
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-patterns.c
index b2c1de2..0d5824c 100644 (file)
@@ -1,5 +1,5 @@
 /* Analysis Utilities for Loop Vectorization.
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
    Contributed by Dorit Nuzman <dorit@il.ibm.com>
 
 This file is part of GCC.
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "target.h"
 #include "basic-block.h"
-#include "diagnostic.h"
+#include "gimple-pretty-print.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "cfgloop.h"
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-data-ref.h"
 #include "tree-vectorizer.h"
 #include "recog.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 
 /* Function prototypes */
@@ -254,6 +255,11 @@ vect_recog_dot_prod_pattern (gimple last_stmt, tree *type_in, tree *type_out)
 
   prod_type = half_type;
   stmt = SSA_NAME_DEF_STMT (oprnd0);
+
+  /* It could not be the dot_prod pattern if the stmt is outside the loop.  */
+  if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
+    return NULL;
+
   /* 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 (!is_gimple_assign (stmt))
@@ -362,7 +368,7 @@ vect_recog_widen_mult_pattern (gimple last_stmt,
   tree oprnd0, oprnd1;
   tree type, half_type0, half_type1;
   gimple pattern_stmt;
-  tree vectype;
+  tree vectype, vectype_out;
   tree dummy;
   tree var;
   enum tree_code dummy_code;
@@ -405,14 +411,16 @@ vect_recog_widen_mult_pattern (gimple last_stmt,
 
   /* Check target support  */
   vectype = get_vectype_for_scalar_type (half_type0);
+  vectype_out = get_vectype_for_scalar_type (type);
   if (!vectype
-      || !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt, vectype,
+      || !supportable_widening_operation (WIDEN_MULT_EXPR, last_stmt,
+                                         vectype_out, vectype,
                                          &dummy, &dummy, &dummy_code,
                                          &dummy_code, &dummy_int, &dummy_vec))
     return NULL;
 
   *type_in = vectype;
-  *type_out = NULL_TREE;
+  *type_out = vectype_out;
 
   /* Pattern supported. Create a stmt to be used to replace the pattern: */
   var = vect_recog_temp_ssa_var (type, NULL);
@@ -456,7 +464,6 @@ vect_recog_widen_mult_pattern (gimple last_stmt,
 static gimple
 vect_recog_pow_pattern (gimple last_stmt, tree *type_in, tree *type_out)
 {
-  tree type;
   tree fn, base, exp = NULL;
   gimple stmt;
   tree var;
@@ -464,8 +471,6 @@ vect_recog_pow_pattern (gimple last_stmt, tree *type_in, tree *type_out)
   if (!is_gimple_call (last_stmt) || gimple_call_lhs (last_stmt) == NULL)
     return NULL;
 
-  type = gimple_expr_type (last_stmt);
-
   fn = gimple_call_fndecl (last_stmt);
   switch (DECL_FUNCTION_CODE (fn))
     {
@@ -671,6 +676,8 @@ vect_pattern_recog_1 (
   tree pattern_vectype;
   tree type_in, type_out;
   enum tree_code code;
+  int i;
+  gimple next;
 
   pattern_stmt = (* vect_recog_func) (stmt, &type_in, &type_out);
   if (!pattern_stmt)
@@ -680,7 +687,9 @@ vect_pattern_recog_1 (
     {
       /* No need to check target support (already checked by the pattern
          recognition function).  */
-      pattern_vectype = type_in;
+      if (type_out)
+       gcc_assert (VECTOR_MODE_P (TYPE_MODE (type_out)));
+      pattern_vectype = type_out ? type_out : type_in;
     }
   else
     {
@@ -689,9 +698,16 @@ vect_pattern_recog_1 (
       optab optab;
 
       /* Check target support  */
-      pattern_vectype = get_vectype_for_scalar_type (type_in);
-      if (!pattern_vectype)
-        return;
+      type_in = get_vectype_for_scalar_type (type_in);
+      if (!type_in)
+       return;
+      if (type_out)
+       type_out = get_vectype_for_scalar_type (type_out);
+      else
+       type_out = type_in;
+      if (!type_out)
+       return;
+      pattern_vectype = type_out;
 
       if (is_gimple_assign (pattern_stmt))
        code = gimple_assign_rhs_code (pattern_stmt);
@@ -701,15 +717,11 @@ vect_pattern_recog_1 (
          code = CALL_EXPR;
        }
 
-      optab = optab_for_tree_code (code, pattern_vectype, optab_default);
-      vec_mode = TYPE_MODE (pattern_vectype);
+      optab = optab_for_tree_code (code, type_in, optab_default);
+      vec_mode = TYPE_MODE (type_in);
       if (!optab
-          || (icode = optab_handler (optab, vec_mode)->insn_code) ==
-              CODE_FOR_nothing
-          || (type_out
-              && (!get_vectype_for_scalar_type (type_out)
-                  || (insn_data[icode].operand[0].mode !=
-                      TYPE_MODE (get_vectype_for_scalar_type (type_out))))))
+          || (icode = optab_handler (optab, vec_mode)) == CODE_FOR_nothing
+          || (insn_data[icode].operand[0].mode != TYPE_MODE (type_out)))
        return;
     }
 
@@ -732,7 +744,11 @@ vect_pattern_recog_1 (
   STMT_VINFO_IN_PATTERN_P (stmt_info) = true;
   STMT_VINFO_RELATED_STMT (stmt_info) = pattern_stmt;
 
-  return;
+  /* Patterns cannot be vectorized using SLP, because they change the order of
+     computation.  */
+  FOR_EACH_VEC_ELT (gimple, LOOP_VINFO_REDUCTIONS (loop_vinfo), i, next)
+    if (next == stmt)
+      VEC_ordered_remove (gimple, LOOP_VINFO_REDUCTIONS (loop_vinfo), i); 
 }
 
 
@@ -812,7 +828,6 @@ vect_pattern_recog (loop_vec_info loop_vinfo)
   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
   unsigned int nbbs = loop->num_nodes;
   gimple_stmt_iterator si;
-  gimple stmt;
   unsigned int i, j;
   gimple (* vect_recog_func_ptr) (gimple, tree *, tree *);
 
@@ -826,8 +841,6 @@ vect_pattern_recog (loop_vec_info loop_vinfo)
       basic_block bb = bbs[i];
       for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
         {
-          stmt = gsi_stmt (si);
-
           /* Scan over all generic vect_recog_xxx_pattern functions.  */
           for (j = 0; j < NUM_PATTERNS; j++)
             {