fold-const.c (fold_binary_loc): Move simplifying of comparisons against the highest or lowest possible integer ...

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.

From-SVN: r226153
This commit is contained in:
Richard Biener 2015-07-24 12:36:00 +00:00 committed by Richard Biener
parent fa138f6efd
commit 21aacde458
3 changed files with 73 additions and 117 deletions

View file

@ -1,3 +1,9 @@
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.

View file

@ -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.

View file

@ -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)