OSDN Git Service

PR c++/35325
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ifcombine.c
index 89fd61d..cec5868 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"
@@ -167,17 +166,22 @@ 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)
          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 +191,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 = orig_name;
        }
 
       return true;
@@ -308,13 +312,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 +406,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 +483,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 +605,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 +623,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 */
+ }
 };