[PATCH] Rewrite TRUTH_NOT_EXPR as BIT_{NOT,XOR}_EXPR
Richard Guenther
rguenther@suse.de
Mon Jul 18 14:48:00 GMT 2011
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.
Thanks,
Richard.
2011-07-18 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 instead of TRUTH_NOT_EXPR.
* gcc.dg/tree-ssa/bool-10.c: Adjust expected pattern.
* gcc.dg/tree-ssa/bool-11.c: Likewise.
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-18 16:26:29.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,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) == BIT_NOT_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));
--- 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) == BIT_NOT_EXPR)
{
tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
bool nans = HONOR_NANS (TYPE_MODE (type));
More information about the Gcc-patches
mailing list