On Mon, 18 Jul 2011, Richard Guenther wrote:

> 
> This rewrites TRUTH_NOT_EXPRs during gimplification
> as BIT_NOT_EXPR respective BIT_XOR_EXPR as RTL expansion does.  This
> completes the series lowering the TRUTH_*_EXPRs to operations that
> are also available on HW and allows us to unify code handling
> TRUTH_*_EXPRs and BIT_*_EXPRs.
> 
> The patch has seen final adjustment for the testsuite fallout
> (which happened to be minor after the prerequesite fixes), so
> it is currently in a final bootstrap & regtest cycle.
> 
> I'll commit it tomorrow if that works out fine.

Of course it catched a bug in the tree-ssa-forwprop.c parts.  Fixed,
re-bootstrapped and tested on x86_64-unknown-linux-gnu and
committed as follows.

Richard.

2011-07-19  Richard Guenther  <rguent...@suse.de>

        * gimplify.c (gimplify_expr): Gimplify TRUTH_NOT_EXPR as
        BIT_XOR_EXPR, same as the RTL expander does.
        * tree-cfg.c (verify_expr): Disallow TRUTH_NOT_EXPR in the gimple IL.
        (verify_gimple_assign_unary): Likewise.
        * tree-ssa-propagate.c (valid_gimple_rhs_p): Disallow TRUTH_*_EXPR.
        * tree-ssa-forwprop.c (forward_propagate_comparison): Handle
        BIT_NOT_EXPR and BIT_XOR_EXPR instead of TRUTH_NOT_EXPR.

        * gcc.dg/tree-ssa/bool-10.c: Adjust expected pattern.
        * gcc.dg/tree-ssa/bool-11.c: Likewise.
        * gcc.dg/torture/20110719-1.c: New testcase.

Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig 2011-07-18 16:20:14.000000000 +0200
--- gcc/gimplify.c      2011-07-18 16:22:55.000000000 +0200
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6787,6803 ****
  
        case TRUTH_NOT_EXPR:
          {
!           tree orig_type = TREE_TYPE (*expr_p);
            *expr_p = gimple_boolify (*expr_p);
!           if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
!             {
!               *expr_p = fold_convert_loc (saved_location, orig_type, *expr_p);
!               ret = GS_OK;
!               break;
!             }
!           ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
!                                is_gimple_val, fb_rvalue);
!           recalculate_side_effects (*expr_p);
            break;
          }
  
--- 6787,6810 ----
  
        case TRUTH_NOT_EXPR:
          {
!           tree type = TREE_TYPE (*expr_p);
!           /* The parsers are careful to generate TRUTH_NOT_EXPR
!              only with operands that are always zero or one.
!              We do not fold here but handle the only interesting case
!              manually, as fold may re-introduce the TRUTH_NOT_EXPR.  */
            *expr_p = gimple_boolify (*expr_p);
!           if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
!             *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
!                                   TREE_TYPE (*expr_p),
!                                   TREE_OPERAND (*expr_p, 0));
!           else
!             *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
!                                   TREE_TYPE (*expr_p),
!                                   TREE_OPERAND (*expr_p, 0),
!                                   build_int_cst (TREE_TYPE (*expr_p), 1));
!           if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
!             *expr_p = fold_convert_loc (input_location, type, *expr_p);
!           ret = GS_OK;
            break;
          }
  
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig 2011-07-18 16:20:14.000000000 +0200
--- gcc/tree-cfg.c      2011-07-18 16:22:55.000000000 +0200
*************** verify_expr (tree *tp, int *walk_subtree
*** 2753,2759 ****
        break;
  
      case NON_LVALUE_EXPR:
!       gcc_unreachable ();
  
      CASE_CONVERT:
      case FIX_TRUNC_EXPR:
--- 2753,2760 ----
        break;
  
      case NON_LVALUE_EXPR:
!     case TRUTH_NOT_EXPR:
!       gcc_unreachable ();
  
      CASE_CONVERT:
      case FIX_TRUNC_EXPR:
*************** verify_expr (tree *tp, int *walk_subtree
*** 2761,2767 ****
      case NEGATE_EXPR:
      case ABS_EXPR:
      case BIT_NOT_EXPR:
-     case TRUTH_NOT_EXPR:
        CHECK_OP (0, "invalid operand to unary operator");
        break;
  
--- 2762,2767 ----
*************** verify_gimple_assign_unary (gimple stmt)
*** 3417,3435 ****
        /* FIXME.  */
        return false;
  
-     case TRUTH_NOT_EXPR:
-       /* We require two-valued operand types.  */
-       if (!(TREE_CODE (rhs1_type) == BOOLEAN_TYPE
-           || (INTEGRAL_TYPE_P (rhs1_type)
-               && TYPE_PRECISION (rhs1_type) == 1)))
-         {
-         error ("invalid types in truth not");
-         debug_generic_expr (lhs_type);
-         debug_generic_expr (rhs1_type);
-         return true;
-         }
-       break;
- 
      case NEGATE_EXPR:
      case ABS_EXPR:
      case BIT_NOT_EXPR:
--- 3417,3422 ----
Index: gcc/tree-ssa-propagate.c
===================================================================
*** gcc/tree-ssa-propagate.c.orig       2011-07-18 16:20:14.000000000 +0200
--- gcc/tree-ssa-propagate.c    2011-07-18 16:22:55.000000000 +0200
*************** valid_gimple_rhs_p (tree expr)
*** 601,619 ****
            }
            break;
  
-       case TRUTH_NOT_EXPR:
-         if (!is_gimple_val (TREE_OPERAND (expr, 0)))
-           return false;
-         break;
- 
-       case TRUTH_AND_EXPR:
-       case TRUTH_XOR_EXPR:
-       case TRUTH_OR_EXPR:
-         if (!is_gimple_val (TREE_OPERAND (expr, 0))
-             || !is_gimple_val (TREE_OPERAND (expr, 1)))
-           return false;
-         break;
- 
        default:
          return false;
        }
--- 601,606 ----
Index: gcc/testsuite/gcc.dg/tree-ssa/bool-10.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/bool-10.c.orig        2008-08-20 
10:24:07.000000000 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/bool-10.c     2011-07-18 16:24:16.000000000 
+0200
*************** int f(_Bool x)
*** 9,14 ****
  /* There should be no != 1 which is produced by the front-end as
     bool_var != 1 is the same as !bool_var. */
  /* { dg-final { scan-tree-dump-times "!= 1" 0 "optimized"} } */
! /* { dg-final { scan-tree-dump-times "!x" 1 "optimized"} } */
  
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 9,14 ----
  /* There should be no != 1 which is produced by the front-end as
     bool_var != 1 is the same as !bool_var. */
  /* { dg-final { scan-tree-dump-times "!= 1" 0 "optimized"} } */
! /* { dg-final { scan-tree-dump-times "~x" 1 "optimized"} } */
  
  /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/bool-11.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/bool-11.c.orig        2008-08-20 
10:24:07.000000000 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/bool-11.c     2011-07-18 16:24:46.000000000 
+0200
*************** int f(_Bool x)
*** 9,14 ****
  /* There should be no == 0 which is produced by the front-end as
     bool_var == 0 is the same as !bool_var. */
  /* { dg-final { scan-tree-dump-times "== 0" 0 "optimized"} } */
! /* { dg-final { scan-tree-dump-times "!x" 1 "optimized"} } */
  
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 9,14 ----
  /* There should be no == 0 which is produced by the front-end as
     bool_var == 0 is the same as !bool_var. */
  /* { dg-final { scan-tree-dump-times "== 0" 0 "optimized"} } */
! /* { dg-final { scan-tree-dump-times "~x" 1 "optimized"} } */
  
  /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c.orig        2011-07-18 16:18:35.000000000 +0200
--- gcc/tree-ssa-forwprop.c     2011-07-19 11:37:10.000000000 +0200
*************** forward_propagate_comparison (gimple stm
*** 1127,1133 ****
        && (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
          || TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt))
             == tcc_comparison
!           || gimple_assign_rhs_code (use_stmt) == TRUTH_NOT_EXPR)
        && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (use_stmt))))
      {
        tree lhs = gimple_assign_lhs (use_stmt);
--- 1127,1134 ----
        && (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
          || TREE_CODE_CLASS (gimple_assign_rhs_code (use_stmt))
             == tcc_comparison
!           || gimple_assign_rhs_code (use_stmt) == BIT_NOT_EXPR
!         || gimple_assign_rhs_code (use_stmt) == BIT_XOR_EXPR)
        && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (use_stmt))))
      {
        tree lhs = gimple_assign_lhs (use_stmt);
*************** forward_propagate_comparison (gimple stm
*** 1164,1170 ****
        }
        /* We can propagate the condition into a statement that
         computes the logical negation of the comparison result.  */
!       else if (gimple_assign_rhs_code (use_stmt) == TRUTH_NOT_EXPR)
        {
          tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
          bool nans = HONOR_NANS (TYPE_MODE (type));
--- 1165,1174 ----
        }
        /* We can propagate the condition into a statement that
         computes the logical negation of the comparison result.  */
!       else if ((gimple_assign_rhs_code (use_stmt) == BIT_NOT_EXPR
!               && TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
!              || (gimple_assign_rhs_code (use_stmt) == BIT_XOR_EXPR
!                  && integer_onep (gimple_assign_rhs2 (use_stmt))))
        {
          tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
          bool nans = HONOR_NANS (TYPE_MODE (type));
Index: gcc/testsuite/gcc.dg/torture/20110719-1.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/20110719-1.c   2011-07-19 11:38:07.000000000 
+0200
***************
*** 0 ****
--- 1,10 ----
+ extern void abort (void);
+ int i;
+ int main()
+ {
+   int b = i != 0;
+   int c = ~b;
+   if (c != -1)
+     abort ();
+   return 0;
+ }

Reply via email to