Hello,

this patch ensures that after gimplification also comparison expressions using 
FE's boolean_type_node.  As we need to deal here with C/C++'s (obj-c/c++ and 
java's), Ada's, and Fortran's specific boolean types, this patch alters some 
checks in tree-cfg for Ada's sake, and we need to deal in fold-const about 
type-conversion of comparisons special.
Additionally it takes care that in forwprop pass we don't do type hoising for 
boolean types.

ChangeLog

2011-05-26  Kai Tietz

          * gimplify.c (gimple_boolify): Boolify all comparison
          expressions.
          (gimplify_expr): Use 'useless_type_conversion_p' for comparing
          org_type with boolean_type_node for TRUTH-expressions and comparisons.
          * fold-const.c (fold_unary_loc): Handle comparison conversions with
          boolean-type special.
          * tree-cfg.c (verify_gimple_comparison): Adjust check for boolean
          or compatible types.
          (verify_gimple_assign_unary): Likewise.
          * tree-ssa-forwprop.c (forward_propagate_comparison): Handle
          boolean case special.

Tested on x86_64-pc-linux-gnu (multilib) with regression test for all standard 
languages (C, C++, Obj-C, Fortran, Java) plus Obj-C++ and Ada. Ok for apply?

The following tests are failing due this change (what is to be expected here 
and needs some additional handling in forwprop).
FAIL: gcc.dg/binop-xor1.c scan-tree-dump-times optimized "<bb[^>]*>" 5
FAIL: gcc.dg/binop-xor1.c scan-tree-dump-times optimized "\^" 1
FAIL: gcc.dg/binop-xor3.c scan-tree-dump-times optimized "<bb[^>]*>" 1
FAIL: gcc.dg/binop-xor3.c scan-tree-dump-times optimized "\^" 1
XPASS: gcc.dg/tree-ssa/20030807-7.c scan-tree-dump-times vrp1 "if " 1
FAIL: gcc.dg/tree-ssa/builtin-expect-5.c scan-tree-dump forwprop1 
"builtin_expect[^\n]*, 1\);\n[^\n]*if"
FAIL: gcc.dg/tree-ssa/pr21031.c scan-tree-dump-times forwprop1 "Replaced" 2
FAIL: gcc.dg/tree-ssa/pr30978.c scan-tree-dump optimized "e_. = a_..D. > 0;"
FAIL: gcc.dg/tree-ssa/ssa-fre-6.c scan-tree-dump-times fre1 "Replaced " 5
FAIL: gcc.dg/tree-ssa/vrp47.c scan-tree-dump-times dom1 "x[^ ]* & y" 1
FAIL: gcc.dg/tree-ssa/vrp47.c scan-tree-dump-times vrp1 "x[^ ]* \^ 1" 1
FAIL: gcc.dg/vect/pr49038.c execution test
FAIL: gcc.dg/vect/pr49038.c -flto execution test
FAIL: gcc.target/i386/andor-2.c scan-assembler-not sete

The Ada, Obj-C, Obj-C++, C++, Fortran, and Java testsuite don't show any new 
regressions by this.

Some failing testcases are simply caused by different folding behavior and 
producing simplier code.  The binop-xor tests 1 and 3 might be better removed 
for now, or marked as being expect to fail. The cause for their failing is in 
doing tree-analysis via fold-const on gimplified trees, which now don't allow 
folding here to look through.
To illustrate required changes for other tests, I attach here some required 
changes for testsuite

Index: gcc.dg/tree-ssa/pr30978.c
===================================================================
--- gcc.dg/tree-ssa/pr30978.c   (revision 174264)
+++ gcc.dg/tree-ssa/pr30978.c   (working copy)
@@ -10,5 +10,5 @@
   return e;
 }

-/* { dg-final { scan-tree-dump "e_. = a_..D. > 0;" "optimized" } } */
+/* { dg-final { scan-tree-dump " = a_..D. > 0;\n[^\n]*e_. = \\\(int\\\)" 
"optimized" } } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */

Index: gcc.dg/tree-ssa/builtin-expect-5.c
===================================================================
--- gcc.dg/tree-ssa/builtin-expect-5.c  (revision 174264)
+++ gcc.dg/tree-ssa/builtin-expect-5.c  (working copy)
@@ -11,5 +11,5 @@

 /* { dg-final { scan-tree-dump-times { if } 2 "forwprop1"} } */
 /* { dg-final { scan-tree-dump {builtin_expect[^\n]*, 0\);\n[^\n]*if} 
"forwprop1"} } */
-/* { dg-final { scan-tree-dump {builtin_expect[^\n]*, 1\);\n[^\n]*if} 
"forwprop1"} } */
+/* { dg-final { scan-tree-dump {builtin_expect[^\n]*, 1\);} "forwprop1"} } */
 /* { dg-final { cleanup-tree-dump "forwprop?" } } */

Index: gcc.dg/tree-ssa/pr21031.c
===================================================================
--- gcc.dg/tree-ssa/pr21031.c   (revision 174264)
+++ gcc.dg/tree-ssa/pr21031.c   (working copy)
@@ -16,5 +16,5 @@
     return 0;
 }

-/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "Replaced" 1 "forwprop1"} } */
 /* { dg-final { cleanup-tree-dump "forwprop1" } } */

Index: gcc.dg/tree-ssa/ssa-fre-6.c
===================================================================
--- gcc.dg/tree-ssa/ssa-fre-6.c (revision 174264)
+++ gcc.dg/tree-ssa/ssa-fre-6.c (working copy)
@@ -2,5 +2,5 @@
 /* { dg-options "-O -fdump-tree-fre1-details" } */

  int i; int foo(void) { i = 2; int j = i * 2; int k = i + 2; return j == k; }
-/* { dg-final { scan-tree-dump-times "Replaced " 5 "fre1" } } */
+/* { dg-final { scan-tree-dump-times "Replaced " 6 "fre1" } } */
 /* { dg-final { cleanup-tree-dump "fre1" } } */

Regards,
Kai
Index: gcc/gcc/gimplify.c
===================================================================
--- gcc.orig/gcc/gimplify.c     2011-05-23 13:49:29.235177000 +0200
+++ gcc/gcc/gimplify.c  2011-05-26 10:36:40.757641800 +0200
@@ -2837,15 +2837,18 @@ gimple_boolify (tree expr)
 
     case TRUTH_NOT_EXPR:
       TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
-      /* FALLTHRU */
 
-    case EQ_EXPR: case NE_EXPR:
-    case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
       /* These expressions always produce boolean results.  */
       TREE_TYPE (expr) = boolean_type_node;
       return expr;
 
     default:
+      if (COMPARISON_CLASS_P (expr))
+        {
+         /* These expressions always produce boolean results.  */
+         TREE_TYPE (expr) = boolean_type_node;
+         return expr;
+       }
       /* Other expressions that get here must have boolean values, but
         might need to be converted to the appropriate mode.  */
       if (type == boolean_type_node)
@@ -6758,7 +6761,7 @@ gimplify_expr (tree *expr_p, gimple_seq
            tree org_type = TREE_TYPE (*expr_p);
 
            *expr_p = gimple_boolify (*expr_p);
-           if (org_type != boolean_type_node)
+           if (!useless_type_conversion_p (org_type, boolean_type_node))
              {
                *expr_p = fold_convert (org_type, *expr_p);
                ret = GS_OK;
@@ -7203,7 +7206,7 @@ gimplify_expr (tree *expr_p, gimple_seq
               fold_truth_not_expr) happily uses operand type and doesn't
               automatically uses boolean_type as result, we need to keep
               orignal type.  */
-           if (org_type != boolean_type_node)
+           if (!useless_type_conversion_p (org_type, boolean_type_node))
              {
                *expr_p = fold_convert (org_type, *expr_p);
                ret = GS_OK;
@@ -7281,9 +7284,28 @@ gimplify_expr (tree *expr_p, gimple_seq
                 plain wrong if bitfields are involved.  */
                {
                  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
+                 tree org_type = TREE_TYPE (*expr_p);
+
+                 if (!useless_type_conversion_p (org_type, boolean_type_node))
+                   {
+                     TREE_TYPE (*expr_p) = boolean_type_node;
+                     *expr_p = fold_convert_loc (saved_location, org_type, 
*expr_p);
+                     ret = GS_OK;
+                     goto dont_recalculate;
+                   }
 
                  if (!AGGREGATE_TYPE_P (type))
-                   goto expr_2;
+                   {
+                     enum gimplify_status r0, r1;
+
+                     r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                                         post_p, is_gimple_val, fb_rvalue);
+                     r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                                         post_p, is_gimple_val, fb_rvalue);
+
+                     ret = MIN (r0, r1);
+                   }
+
                  else if (TYPE_MODE (type) != BLKmode)
                    ret = gimplify_scalar_mode_aggregate_compare (expr_p);
                  else
Index: gcc/gcc/fold-const.c
===================================================================
--- gcc.orig/gcc/fold-const.c   2011-05-23 13:49:29.000000000 +0200
+++ gcc/gcc/fold-const.c        2011-05-26 10:39:48.721510200 +0200
@@ -7641,6 +7641,12 @@ fold_unary_loc (location_t loc, enum tre
        }
       else if (COMPARISON_CLASS_P (arg0))
        {
+         /* Don't optimize type change, if op0 is of kind boolean_type_node.
+            Otherwise this will lead to race-condition on gimplification
+            trying to boolify comparison expression.  */
+         if (TREE_TYPE (op0) == boolean_type_node)
+           return NULL_TREE;
+
          if (TREE_CODE (type) == BOOLEAN_TYPE)
            {
              arg0 = copy_node (arg0);
@@ -7672,11 +7678,12 @@ fold_unary_loc (location_t loc, enum tre
       if (TREE_TYPE (op0) == type)
        return op0;
 
-      /* If we have (type) (a CMP b) and type is an integral type, return
+      /* If we have (type) (a CMP b) and type is a boolean type, return
          new expression involving the new type.  */
-      if (COMPARISON_CLASS_P (op0) && INTEGRAL_TYPE_P (type))
-       return fold_build2_loc (loc, TREE_CODE (op0), type, TREE_OPERAND (op0, 
0),
-                           TREE_OPERAND (op0, 1));
+      if (COMPARISON_CLASS_P (op0) && TREE_CODE (type) == BOOLEAN_TYPE)
+       return fold_build2_loc (loc, TREE_CODE (op0), type,
+                               TREE_OPERAND (op0, 0),
+                               TREE_OPERAND (op0, 1));
 
       /* Handle cases of two conversions in a row.  */
       if (CONVERT_EXPR_P (op0))
Index: gcc/gcc/tree-cfg.c
===================================================================
--- gcc.orig/gcc/tree-cfg.c     2011-05-20 19:44:41.000000000 +0200
+++ gcc/gcc/tree-cfg.c  2011-05-25 13:17:22.743935300 +0200
@@ -3208,7 +3208,10 @@ verify_gimple_comparison (tree type, tre
        && (!POINTER_TYPE_P (op0_type)
           || !POINTER_TYPE_P (op1_type)
           || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
-      || !INTEGRAL_TYPE_P (type))
+      || !(TREE_CODE (type) == BOOLEAN_TYPE
+          || (TREE_TYPE (type) && TREE_CODE (type) == INTEGER_TYPE
+              && TREE_CODE (TREE_TYPE (type)) == BOOLEAN_TYPE)
+          || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
     {
       error ("type mismatch in comparison expression");
       debug_generic_expr (type);
@@ -3352,6 +3355,8 @@ verify_gimple_assign_unary (gimple stmt)
     case TRUTH_NOT_EXPR:
       /* We require two-valued operand types.  */
       if (!(TREE_CODE (rhs1_type) == BOOLEAN_TYPE
+           || (TREE_TYPE (rhs1_type) && TREE_CODE (rhs1_type) == INTEGER_TYPE
+               && TREE_CODE (TREE_TYPE (rhs1_type)) == BOOLEAN_TYPE)
            || (INTEGRAL_TYPE_P (rhs1_type)
                && TYPE_PRECISION (rhs1_type) == 1)))
         {
Index: gcc/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc.orig/gcc/tree-ssa-forwprop.c    2011-05-23 13:49:29.000000000 +0200
+++ gcc/gcc/tree-ssa-forwprop.c 2011-05-23 13:55:35.281805900 +0200
@@ -1152,7 +1152,10 @@ forward_propagate_comparison (gimple stm
       tree lhs = gimple_assign_lhs (use_stmt);
 
       /* We can propagate the condition into a conversion.  */
-      if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
+      if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
+         && (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
+             || (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+                 && TYPE_PRECISION (TREE_TYPE (lhs)) == 1)))
        {
          /* Avoid using fold here as that may create a COND_EXPR with
             non-boolean condition as canonical form.  */

Reply via email to