aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c117
-rw-r--r--gcc/match.pd67
3 files changed, 73 insertions, 117 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6f8ae02..d7f6ca5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2015-07-24 Richard Biener <rguenther@suse.de>
+ * fold-const.c (fold_binary_loc): Move simplifying of comparisons
+ against the highest or lowest possible integer ...
+ * match.pd: ... as patterns here.
+
+2015-07-24 Richard Biener <rguenther@suse.de>
+
* genmatch.c (struct capture_info): Add same_as field.
(capture_info::capture_info): Initialize same_as.
(capture_info::walk_match): Compute same_as.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c404857..739a3a9 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -11617,123 +11617,6 @@ fold_binary_loc (location_t loc,
}
}
- /* Comparisons with the highest or lowest possible integer of
- the specified precision will have known values. */
- {
- tree arg1_type = TREE_TYPE (arg1);
- unsigned int prec = TYPE_PRECISION (arg1_type);
-
- if (TREE_CODE (arg1) == INTEGER_CST
- && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type)))
- {
- wide_int max = wi::max_value (arg1_type);
- wide_int signed_max = wi::max_value (prec, SIGNED);
- wide_int min = wi::min_value (arg1_type);
-
- if (wi::eq_p (arg1, max))
- switch (code)
- {
- case GT_EXPR:
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
-
- case GE_EXPR:
- return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
-
- case LE_EXPR:
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
-
- case LT_EXPR:
- return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
-
- /* The GE_EXPR and LT_EXPR cases above are not normally
- reached because of previous transformations. */
-
- default:
- break;
- }
- else if (wi::eq_p (arg1, max - 1))
- switch (code)
- {
- case GT_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- return fold_build2_loc (loc, EQ_EXPR, type,
- fold_convert_loc (loc,
- TREE_TYPE (arg1), arg0),
- arg1);
- case LE_EXPR:
- arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- return fold_build2_loc (loc, NE_EXPR, type,
- fold_convert_loc (loc, TREE_TYPE (arg1),
- arg0),
- arg1);
- default:
- break;
- }
- else if (wi::eq_p (arg1, min))
- switch (code)
- {
- case LT_EXPR:
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
-
- case LE_EXPR:
- return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
-
- case GE_EXPR:
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
-
- case GT_EXPR:
- return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
-
- default:
- break;
- }
- else if (wi::eq_p (arg1, min + 1))
- switch (code)
- {
- case GE_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- return fold_build2_loc (loc, NE_EXPR, type,
- fold_convert_loc (loc,
- TREE_TYPE (arg1), arg0),
- arg1);
- case LT_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- return fold_build2_loc (loc, EQ_EXPR, type,
- fold_convert_loc (loc, TREE_TYPE (arg1),
- arg0),
- arg1);
- default:
- break;
- }
-
- else if (wi::eq_p (arg1, signed_max)
- && TYPE_UNSIGNED (arg1_type)
- /* We will flip the signedness of the comparison operator
- associated with the mode of arg1, so the sign bit is
- specified by this mode. Check that arg1 is the signed
- max associated with this sign bit. */
- && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type))
- /* signed_type does not work on pointer types. */
- && INTEGRAL_TYPE_P (arg1_type))
- {
- /* The following case also applies to X < signed_max+1
- and X >= signed_max+1 because previous transformations. */
- if (code == LE_EXPR || code == GT_EXPR)
- {
- tree st = signed_type_for (arg1_type);
- return fold_build2_loc (loc,
- code == LE_EXPR ? GE_EXPR : LT_EXPR,
- type, fold_convert_loc (loc, st, arg0),
- build_int_cst (st, 0));
- }
- }
- }
- }
-
/* If we are comparing an ABS_EXPR with a constant, we can
convert all the cases into explicit comparisons, but they may
well not be faster than doing the ABS and one comparison.
diff --git a/gcc/match.pd b/gcc/match.pd
index 398378d..3d53abf 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1824,6 +1824,73 @@ along with GCC; see the file COPYING3. If not see
{ constant_boolean_node (cmp == NE_EXPR, type); })))
+/* Non-equality compare simplifications from fold_binary */
+(for cmp (lt gt le ge)
+ /* Comparisons with the highest or lowest possible integer of
+ the specified precision will have known values. */
+ (simplify
+ (cmp (convert?@2 @0) INTEGER_CST@1)
+ (if ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
+ && tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0)))
+ (with
+ {
+ tree arg1_type = TREE_TYPE (@1);
+ unsigned int prec = TYPE_PRECISION (arg1_type);
+ wide_int max = wi::max_value (arg1_type);
+ wide_int signed_max = wi::max_value (prec, SIGNED);
+ wide_int min = wi::min_value (arg1_type);
+ }
+ (switch
+ (if (wi::eq_p (@1, max))
+ (switch
+ (if (cmp == GT_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == GE_EXPR)
+ (eq @2 @1))
+ (if (cmp == LE_EXPR)
+ { constant_boolean_node (true, type); })
+ (if (cmp == LT_EXPR)
+ (ne @2 @1))))
+ (if (wi::eq_p (@1, max - 1))
+ (switch
+ (if (cmp == GT_EXPR)
+ (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); }))
+ (if (cmp == LE_EXPR)
+ (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); }))))
+ (if (wi::eq_p (@1, min))
+ (switch
+ (if (cmp == LT_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == LE_EXPR)
+ (eq @2 @1))
+ (if (cmp == GE_EXPR)
+ { constant_boolean_node (true, type); })
+ (if (cmp == GT_EXPR)
+ (ne @2 @1))))
+ (if (wi::eq_p (@1, min + 1))
+ (switch
+ (if (cmp == GE_EXPR)
+ (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); }))
+ (if (cmp == LT_EXPR)
+ (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); }))))
+ (if (wi::eq_p (@1, signed_max)
+ && TYPE_UNSIGNED (arg1_type)
+ /* We will flip the signedness of the comparison operator
+ associated with the mode of @1, so the sign bit is
+ specified by this mode. Check that @1 is the signed
+ max associated with this sign bit. */
+ && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (arg1_type))
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ (if (cmp == LE_EXPR || cmp == GT_EXPR)
+ (with { tree st = signed_type_for (arg1_type); }
+ (if (cmp == LE_EXPR)
+ (ge (convert:st @0) { build_zero_cst (st); })
+ (lt (convert:st @0) { build_zero_cst (st); }))))))))))
+
+
/* bool_var != 0 becomes bool_var. */
(simplify
(ne @0 integer_zerop@1)