To get desired transforms from tree-ssa-forwprop.c which uses
fold_stmt.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2014-09-15  Richard Biener  <rguent...@suse.de>

        * gimple-fold.c: Include tree-eh.c.
        (fold_stmt_1): Handle GIMPLE_CONDs for gimple_simplify.
        * gimple-match-head.c (gimple_simplify): Likewise.
        * match-comparison.pd (bool != 0): Avoid some churn on
        GIMPLE and amend comment.

Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c   (revision 215212)
+++ gcc/gimple-fold.c   (working copy)
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.
 #include "dbgcnt.h"
 #include "builtins.h"
 #include "output.h"
+#include "tree-eh.h"
 #include "gimple-match.h"
 
 
@@ -2881,15 +2882,67 @@ fold_stmt_1 (gimple_stmt_iterator *gsi,
      no further stmts need to be inserted (basically disallow
      creating of new SSA names).  */
   if (!inplace
-      || is_gimple_assign (stmt))
+      || is_gimple_assign (stmt)
+      || gimple_code (stmt) == GIMPLE_COND)
     {
       gimple_seq seq = NULL;
       code_helper rcode;
       tree ops[3] = {};
       if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize))
        {
-         if (is_gimple_assign (stmt)
-             && rcode.is_tree_code ())
+         if (gimple_code (stmt) == GIMPLE_COND)
+           {
+             gcc_assert (rcode.is_tree_code ());
+             if (TREE_CODE_CLASS ((enum tree_code)rcode) == tcc_comparison
+                 /* GIMPLE_CONDs condition may not throw.  */
+                 /* ???  Not sure how we want to deal with combining
+                    from possibly throwing statements.  Trivial
+                    simplifications may lead to DCEing an internal
+                    throw.  But we probably still want to simplify
+                    things to a constant for example?  Similar to
+                    abnormals we could discard the simplification
+                    result if we ever push a could-throw stmt to
+                    the sequence.  */
+                 && (!flag_exceptions
+                     || !cfun->can_throw_non_call_exceptions
+                     || !operation_could_trap_p (rcode, FLOAT_TYPE_P 
(TREE_TYPE (ops[0])), false, NULL_TREE)))
+               gimple_cond_set_condition (stmt, rcode, ops[0], ops[1]);
+             else if (rcode == SSA_NAME)
+               gimple_cond_set_condition (stmt, NE_EXPR, ops[0],
+                                          build_zero_cst (TREE_TYPE (ops[0])));
+             else if (rcode == INTEGER_CST)
+               {
+                 if (integer_zerop (ops[0]))
+                   gimple_cond_make_false (stmt);
+                 else
+                   gimple_cond_make_true (stmt);
+               }
+             else if (!inplace)
+               {
+                 tree res = maybe_push_res_to_seq (rcode, boolean_type_node,
+                                                   ops, &seq);
+                 if (!res)
+                   goto fail;
+                 gimple_cond_set_condition (stmt, NE_EXPR, res,
+                                            build_zero_cst (TREE_TYPE (res)));
+               }
+             else
+               goto fail;
+             if (dump_file && (dump_flags & TDF_DETAILS))
+               {
+                 fprintf (dump_file, "gimple_simplified to ");
+                 if (!gimple_seq_empty_p (seq))
+                   print_gimple_seq (dump_file, seq, 0, TDF_SLIM);
+                 print_gimple_stmt (dump_file, gsi_stmt (*gsi),
+                                    0, TDF_SLIM);
+               }
+             gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+             changed = true;
+fail:
+             ;
+           }
+         else if (is_gimple_assign (stmt)
+                  && rcode.is_tree_code ())
            {
              if ((!inplace
                   || gimple_num_ops (stmt) <= get_gimple_rhs_num_ops (rcode))
Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c     (revision 215212)
+++ gcc/gimple-match-head.c     (working copy)
@@ -573,213 +573,244 @@ gimple_simplify (gimple stmt,
                 code_helper *rcode, tree *ops,
                 gimple_seq *seq, tree (*valueize)(tree))
 {
-  if (is_gimple_assign (stmt))
+  switch (gimple_code (stmt))
     {
-      enum tree_code code = gimple_assign_rhs_code (stmt);
-      tree type = TREE_TYPE (gimple_assign_lhs (stmt));
-      switch (gimple_assign_rhs_class (stmt))
-       {
-       case GIMPLE_SINGLE_RHS:
-         if (code == REALPART_EXPR
-             || code == IMAGPART_EXPR
-             || code == VIEW_CONVERT_EXPR)
+    case GIMPLE_ASSIGN:
+      {
+       enum tree_code code = gimple_assign_rhs_code (stmt);
+       tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+       switch (gimple_assign_rhs_class (stmt))
+         {
+         case GIMPLE_SINGLE_RHS:
+           if (code == REALPART_EXPR
+               || code == IMAGPART_EXPR
+               || code == VIEW_CONVERT_EXPR)
+             {
+               tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+               if (valueize && TREE_CODE (op0) == SSA_NAME)
+                 {
+                   op0 = valueize (op0);
+                   if (!op0)
+                     return false;
+                 }
+               *rcode = code;
+               ops[0] = op0;
+               return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+             }
+           else if (code == BIT_FIELD_REF)
+             {
+               tree rhs1 = gimple_assign_rhs1 (stmt);
+               tree op0 = TREE_OPERAND (rhs1, 0);
+               if (valueize && TREE_CODE (op0) == SSA_NAME)
+                 {
+                   op0 = valueize (op0);
+                   if (!op0)
+                     return false;
+                 }
+               *rcode = code;
+               ops[0] = op0;
+               ops[1] = TREE_OPERAND (rhs1, 1);
+               ops[2] = TREE_OPERAND (rhs1, 2);
+               return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+             }
+           else if (code == SSA_NAME
+                    && valueize)
+             {
+               tree op0 = gimple_assign_rhs1 (stmt);
+               tree valueized = valueize (op0);
+               if (!valueized || op0 == valueized)
+                 return false;
+               ops[0] = valueized;
+               *rcode = TREE_CODE (op0);
+               return true;
+             }
+           break;
+         case GIMPLE_UNARY_RHS:
            {
-             tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
-             if (valueize && TREE_CODE (op0) == SSA_NAME)
+             tree rhs1 = gimple_assign_rhs1 (stmt);
+             if (valueize && TREE_CODE (rhs1) == SSA_NAME)
                {
-                 op0 = valueize (op0);
-                 if (!op0)
+                 rhs1 = valueize (rhs1);
+                 if (!rhs1)
                    return false;
                }
              *rcode = code;
-             ops[0] = op0;
+             ops[0] = rhs1;
              return gimple_resimplify1 (seq, rcode, type, ops, valueize);
            }
-         else if (code == BIT_FIELD_REF)
+         case GIMPLE_BINARY_RHS:
            {
              tree rhs1 = gimple_assign_rhs1 (stmt);
-             tree op0 = TREE_OPERAND (rhs1, 0);
-             if (valueize && TREE_CODE (op0) == SSA_NAME)
+             if (valueize && TREE_CODE (rhs1) == SSA_NAME)
                {
-                 op0 = valueize (op0);
-                 if (!op0)
+                 rhs1 = valueize (rhs1);
+                 if (!rhs1)
+                   return false;
+               }
+             tree rhs2 = gimple_assign_rhs2 (stmt);
+             if (valueize && TREE_CODE (rhs2) == SSA_NAME)
+               {
+                 rhs2 = valueize (rhs2);
+                 if (!rhs2)
                    return false;
                }
              *rcode = code;
-             ops[0] = op0;
-             ops[1] = TREE_OPERAND (rhs1, 1);
-             ops[2] = TREE_OPERAND (rhs1, 2);
-             return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+             ops[0] = rhs1;
+             ops[1] = rhs2;
+             return gimple_resimplify2 (seq, rcode, type, ops, valueize);
            }
-         else if (code == SSA_NAME
-                  && valueize)
+         case GIMPLE_TERNARY_RHS:
            {
-             tree op0 = gimple_assign_rhs1 (stmt);
-             tree valueized = valueize (op0);
-             if (!valueized || op0 == valueized)
-               return false;
-             ops[0] = valueized;
-             *rcode = TREE_CODE (op0);
-             return true;
+             tree rhs1 = gimple_assign_rhs1 (stmt);
+             if (valueize && TREE_CODE (rhs1) == SSA_NAME)
+               {
+                 rhs1 = valueize (rhs1);
+                 if (!rhs1)
+                   return false;
+               }
+             tree rhs2 = gimple_assign_rhs2 (stmt);
+             if (valueize && TREE_CODE (rhs2) == SSA_NAME)
+               {
+                 rhs2 = valueize (rhs2);
+                 if (!rhs2)
+                   return false;
+               }
+             tree rhs3 = gimple_assign_rhs3 (stmt);
+             if (valueize && TREE_CODE (rhs3) == SSA_NAME)
+               {
+                 rhs3 = valueize (rhs3);
+                 if (!rhs3)
+                   return false;
+               }
+             *rcode = code;
+             ops[0] = rhs1;
+             ops[1] = rhs2;
+             ops[2] = rhs3;
+             return gimple_resimplify3 (seq, rcode, type, ops, valueize);
            }
-         break;
-       case GIMPLE_UNARY_RHS:
-         {
-           tree rhs1 = gimple_assign_rhs1 (stmt);
-           if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-             {
-               rhs1 = valueize (rhs1);
-               if (!rhs1)
-                 return false;
-             }
-           *rcode = code;
-           ops[0] = rhs1;
-           return gimple_resimplify1 (seq, rcode, type, ops, valueize);
-         }
-       case GIMPLE_BINARY_RHS:
-         {
-           tree rhs1 = gimple_assign_rhs1 (stmt);
-           if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-             {
-               rhs1 = valueize (rhs1);
-               if (!rhs1)
-                 return false;
-             }
-           tree rhs2 = gimple_assign_rhs2 (stmt);
-           if (valueize && TREE_CODE (rhs2) == SSA_NAME)
-             {
-               rhs2 = valueize (rhs2);
-               if (!rhs2)
-                 return false;
-             }
-           *rcode = code;
-           ops[0] = rhs1;
-           ops[1] = rhs2;
-           return gimple_resimplify2 (seq, rcode, type, ops, valueize);
-         }
-       case GIMPLE_TERNARY_RHS:
-         {
-           tree rhs1 = gimple_assign_rhs1 (stmt);
-           if (valueize && TREE_CODE (rhs1) == SSA_NAME)
-             {
-               rhs1 = valueize (rhs1);
-               if (!rhs1)
-                 return false;
-             }
-           tree rhs2 = gimple_assign_rhs2 (stmt);
-           if (valueize && TREE_CODE (rhs2) == SSA_NAME)
-             {
-               rhs2 = valueize (rhs2);
-               if (!rhs2)
-                 return false;
-             }
-           tree rhs3 = gimple_assign_rhs3 (stmt);
-           if (valueize && TREE_CODE (rhs3) == SSA_NAME)
-             {
-               rhs3 = valueize (rhs3);
-               if (!rhs3)
-                 return false;
-             }
-           *rcode = code;
-           ops[0] = rhs1;
-           ops[1] = rhs2;
-           ops[2] = rhs3;
-           return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+         default:
+           gcc_unreachable ();
          }
-       default:
-         gcc_unreachable ();
-       }
-    }
-  else if (is_gimple_call (stmt)
-          /* ???  This way we can't simplify calls with side-effects.  */
-          && gimple_call_lhs (stmt) != NULL_TREE)
-    {
-      tree fn = gimple_call_fn (stmt);
-      /* ???  Internal function support missing.  */
-      if (!fn)
-       return false;
-      if (TREE_CODE (fn) == SSA_NAME
-         && valueize)
-       fn = valueize (fn);
-      if (!fn
-         || TREE_CODE (fn) != ADDR_EXPR
-         || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
-         || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
-         || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
-         || !gimple_builtin_call_types_compatible_p (stmt,
-                                                     TREE_OPERAND (fn, 0)))
-       return false;
+       break;
+      }
 
-      tree decl = TREE_OPERAND (fn, 0);
-      tree type = TREE_TYPE (gimple_call_lhs (stmt));
-      switch (gimple_call_num_args (stmt))
+    case GIMPLE_CALL:
+      /* ???  This way we can't simplify calls with side-effects.  */
+      if (gimple_call_lhs (stmt) != NULL_TREE)
        {
-       case 1:
-         {
-           tree arg1 = gimple_call_arg (stmt, 0);
-           if (valueize && TREE_CODE (arg1) == SSA_NAME)
-             {
-               arg1 = valueize (arg1);
-               if (!arg1)
-                 return false;
-             }
-           *rcode = DECL_FUNCTION_CODE (decl);
-           ops[0] = arg1;
-           return gimple_resimplify1 (seq, rcode, type, ops, valueize);
-         }
-       case 2:
-         {
-           tree arg1 = gimple_call_arg (stmt, 0);
-           if (valueize && TREE_CODE (arg1) == SSA_NAME)
-             {
-               arg1 = valueize (arg1);
-               if (!arg1)
-                 return false;
-             }
-           tree arg2 = gimple_call_arg (stmt, 1);
-           if (valueize && TREE_CODE (arg2) == SSA_NAME)
-             {
-               arg2 = valueize (arg2);
-               if (!arg2)
-                 return false;
-             }
-           *rcode = DECL_FUNCTION_CODE (decl);
-           ops[0] = arg1;
-           ops[1] = arg2;
-           return gimple_resimplify2 (seq, rcode, type, ops, valueize);
-         }
-       case 3:
-         {
-           tree arg1 = gimple_call_arg (stmt, 0);
-           if (valueize && TREE_CODE (arg1) == SSA_NAME)
-             {
-               arg1 = valueize (arg1);
-               if (!arg1)
-                 return false;
-             }
-           tree arg2 = gimple_call_arg (stmt, 1);
-           if (valueize && TREE_CODE (arg2) == SSA_NAME)
-             {
-               arg2 = valueize (arg2);
-               if (!arg2)
-                 return false;
-             }
-           tree arg3 = gimple_call_arg (stmt, 2);
-           if (valueize && TREE_CODE (arg3) == SSA_NAME)
+         tree fn = gimple_call_fn (stmt);
+         /* ???  Internal function support missing.  */
+         if (!fn)
+           return false;
+         if (TREE_CODE (fn) == SSA_NAME
+             && valueize)
+           fn = valueize (fn);
+         if (!fn
+             || TREE_CODE (fn) != ADDR_EXPR
+             || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
+             || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
+             || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 
0)))
+             || !gimple_builtin_call_types_compatible_p (stmt,
+                                                         TREE_OPERAND (fn, 0)))
+           return false;
+
+         tree decl = TREE_OPERAND (fn, 0);
+         tree type = TREE_TYPE (gimple_call_lhs (stmt));
+         switch (gimple_call_num_args (stmt))
+           {
+           case 1:
              {
-               arg3 = valueize (arg3);
-               if (!arg3)
-                 return false;
+               tree arg1 = gimple_call_arg (stmt, 0);
+               if (valueize && TREE_CODE (arg1) == SSA_NAME)
+                 {
+                   arg1 = valueize (arg1);
+                   if (!arg1)
+                     return false;
+                 }
+               *rcode = DECL_FUNCTION_CODE (decl);
+               ops[0] = arg1;
+               return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+             }
+           case 2:
+             {
+               tree arg1 = gimple_call_arg (stmt, 0);
+               if (valueize && TREE_CODE (arg1) == SSA_NAME)
+                 {
+                   arg1 = valueize (arg1);
+                   if (!arg1)
+                     return false;
+                 }
+               tree arg2 = gimple_call_arg (stmt, 1);
+               if (valueize && TREE_CODE (arg2) == SSA_NAME)
+                 {
+                   arg2 = valueize (arg2);
+                   if (!arg2)
+                     return false;
+                 }
+               *rcode = DECL_FUNCTION_CODE (decl);
+               ops[0] = arg1;
+               ops[1] = arg2;
+               return gimple_resimplify2 (seq, rcode, type, ops, valueize);
+             }
+           case 3:
+             {
+               tree arg1 = gimple_call_arg (stmt, 0);
+               if (valueize && TREE_CODE (arg1) == SSA_NAME)
+                 {
+                   arg1 = valueize (arg1);
+                   if (!arg1)
+                     return false;
+                 }
+               tree arg2 = gimple_call_arg (stmt, 1);
+               if (valueize && TREE_CODE (arg2) == SSA_NAME)
+                 {
+                   arg2 = valueize (arg2);
+                   if (!arg2)
+                     return false;
+                 }
+               tree arg3 = gimple_call_arg (stmt, 2);
+               if (valueize && TREE_CODE (arg3) == SSA_NAME)
+                 {
+                   arg3 = valueize (arg3);
+                   if (!arg3)
+                     return false;
+                 }
+               *rcode = DECL_FUNCTION_CODE (decl);
+               ops[0] = arg1;
+               ops[1] = arg2;
+               ops[2] = arg3;
+               return gimple_resimplify3 (seq, rcode, type, ops, valueize);
              }
-           *rcode = DECL_FUNCTION_CODE (decl);
-           ops[0] = arg1;
-           ops[1] = arg2;
-           ops[2] = arg3;
-           return gimple_resimplify3 (seq, rcode, type, ops, valueize);
-         }
-       default:
-         return false;
+           default:
+             return false;
+           }
        }
+      break;
+
+    case GIMPLE_COND:
+      {
+       tree lhs = gimple_cond_lhs (stmt);
+       if (valueize && TREE_CODE (lhs) == SSA_NAME)
+         {
+           lhs = valueize (lhs);
+           if (!lhs)
+             return false;
+         }
+       tree rhs = gimple_cond_rhs (stmt);
+       if (valueize && TREE_CODE (rhs) == SSA_NAME)
+         {
+           rhs = valueize (rhs);
+           if (!rhs)
+             return false;
+         }
+       *rcode = gimple_cond_code (stmt);
+       ops[0] = lhs;
+       ops[1] = rhs;
+        return gimple_resimplify2 (seq, rcode, boolean_type_node, ops, 
valueize);
+      }
+
+    default:
+      break;
     }
 
   return false;
Index: gcc/match-comparison.pd
===================================================================
--- gcc/match-comparison.pd     (revision 215212)
+++ gcc/match-comparison.pd     (working copy)
@@ -1,10 +1,18 @@
 /* From fold_binary.  */
 
+/* On GIMPLE bool != 0 is simply the canonical way to express a
+   condition in COND_EXPRs and GIMPLE_CONDs.
+   ???  Of course for assignments we still may want to strip those...  */
 (simplify
  (ne @0 integer_zerop@1)
  (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE)
-  /* ???  In GENERIC the type of the comparison may be 'int'.  */
-  (convert @0)))
+  /* On GENERIC comparisons can have arbitrary integer types.  */
+  (if (GENERIC)
+    (convert @0))
+  /* On GIMPLE boolean types may have a precision != 1 thus the
+     comparison serves as a more canonical required conversion.  */
+  (if (GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@0)))
+    @0)))
 
 /* Distribute operations in equality compares.  */
 (for op (eq ne)

Reply via email to