[PATCH] Rewrite TRUTH_NOT_EXPR as BIT_{NOT,XOR}_EXPR

Richard Guenther rguenther@suse.de
Tue Jul 19 11:43:00 GMT 2011


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  <rguenther@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;
+ }



More information about the Gcc-patches mailing list