OSDN Git Service

* tree-ssa-ifcombine.c (get_name_for_bit_test): Use
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ifcombine.c
index 89fd61d..93e7810 100644 (file)
@@ -6,7 +6,7 @@ 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ MERCHANTABILITY or 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"
@@ -136,6 +135,31 @@ same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
   return true;
 }
 
+/* Return the best representative SSA name for CANDIDATE which is used
+   in a bit test.  */
+
+static tree
+get_name_for_bit_test (tree candidate)
+{
+  /* Skip single-use names in favor of using the name from a
+     non-widening conversion definition.  */
+  if (TREE_CODE (candidate) == SSA_NAME
+      && has_single_use (candidate))
+    {
+      tree def_stmt = SSA_NAME_DEF_STMT (candidate);
+      if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
+         && CONVERT_EXPR_P (GIMPLE_STMT_OPERAND (def_stmt, 1)))
+       {
+         tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+         if (TYPE_PRECISION (TREE_TYPE (rhs))
+             <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (rhs, 0))))
+           return TREE_OPERAND (rhs, 0);
+       }
+    }
+
+  return candidate;
+}
+
 /* Recognize a single bit test pattern in COND_EXPR and its defining
    statements.  Store the name being tested in *NAME and the bit
    in *BIT.  The COND_EXPR computes *NAME & (1 << *BIT).
@@ -167,17 +191,21 @@ recognize_single_bit_test (tree cond_expr, tree *name, tree *bit)
       && integer_onep (TREE_OPERAND (t, 1))
       && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME)
     {
-      t = TREE_OPERAND (t, 0);
+      tree orig_name = TREE_OPERAND (t, 0);
+
+      /* Look through copies and conversions to eventually
+        find the stmt that computes the shift.  */
+      t = orig_name;
       do {
        t = SSA_NAME_DEF_STMT (t);
        if (TREE_CODE (t) != GIMPLE_MODIFY_STMT)
-         return false;
+         break;
        t = GIMPLE_STMT_OPERAND (t, 1);
-       if (TREE_CODE (t) == NOP_EXPR
-           || TREE_CODE (t) == CONVERT_EXPR)
+       if (CONVERT_EXPR_P (t))
          t = TREE_OPERAND (t, 0);
       } while (TREE_CODE (t) == SSA_NAME);
 
+      /* If we found such, decompose it.  */
       if (TREE_CODE (t) == RSHIFT_EXPR)
        {
          /* op0 & (1 << op1) */
@@ -187,8 +215,8 @@ recognize_single_bit_test (tree cond_expr, tree *name, tree *bit)
       else
        {
          /* t & 1 */
-         *bit = integer_one_node;
-         *name = t;
+         *bit = integer_zero_node;
+         *name = get_name_for_bit_test (orig_name);
        }
 
       return true;
@@ -268,7 +296,7 @@ recognize_bits_test (tree cond_expr, tree *name, tree *bits)
   if (TREE_CODE (t) != BIT_AND_EXPR)
     return false;
 
-  *name = TREE_OPERAND (t, 0);
+  *name = get_name_for_bit_test (TREE_OPERAND (t, 0));
   *bits = TREE_OPERAND (t, 1);
 
   return true;
@@ -308,13 +336,15 @@ ifcombine_ifandif (basic_block inner_cond_bb, basic_block outer_cond_bb)
       /* Do it.  */
       bsi = bsi_for_stmt (inner_cond);
       t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
-                      integer_one_node, bit1);
+                      build_int_cst (TREE_TYPE (name1), 1), bit1);
       t2 = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
-                       integer_one_node, bit2);
+                       build_int_cst (TREE_TYPE (name1), 1), bit2);
       t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), t, t2);
-      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+                                   true, BSI_SAME_STMT);
       t2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
-      t2 = force_gimple_operand_bsi (&bsi, t2, true, NULL_TREE);
+      t2 = force_gimple_operand_bsi (&bsi, t2, true, NULL_TREE,
+                                    true, BSI_SAME_STMT);
       COND_EXPR_COND (inner_cond) = fold_build2 (EQ_EXPR, boolean_type_node,
                                                 t2, t);
       update_stmt (inner_cond);
@@ -400,9 +430,11 @@ ifcombine_iforif (basic_block inner_cond_bb, basic_block outer_cond_bb)
       /* Do it.  */
       bsi = bsi_for_stmt (inner_cond);
       t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), bits1, bits2);
-      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+                                   true, BSI_SAME_STMT);
       t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
-      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+      t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+                                   true, BSI_SAME_STMT);
       COND_EXPR_COND (inner_cond) = fold_build2 (NE_EXPR, boolean_type_node, t,
                                                 build_int_cst (TREE_TYPE (t), 0));
       update_stmt (inner_cond);
@@ -475,6 +507,9 @@ ifcombine_iforif (basic_block inner_cond_bb, basic_block outer_cond_bb)
       /* Do it.  */
       t = fold_build2 (code, boolean_type_node,
                       TREE_OPERAND (ccond2, 0), TREE_OPERAND (ccond2, 1));
+      t = canonicalize_cond_expr_cond (t);
+      if (!t)
+       return false;
       COND_EXPR_COND (inner_cond) = t;
       update_stmt (inner_cond);
 
@@ -594,7 +629,10 @@ gate_ifcombine (void)
   return 1;
 }
 
-struct tree_opt_pass pass_tree_ifcombine = {
+struct gimple_opt_pass pass_tree_ifcombine = 
+{
+ {
+  GIMPLE_PASS,
   "ifcombine",                 /* name */
   gate_ifcombine,              /* gate */
   tree_ssa_ifcombine,          /* execute */
@@ -609,6 +647,6 @@ struct tree_opt_pass pass_tree_ifcombine = {
   TODO_dump_func
   | TODO_ggc_collect
   | TODO_update_ssa
-  | TODO_verify_ssa,           /* todo_flags_finish */
-  0                            /* letter */
+  | TODO_verify_ssa            /* todo_flags_finish */
+ }
 };