aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/gimplify.c27
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/20110719-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/bool-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/bool-11.c2
-rw-r--r--gcc/tree-cfg.c17
-rw-r--r--gcc/tree-ssa-forwprop.c8
-rw-r--r--gcc/tree-ssa-propagate.c13
9 files changed, 53 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d46d52d..2982c9b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+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.
+
2011-07-19 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/49768
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index d1ce6d3..03e2ca6 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6787,17 +6787,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case TRUTH_NOT_EXPR:
{
- tree orig_type = TREE_TYPE (*expr_p);
+ 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 (!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);
+ 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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 07c283d..d87ce8d74 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-07-19 Richard Guenther <rguenther@suse.de>
+
+ * 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.
+
2011-07-19 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/49768
diff --git a/gcc/testsuite/gcc.dg/torture/20110719-1.c b/gcc/testsuite/gcc.dg/torture/20110719-1.c
new file mode 100644
index 0000000..7797e08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/20110719-1.c
@@ -0,0 +1,10 @@
+extern void abort (void);
+int i;
+int main()
+{
+ int b = i != 0;
+ int c = ~b;
+ if (c != -1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c
index d7bf20d..58d0645 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c
@@ -9,6 +9,6 @@ int f(_Bool x)
/* 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 { scan-tree-dump-times "~x" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c
index 8d88b7e..ee266c7 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c
@@ -9,6 +9,6 @@ int f(_Bool x)
/* 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 { scan-tree-dump-times "~x" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 12d8fb4..cd13472 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2680,7 +2680,8 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
break;
case NON_LVALUE_EXPR:
- gcc_unreachable ();
+ case TRUTH_NOT_EXPR:
+ gcc_unreachable ();
CASE_CONVERT:
case FIX_TRUNC_EXPR:
@@ -2688,7 +2689,6 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
case NEGATE_EXPR:
case ABS_EXPR:
case BIT_NOT_EXPR:
- case TRUTH_NOT_EXPR:
CHECK_OP (0, "invalid operand to unary operator");
break;
@@ -3344,19 +3344,6 @@ verify_gimple_assign_unary (gimple stmt)
/* 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:
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 8e6b704..1f2a60c 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1127,7 +1127,8 @@ forward_propagate_comparison (gimple stmt)
&& (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)
+ || 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);
@@ -1164,7 +1165,10 @@ forward_propagate_comparison (gimple stmt)
}
/* 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)
+ 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));
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 7f1d84e..64c3fdf 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -601,19 +601,6 @@ valid_gimple_rhs_p (tree expr)
}
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;
}