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:
parent
fa138f6efd
commit
21aacde458
3 changed files with 73 additions and 117 deletions
|
@ -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.
|
||||
|
|
117
gcc/fold-const.c
117
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.
|
||||
|
|
67
gcc/match.pd
67
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue