Commit 8d1628eb by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/81346 (Missed constant propagation into comparison)

	PR tree-optimization/81346
	* fold-const.h (fold_div_compare, range_check_type): Declare.
	* fold-const.c (range_check_type): New function.
	(build_range_check): Use range_check_type.
	(fold_div_compare): No longer static, rewritten into
	a match.pd helper function.
	(fold_comparison): Don't call fold_div_compare here.
	* match.pd (X / C1 op C2): New optimization using fold_div_compare
	as helper function.

	* gcc.dg/tree-ssa/pr81346-1.c: New test.
	* gcc.dg/tree-ssa/pr81346-2.c: New test.
	* gcc.dg/tree-ssa/pr81346-3.c: New test.
	* gcc.dg/tree-ssa/pr81346-4.c: New test.
	* gcc.target/i386/umod-3.c: Hide comparison against 1 from the
	compiler to avoid X / C1 op C2 optimization to trigger.

From-SVN: r250338
parent 20deef65
2017-07-19 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/81346
* fold-const.h (fold_div_compare, range_check_type): Declare.
* fold-const.c (range_check_type): New function.
(build_range_check): Use range_check_type.
(fold_div_compare): No longer static, rewritten into
a match.pd helper function.
(fold_comparison): Don't call fold_div_compare here.
* match.pd (X / C1 op C2): New optimization using fold_div_compare
as helper function.
2017-07-19 Nathan Sidwell <nathan@acm.org> 2017-07-19 Nathan Sidwell <nathan@acm.org>
* tree.h (TYPE_MINVAL, TYPE_MAXVAL): Rename to ... * tree.h (TYPE_MINVAL, TYPE_MAXVAL): Rename to ...
......
...@@ -132,7 +132,6 @@ static tree fold_binary_op_with_conditional_arg (location_t, ...@@ -132,7 +132,6 @@ static tree fold_binary_op_with_conditional_arg (location_t,
enum tree_code, tree, enum tree_code, tree,
tree, tree, tree, tree,
tree, tree, int); tree, tree, int);
static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
static tree fold_negate_const (tree, tree); static tree fold_negate_const (tree, tree);
static tree fold_not_const (const_tree, tree); static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree); static tree fold_relational_const (enum tree_code, tree, tree, tree);
...@@ -4787,6 +4786,39 @@ maskable_range_p (const_tree low, const_tree high, tree type, tree *mask, ...@@ -4787,6 +4786,39 @@ maskable_range_p (const_tree low, const_tree high, tree type, tree *mask,
return true; return true;
} }
/* Helper routine for build_range_check and match.pd. Return the type to
perform the check or NULL if it shouldn't be optimized. */
tree
range_check_type (tree etype)
{
/* First make sure that arithmetics in this type is valid, then make sure
that it wraps around. */
if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
TYPE_UNSIGNED (etype));
if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
{
tree utype, minv, maxv;
/* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
for the type in question, as we rely on this here. */
utype = unsigned_type_for (etype);
maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
build_int_cst (TREE_TYPE (maxv), 1), 1);
minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
minv, 1, maxv, 1)))
etype = utype;
else
return NULL_TREE;
}
return etype;
}
/* Given a range, LOW, HIGH, and IN_P, an expression, EXP, and a result /* Given a range, LOW, HIGH, and IN_P, an expression, EXP, and a result
type, TYPE, return an expression to test if EXP is in (or out of, depending type, TYPE, return an expression to test if EXP is in (or out of, depending
on IN_P) the range. Return 0 if the test couldn't be created. */ on IN_P) the range. Return 0 if the test couldn't be created. */
...@@ -4869,31 +4901,10 @@ build_range_check (location_t loc, tree type, tree exp, int in_p, ...@@ -4869,31 +4901,10 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
} }
/* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low). /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
This requires wrap-around arithmetics for the type of the expression. This requires wrap-around arithmetics for the type of the expression. */
First make sure that arithmetics in this type is valid, then make sure etype = range_check_type (etype);
that it wraps around. */ if (etype == NULL_TREE)
if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE) return NULL_TREE;
etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
TYPE_UNSIGNED (etype));
if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
{
tree utype, minv, maxv;
/* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
for the type in question, as we rely on this here. */
utype = unsigned_type_for (etype);
maxv = fold_convert_loc (loc, utype, TYPE_MAX_VALUE (etype));
maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
build_int_cst (TREE_TYPE (maxv), 1), 1);
minv = fold_convert_loc (loc, utype, TYPE_MIN_VALUE (etype));
if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
minv, 1, maxv, 1)))
etype = utype;
else
return 0;
}
high = fold_convert_loc (loc, etype, high); high = fold_convert_loc (loc, etype, high);
low = fold_convert_loc (loc, etype, low); low = fold_convert_loc (loc, etype, low);
...@@ -6548,65 +6559,55 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate) ...@@ -6548,65 +6559,55 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)); return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
} }
/* Subroutine of fold() that optimizes comparisons of a division by /* Subroutine of match.pd that optimizes comparisons of a division by
a nonzero integer constant against an integer constant, i.e. a nonzero integer constant against an integer constant, i.e.
X/C1 op C2. X/C1 op C2.
CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, CODE is the comparison operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR,
GE_EXPR or LE_EXPR. TYPE is the type of the result and ARG0 and ARG1 GE_EXPR or LE_EXPR. ARG01 and ARG1 must be a INTEGER_CST. */
are the operands of the comparison. ARG1 must be a TREE_REAL_CST.
The function returns the constant folded tree if a simplification
can be made, and NULL_TREE otherwise. */
static tree enum tree_code
fold_div_compare (location_t loc, fold_div_compare (enum tree_code code, tree c1, tree c2, tree *lo,
enum tree_code code, tree type, tree arg0, tree arg1) tree *hi, bool *neg_overflow)
{ {
tree prod, tmp, hi, lo; tree prod, tmp, type = TREE_TYPE (c1);
tree arg00 = TREE_OPERAND (arg0, 0); signop sign = TYPE_SIGN (type);
tree arg01 = TREE_OPERAND (arg0, 1);
signop sign = TYPE_SIGN (TREE_TYPE (arg0));
bool neg_overflow = false;
bool overflow; bool overflow;
/* We have to do this the hard way to detect unsigned overflow. /* We have to do this the hard way to detect unsigned overflow.
prod = int_const_binop (MULT_EXPR, arg01, arg1); */ prod = int_const_binop (MULT_EXPR, c1, c2); */
wide_int val = wi::mul (arg01, arg1, sign, &overflow); wide_int val = wi::mul (c1, c2, sign, &overflow);
prod = force_fit_type (TREE_TYPE (arg00), val, -1, overflow); prod = force_fit_type (type, val, -1, overflow);
neg_overflow = false; *neg_overflow = false;
if (sign == UNSIGNED) if (sign == UNSIGNED)
{ {
tmp = int_const_binop (MINUS_EXPR, arg01, tmp = int_const_binop (MINUS_EXPR, c1, build_int_cst (type, 1));
build_int_cst (TREE_TYPE (arg01), 1)); *lo = prod;
lo = prod;
/* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp). */ /* Likewise *hi = int_const_binop (PLUS_EXPR, prod, tmp). */
val = wi::add (prod, tmp, sign, &overflow); val = wi::add (prod, tmp, sign, &overflow);
hi = force_fit_type (TREE_TYPE (arg00), val, *hi = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (prod));
-1, overflow | TREE_OVERFLOW (prod));
} }
else if (tree_int_cst_sgn (arg01) >= 0) else if (tree_int_cst_sgn (c1) >= 0)
{ {
tmp = int_const_binop (MINUS_EXPR, arg01, tmp = int_const_binop (MINUS_EXPR, c1, build_int_cst (type, 1));
build_int_cst (TREE_TYPE (arg01), 1)); switch (tree_int_cst_sgn (c2))
switch (tree_int_cst_sgn (arg1))
{ {
case -1: case -1:
neg_overflow = true; *neg_overflow = true;
lo = int_const_binop (MINUS_EXPR, prod, tmp); *lo = int_const_binop (MINUS_EXPR, prod, tmp);
hi = prod; *hi = prod;
break; break;
case 0: case 0:
lo = fold_negate_const (tmp, TREE_TYPE (arg0)); *lo = fold_negate_const (tmp, type);
hi = tmp; *hi = tmp;
break; break;
case 1: case 1:
hi = int_const_binop (PLUS_EXPR, prod, tmp); *hi = int_const_binop (PLUS_EXPR, prod, tmp);
lo = prod; *lo = prod;
break; break;
default: default:
...@@ -6618,24 +6619,23 @@ fold_div_compare (location_t loc, ...@@ -6618,24 +6619,23 @@ fold_div_compare (location_t loc,
/* A negative divisor reverses the relational operators. */ /* A negative divisor reverses the relational operators. */
code = swap_tree_comparison (code); code = swap_tree_comparison (code);
tmp = int_const_binop (PLUS_EXPR, arg01, tmp = int_const_binop (PLUS_EXPR, c1, build_int_cst (type, 1));
build_int_cst (TREE_TYPE (arg01), 1)); switch (tree_int_cst_sgn (c2))
switch (tree_int_cst_sgn (arg1))
{ {
case -1: case -1:
hi = int_const_binop (MINUS_EXPR, prod, tmp); *hi = int_const_binop (MINUS_EXPR, prod, tmp);
lo = prod; *lo = prod;
break; break;
case 0: case 0:
hi = fold_negate_const (tmp, TREE_TYPE (arg0)); *hi = fold_negate_const (tmp, type);
lo = tmp; *lo = tmp;
break; break;
case 1: case 1:
neg_overflow = true; *neg_overflow = true;
lo = int_const_binop (PLUS_EXPR, prod, tmp); *lo = int_const_binop (PLUS_EXPR, prod, tmp);
hi = prod; *hi = prod;
break; break;
default: default:
...@@ -6643,63 +6643,17 @@ fold_div_compare (location_t loc, ...@@ -6643,63 +6643,17 @@ fold_div_compare (location_t loc,
} }
} }
switch (code) if (code != EQ_EXPR && code != NE_EXPR)
{ return code;
case EQ_EXPR:
if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi))
return omit_one_operand_loc (loc, type, integer_zero_node, arg00);
if (TREE_OVERFLOW (hi))
return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
if (TREE_OVERFLOW (lo))
return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
return build_range_check (loc, type, arg00, 1, lo, hi);
case NE_EXPR: if (TREE_OVERFLOW (*lo)
if (TREE_OVERFLOW (lo) && TREE_OVERFLOW (hi)) || operand_equal_p (*lo, TYPE_MIN_VALUE (type), 0))
return omit_one_operand_loc (loc, type, integer_one_node, arg00); *lo = NULL_TREE;
if (TREE_OVERFLOW (hi)) if (TREE_OVERFLOW (*hi)
return fold_build2_loc (loc, LT_EXPR, type, arg00, lo); || operand_equal_p (*hi, TYPE_MAX_VALUE (type), 0))
if (TREE_OVERFLOW (lo)) *hi = NULL_TREE;
return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
return build_range_check (loc, type, arg00, 0, lo, hi);
case LT_EXPR: return code;
if (TREE_OVERFLOW (lo))
{
tmp = neg_overflow ? integer_zero_node : integer_one_node;
return omit_one_operand_loc (loc, type, tmp, arg00);
}
return fold_build2_loc (loc, LT_EXPR, type, arg00, lo);
case LE_EXPR:
if (TREE_OVERFLOW (hi))
{
tmp = neg_overflow ? integer_zero_node : integer_one_node;
return omit_one_operand_loc (loc, type, tmp, arg00);
}
return fold_build2_loc (loc, LE_EXPR, type, arg00, hi);
case GT_EXPR:
if (TREE_OVERFLOW (hi))
{
tmp = neg_overflow ? integer_one_node : integer_zero_node;
return omit_one_operand_loc (loc, type, tmp, arg00);
}
return fold_build2_loc (loc, GT_EXPR, type, arg00, hi);
case GE_EXPR:
if (TREE_OVERFLOW (lo))
{
tmp = neg_overflow ? integer_one_node : integer_zero_node;
return omit_one_operand_loc (loc, type, tmp, arg00);
}
return fold_build2_loc (loc, GE_EXPR, type, arg00, lo);
default:
break;
}
return NULL_TREE;
} }
...@@ -8793,20 +8747,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type, ...@@ -8793,20 +8747,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
} }
} }
/* We can fold X/C1 op C2 where C1 and C2 are integer constants
into a single range test. */
if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !integer_zerop (TREE_OPERAND (arg0, 1))
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
&& !TREE_OVERFLOW (arg1))
{
tem = fold_div_compare (loc, code, type, arg0, arg1);
if (tem != NULL_TREE)
return tem;
}
return NULL_TREE; return NULL_TREE;
} }
......
...@@ -88,6 +88,8 @@ extern void fold_undefer_overflow_warnings (bool, const gimple *, int); ...@@ -88,6 +88,8 @@ extern void fold_undefer_overflow_warnings (bool, const gimple *, int);
extern void fold_undefer_and_ignore_overflow_warnings (void); extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (void); extern bool fold_deferring_overflow_warnings_p (void);
extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code); extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code);
extern enum tree_code fold_div_compare (enum tree_code, tree, tree,
tree *, tree *, bool *);
extern int operand_equal_p (const_tree, const_tree, unsigned int); extern int operand_equal_p (const_tree, const_tree, unsigned int);
extern int multiple_of_p (tree, const_tree, const_tree); extern int multiple_of_p (tree, const_tree, const_tree);
#define omit_one_operand(T1,T2,T3)\ #define omit_one_operand(T1,T2,T3)\
...@@ -175,6 +177,7 @@ extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0); ...@@ -175,6 +177,7 @@ extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
extern tree make_range (tree, int *, tree *, tree *, bool *); extern tree make_range (tree, int *, tree *, tree *, bool *);
extern tree make_range_step (location_t, enum tree_code, tree, tree, tree, extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
tree *, tree *, int *, bool *); tree *, tree *, int *, bool *);
extern tree range_check_type (tree);
extern tree build_range_check (location_t, tree, tree, int, tree, tree); extern tree build_range_check (location_t, tree, tree, int, tree, tree);
extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int, extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
tree, tree); tree, tree);
......
...@@ -1132,6 +1132,60 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -1132,6 +1132,60 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (wi::gt_p(@2, 0, TYPE_SIGN (TREE_TYPE (@2)))) (if (wi::gt_p(@2, 0, TYPE_SIGN (TREE_TYPE (@2))))
(cmp @0 @1)))) (cmp @0 @1))))
/* X / C1 op C2 into a simple range test. */
(for cmp (simple_comparison)
(simplify
(cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& integer_nonzerop (@1)
&& !TREE_OVERFLOW (@1)
&& !TREE_OVERFLOW (@2))
(with { tree lo, hi; bool neg_overflow;
enum tree_code code = fold_div_compare (cmp, @1, @2, &lo, &hi,
&neg_overflow); }
(switch
(if (code == LT_EXPR || code == GE_EXPR)
(if (TREE_OVERFLOW (lo))
{ build_int_cst (type, (code == LT_EXPR) ^ neg_overflow); }
(if (code == LT_EXPR)
(lt @0 { lo; })
(ge @0 { lo; }))))
(if (code == LE_EXPR || code == GT_EXPR)
(if (TREE_OVERFLOW (hi))
{ build_int_cst (type, (code == LE_EXPR) ^ neg_overflow); }
(if (code == LE_EXPR)
(le @0 { hi; })
(gt @0 { hi; }))))
(if (!lo && !hi)
{ build_int_cst (type, code == NE_EXPR); })
(if (code == EQ_EXPR && !hi)
(ge @0 { lo; }))
(if (code == EQ_EXPR && !lo)
(le @0 { hi; }))
(if (code == NE_EXPR && !hi)
(lt @0 { lo; }))
(if (code == NE_EXPR && !lo)
(gt @0 { hi; }))
(if (GENERIC)
{ build_range_check (UNKNOWN_LOCATION, type, @0, code == EQ_EXPR,
lo, hi); })
(with
{
tree etype = range_check_type (TREE_TYPE (@0));
if (etype)
{
if (! TYPE_UNSIGNED (etype))
etype = unsigned_type_for (etype);
hi = fold_convert (etype, hi);
lo = fold_convert (etype, lo);
hi = const_binop (MINUS_EXPR, etype, hi, lo);
}
}
(if (etype && hi && !TREE_OVERFLOW (hi))
(if (code == EQ_EXPR)
(le (minus (convert:etype @0) { lo; }) { hi; })
(gt (minus (convert:etype @0) { lo; }) { hi; })))))))))
/* X + Z < Y + Z is the same as X < Y when there is no overflow. */ /* X + Z < Y + Z is the same as X < Y when there is no overflow. */
(for op (lt le ge gt) (for op (lt le ge gt)
(simplify (simplify
......
2017-07-19 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/81346
* gcc.dg/tree-ssa/pr81346-1.c: New test.
* gcc.dg/tree-ssa/pr81346-2.c: New test.
* gcc.dg/tree-ssa/pr81346-3.c: New test.
* gcc.dg/tree-ssa/pr81346-4.c: New test.
* gcc.target/i386/umod-3.c: Hide comparison against 1 from the
compiler to avoid X / C1 op C2 optimization to trigger.
2017-07-19 Martin Liska <mliska@suse.cz> 2017-07-19 Martin Liska <mliska@suse.cz>
PR sanitizer/63361 PR sanitizer/63361
......
/* PR tree-optimization/81346 */
/* { dg-do compile { target int32 } } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-times "return 1;" 32 "optimized" } } */
int f00 (int x) { return x / 49152 > -49152; }
int f01 (int x) { int a = 49152, b = -49152; return x / a > b; }
int f02 (int x) { return x / 49152 >= -49152; }
int f03 (int x) { int a = 49152, b = -49152; return x / a >= b; }
int f04 (int x) { return x / 49152 < 49152; }
int f05 (int x) { int a = 49152, b = 49152; return x / a < b; }
int f06 (int x) { return x / 49152 <= 49152; }
int f07 (int x) { int a = 49152, b = 49152; return x / a <= b; }
int f08 (int x) { return x / 46340 >= -46341; }
int f09 (int x) { int a = 46340, b = -46341; return x / a >= b; }
int f10 (int x) { return x / 46340 <= 46341; }
int f11 (int x) { int a = 46340, b = 46341; return x / a <= b; }
int f12 (int x) { return x / 49152 != -49152; }
int f13 (int x) { int a = 49152, b = -49152; return x / a != b; }
int f14 (int x) { return x / 49152 != 49152; }
int f15 (int x) { int a = 49152, b = 49152; return x / a != b; }
int f16 (int x) { return x / -49152 > -49152; }
int f17 (int x) { int a = -49152, b = -49152; return x / a > b; }
int f18 (int x) { return x / -49152 >= -49152; }
int f19 (int x) { int a = -49152, b = -49152; return x / a >= b; }
int f20 (int x) { return x / -49152 < 49152; }
int f21 (int x) { int a = -49152, b = 49152; return x / a < b; }
int f22 (int x) { return x / -49152 <= 49152; }
int f23 (int x) { int a = -49152, b = 49152; return x / a <= b; }
int f24 (int x) { return x / -46340 >= -46341; }
int f25 (int x) { int a = -46340, b = -46341; return x / a >= b; }
int f26 (int x) { return x / -46340 <= 46341; }
int f27 (int x) { int a = -46340, b = 46341; return x / a <= b; }
int f28 (int x) { return x / -49152 != 49152; }
int f29 (int x) { int a = -49152, b = 49152; return x / a != b; }
int f30 (int x) { return x / -49152 != -49152; }
int f31 (int x) { int a = -49152, b = -49152; return x / a != b; }
/* PR tree-optimization/81346 */
/* { dg-do compile { target int32 } } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-times "return 0;" 32 "optimized" } } */
int f00 (int x) { return x / 49152 > 49152; }
int f01 (int x) { int a = 49152, b = 49152; return x / a > b; }
int f02 (int x) { return x / 49152 >= 49152; }
int f03 (int x) { int a = 49152, b = 49152; return x / a >= b; }
int f04 (int x) { return x / 49152 < -49152; }
int f05 (int x) { int a = 49152, b = -49152; return x / a < b; }
int f06 (int x) { return x / 49152 <= -49152; }
int f07 (int x) { int a = 49152, b = -49152; return x / a <= b; }
int f08 (int x) { return x / 46340 > 46341; }
int f09 (int x) { int a = 46340, b = 46341; return x / a > b; }
int f10 (int x) { return x / 46340 < -46341; }
int f11 (int x) { int a = 46340, b = -46341; return x / a < b; }
int f12 (int x) { return x / 49152 == -49152; }
int f13 (int x) { int a = 49152, b = -49152; return x / a == b; }
int f14 (int x) { return x / 49152 == 49152; }
int f15 (int x) { int a = 49152, b = 49152; return x / a == b; }
int f16 (int x) { return x / -49152 > 49152; }
int f17 (int x) { int a = -49152, b = 49152; return x / a > b; }
int f18 (int x) { return x / -49152 >= 49152; }
int f19 (int x) { int a = -49152, b = 49152; return x / a >= b; }
int f20 (int x) { return x / -49152 < -49152; }
int f21 (int x) { int a = -49152, b = -49152; return x / a < b; }
int f22 (int x) { return x / -49152 <= -49152; }
int f23 (int x) { int a = -49152, b = -49152; return x / a <= b; }
int f24 (int x) { return x / -46340 > 46341; }
int f25 (int x) { int a = -46340, b = 46341; return x / a > b; }
int f26 (int x) { return x / -46340 < -46341; }
int f27 (int x) { int a = -46340, b = -46341; return x / a < b; }
int f28 (int x) { return x / -49152 == 49152; }
int f29 (int x) { int a = -49152, b = 49152; return x / a == b; }
int f30 (int x) { return x / -49152 == -49152; }
int f31 (int x) { int a = -49152, b = -49152; return x / a == b; }
/* PR tree-optimization/81346 */
/* { dg-do compile { target int32 } } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
__attribute__((noinline, noclone)) int f00 (int x) { return x / 46340 > -46341; }
__attribute__((noinline, noclone)) int f01 (int x) { int a = 46340, b = -46341; return x / a > b; }
__attribute__((noinline, noclone)) int f02 (int x) { return x / 46340 >= 46341; }
__attribute__((noinline, noclone)) int f03 (int x) { int a = 46340, b = 46341; return x / a >= b; }
__attribute__((noinline, noclone)) int f04 (int x) { return x / 46340 < 46341; }
__attribute__((noinline, noclone)) int f05 (int x) { int a = 46340, b = 46341; return x / a < b; }
__attribute__((noinline, noclone)) int f06 (int x) { return x / 46340 <= -46341; }
__attribute__((noinline, noclone)) int f07 (int x) { int a = 46340, b = -46341; return x / a <= b; }
__attribute__((noinline, noclone)) int f08 (int x) { return x / 46340 == -46341; }
__attribute__((noinline, noclone)) int f09 (int x) { int a = 46340, b = -46341; return x / a == b; }
__attribute__((noinline, noclone)) int f10 (int x) { return x / 46340 == 46341; }
__attribute__((noinline, noclone)) int f11 (int x) { int a = 46340, b = 46341; return x / a == b; }
__attribute__((noinline, noclone)) int f12 (int x) { return x / 46340 != -46341; }
__attribute__((noinline, noclone)) int f13 (int x) { int a = 46340, b = -46341; return x / a != b; }
__attribute__((noinline, noclone)) int f14 (int x) { return x / 46340 != 46341; }
__attribute__((noinline, noclone)) int f15 (int x) { int a = 46340, b = 46341; return x / a != b; }
__attribute__((noinline, noclone)) int f16 (int x) { return x / 15 > -15; }
__attribute__((noinline, noclone)) int f17 (int x) { int a = 15, b = -15; return x / a > b; }
__attribute__((noinline, noclone)) int f18 (int x) { return x / 15 > 15; }
__attribute__((noinline, noclone)) int f19 (int x) { int a = 15, b = 15; return x / a > b; }
__attribute__((noinline, noclone)) int f20 (int x) { return x / 15 >= -15; }
__attribute__((noinline, noclone)) int f21 (int x) { int a = 15, b = -15; return x / a >= b; }
__attribute__((noinline, noclone)) int f22 (int x) { return x / 15 >= 15; }
__attribute__((noinline, noclone)) int f23 (int x) { int a = 15, b = 15; return x / a >= b; }
__attribute__((noinline, noclone)) int f24 (int x) { return x / 15 < -15; }
__attribute__((noinline, noclone)) int f25 (int x) { int a = 15, b = -15; return x / a < b; }
__attribute__((noinline, noclone)) int f26 (int x) { return x / 15 < 15; }
__attribute__((noinline, noclone)) int f27 (int x) { int a = 15, b = 15; return x / a < b; }
__attribute__((noinline, noclone)) int f28 (int x) { return x / 15 <= -15; }
__attribute__((noinline, noclone)) int f29 (int x) { int a = 15, b = -15; return x / a <= b; }
__attribute__((noinline, noclone)) int f30 (int x) { return x / 15 <= 15; }
__attribute__((noinline, noclone)) int f31 (int x) { int a = 15, b = 15; return x / a <= b; }
__attribute__((noinline, noclone)) int f32 (int x) { return x / 15 == -15; }
__attribute__((noinline, noclone)) int f33 (int x) { int a = 15, b = -15; return x / a == b; }
__attribute__((noinline, noclone)) int f34 (int x) { return x / 15 == 15; }
__attribute__((noinline, noclone)) int f35 (int x) { int a = 15, b = 15; return x / a == b; }
__attribute__((noinline, noclone)) int f36 (int x) { return x / 15 != -15; }
__attribute__((noinline, noclone)) int f37 (int x) { int a = 15, b = -15; return x / a != b; }
__attribute__((noinline, noclone)) int f38 (int x) { return x / 15 != 15; }
__attribute__((noinline, noclone)) int f39 (int x) { int a = 15, b = 15; return x / a != b; }
__attribute__((noinline, noclone)) int f40 (int x) { return x / -46340 > -46341; }
__attribute__((noinline, noclone)) int f41 (int x) { int a = -46340, b = -46341; return x / a > b; }
__attribute__((noinline, noclone)) int f42 (int x) { return x / -46340 >= 46341; }
__attribute__((noinline, noclone)) int f43 (int x) { int a = -46340, b = 46341; return x / a >= b; }
__attribute__((noinline, noclone)) int f44 (int x) { return x / -46340 < 46341; }
__attribute__((noinline, noclone)) int f45 (int x) { int a = -46340, b = 46341; return x / a < b; }
__attribute__((noinline, noclone)) int f46 (int x) { return x / -46340 <= -46341; }
__attribute__((noinline, noclone)) int f47 (int x) { int a = -46340, b = -46341; return x / a <= b; }
__attribute__((noinline, noclone)) int f48 (int x) { return x / -46340 == 46341; }
__attribute__((noinline, noclone)) int f49 (int x) { int a = -46340, b = 46341; return x / a == b; }
__attribute__((noinline, noclone)) int f50 (int x) { return x / -46340 == -46341; }
__attribute__((noinline, noclone)) int f51 (int x) { int a = -46340, b = -46341; return x / a == b; }
__attribute__((noinline, noclone)) int f52 (int x) { return x / -46340 != 46341; }
__attribute__((noinline, noclone)) int f53 (int x) { int a = -46340, b = 46341; return x / a != b; }
__attribute__((noinline, noclone)) int f54 (int x) { return x / -46340 != -46341; }
__attribute__((noinline, noclone)) int f55 (int x) { int a = -46340, b = -46341; return x / a != b; }
__attribute__((noinline, noclone)) int f56 (int x) { return x / -15 > 15; }
__attribute__((noinline, noclone)) int f57 (int x) { int a = -15, b = 15; return x / a > b; }
__attribute__((noinline, noclone)) int f58 (int x) { return x / -15 > -15; }
__attribute__((noinline, noclone)) int f59 (int x) { int a = -15, b = -15; return x / a > b; }
__attribute__((noinline, noclone)) int f60 (int x) { return x / -15 >= 15; }
__attribute__((noinline, noclone)) int f61 (int x) { int a = -15, b = 15; return x / a >= b; }
__attribute__((noinline, noclone)) int f62 (int x) { return x / -15 >= -15; }
__attribute__((noinline, noclone)) int f63 (int x) { int a = -15, b = -15; return x / a >= b; }
__attribute__((noinline, noclone)) int f64 (int x) { return x / -15 < 15; }
__attribute__((noinline, noclone)) int f65 (int x) { int a = -15, b = 15; return x / a < b; }
__attribute__((noinline, noclone)) int f66 (int x) { return x / -15 < -15; }
__attribute__((noinline, noclone)) int f67 (int x) { int a = -15, b = -15; return x / a < b; }
__attribute__((noinline, noclone)) int f68 (int x) { return x / -15 <= 15; }
__attribute__((noinline, noclone)) int f69 (int x) { int a = -15, b = 15; return x / a <= b; }
__attribute__((noinline, noclone)) int f70 (int x) { return x / -15 <= -15; }
__attribute__((noinline, noclone)) int f71 (int x) { int a = -15, b = -15; return x / a <= b; }
__attribute__((noinline, noclone)) int f72 (int x) { return x / -15 == 15; }
__attribute__((noinline, noclone)) int f73 (int x) { int a = -15, b = 15; return x / a == b; }
__attribute__((noinline, noclone)) int f74 (int x) { return x / -15 == -15; }
__attribute__((noinline, noclone)) int f75 (int x) { int a = -15, b = -15; return x / a == b; }
__attribute__((noinline, noclone)) int f76 (int x) { return x / -15 != 15; }
__attribute__((noinline, noclone)) int f77 (int x) { int a = -15, b = 15; return x / a != b; }
__attribute__((noinline, noclone)) int f78 (int x) { return x / -15 != -15; }
__attribute__((noinline, noclone)) int f79 (int x) { int a = -15, b = -15; return x / a != b; }
__attribute__((noinline, noclone)) int f80 (int x) { return x / -15 > 0; }
__attribute__((noinline, noclone)) int f81 (int x) { int a = -15, b = 0; return x / a > b; }
__attribute__((noinline, noclone)) int f82 (int x) { return x / 15 > 0; }
__attribute__((noinline, noclone)) int f83 (int x) { int a = 15, b = 0; return x / a > b; }
__attribute__((noinline, noclone)) int f84 (int x) { return x / -15 >= 0; }
__attribute__((noinline, noclone)) int f85 (int x) { int a = -15, b = 0; return x / a >= b; }
__attribute__((noinline, noclone)) int f86 (int x) { return x / 15 >= 0; }
__attribute__((noinline, noclone)) int f87 (int x) { int a = 15, b = 0; return x / a >= b; }
__attribute__((noinline, noclone)) int f88 (int x) { return x / -15 < 0; }
__attribute__((noinline, noclone)) int f89 (int x) { int a = -15, b = 0; return x / a < b; }
__attribute__((noinline, noclone)) int f90 (int x) { return x / 15 < 0; }
__attribute__((noinline, noclone)) int f91 (int x) { int a = 15, b = 0; return x / a < b; }
__attribute__((noinline, noclone)) int f92 (int x) { return x / -15 <= 0; }
__attribute__((noinline, noclone)) int f93 (int x) { int a = -15, b = 0; return x / a <= b; }
__attribute__((noinline, noclone)) int f94 (int x) { return x / 15 <= 0; }
__attribute__((noinline, noclone)) int f95 (int x) { int a = 15, b = 0; return x / a <= b; }
__attribute__((noinline, noclone)) int f96 (int x) { return x / -15 == 0; }
__attribute__((noinline, noclone)) int f97 (int x) { int a = -15, b = 0; return x / a == b; }
__attribute__((noinline, noclone)) int f98 (int x) { return x / 15 == 0; }
__attribute__((noinline, noclone)) int f99 (int x) { int a = 15, b = 0; return x / a == b; }
__attribute__((noinline, noclone)) int f100 (int x) { return x / -15 != 0; }
__attribute__((noinline, noclone)) int f101 (int x) { int a = -15, b = 0; return x / a != b; }
__attribute__((noinline, noclone)) int f102 (int x) { return x / 15 != 0; }
__attribute__((noinline, noclone)) int f103 (int x) { int a = 15, b = 0; return x / a != b; }
/* PR tree-optimization/81346 */
/* { dg-do run } */
/* { dg-options "-O2" } */
#include "pr81346-3.c"
#define INT_MAX __INT_MAX__
#define INT_MIN (-__INT_MAX__ - 1)
extern void abort (void);
int
main ()
{
if (__CHAR_BIT__ != 8 || __SIZEOF_INT__ != 4)
return 0;
#define TEST(fn1, fn2, v1, v2) \
do { \
int w1 = v1; int w2 = v2; \
int in = 1; if (w1 > w2) { in = w1; w1 = w2; w2 = in; in = 0; } \
if (w1 != INT_MIN) { if (fn1 (w1 - 1) != !in || fn2 (w1 - 1) != !in) abort (); } \
if (fn1 (w1) != in || fn2 (w1) != in) abort (); \
if (fn1 (w2) != in || fn2 (w2) != in) abort (); \
if (w2 != INT_MAX) { if (fn1 (w2 + 1) != !in || fn2 (w2 + 1) != !in) abort (); } \
} while (0)
TEST (f00, f01, -2147441939, INT_MAX);
TEST (f02, f03, 2147441940, INT_MAX);
TEST (f04, f05, INT_MIN, 2147441939);
TEST (f06, f07, INT_MIN, -2147441940);
TEST (f08, f09, INT_MIN, -2147441940);
TEST (f10, f11, 2147441940, INT_MAX);
TEST (f12, f13, -2147441939, INT_MAX);
TEST (f14, f15, INT_MIN, 2147441939);
TEST (f16, f17, -224, INT_MAX);
TEST (f18, f19, 240, INT_MAX);
TEST (f20, f21, -239, INT_MAX);
TEST (f22, f23, 225, INT_MAX);
TEST (f24, f25, INT_MIN, -240);
TEST (f26, f27, INT_MIN, 224);
TEST (f28, f29, INT_MIN, -225);
TEST (f30, f31, INT_MIN, 239);
TEST (f32, f33, -239, -225);
TEST (f34, f35, 225, 239);
TEST (f36, f37, -225, -239);
TEST (f38, f39, 239, 225);
TEST (f40, f41, INT_MIN, 2147441939);
TEST (f42, f43, INT_MIN, -2147441940);
TEST (f44, f45, -2147441939, INT_MAX);
TEST (f46, f47, 2147441940, INT_MAX);
TEST (f48, f49, INT_MIN, -2147441940);
TEST (f50, f51, 2147441940, INT_MAX);
TEST (f52, f53, -2147441939, INT_MAX);
TEST (f54, f55, INT_MIN, 2147441939);
TEST (f56, f57, INT_MIN, -240);
TEST (f58, f59, INT_MIN, 224);
TEST (f60, f61, INT_MIN, -225);
TEST (f62, f63, INT_MIN, 239);
TEST (f64, f65, -224, INT_MAX);
TEST (f66, f67, 240, INT_MAX);
TEST (f68, f69, -239, INT_MAX);
TEST (f70, f71, 225, INT_MAX);
TEST (f72, f73, -239, -225);
TEST (f74, f75, 225, 239);
TEST (f76, f77, -225, -239);
TEST (f78, f79, 239, 225);
TEST (f80, f81, INT_MIN, -15);
TEST (f82, f83, 15, INT_MAX);
TEST (f84, f85, INT_MIN, 14);
TEST (f86, f87, -14, INT_MAX);
TEST (f88, f89, 15, INT_MAX);
TEST (f90, f91, INT_MIN, -15);
TEST (f92, f93, -14, INT_MAX);
TEST (f94, f95, INT_MIN, 14);
TEST (f96, f97, -14, 14);
TEST (f98, f99, -14, 14);
TEST (f100, f101, 14, -14);
TEST (f102, f103, 14, -14);
return 0;
}
...@@ -9,9 +9,11 @@ int ...@@ -9,9 +9,11 @@ int
main () main ()
{ {
unsigned char cy; unsigned char cy;
unsigned char cz = 1;
cy = cx / 6; if (cy != 1) exit (1); asm ("" : "+q" (cz));
cy = cx % 6; if (cy != 1) exit (1);
cy = cx / 6; if (cy != cz) exit (1);
cy = cx % 6; if (cy != cz) exit (1);
exit(0); exit(0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment