From 7588d8aae498ba0a9643858555ac44e97877d5cf Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 11 May 2014 20:21:55 +0000 Subject: [PATCH] re PR c/61136 (ice in tree_nop_conversion) gcc/ PR tree-optimization/61136 * wide-int.h (multiple_of_p): Define a version that doesn't return the quotient. * fold-const.c (extract_muldiv_1): Use wi::multiple_of_p instead of an integer_zerop/const_binop pair. (multiple_of_p): Likewise, converting both operands to widest_int precision. gcc/testsuite/ * gcc.dg/torture/pr61136.c: New test. From-SVN: r210312 --- gcc/ChangeLog | 10 ++++++++++ gcc/fold-const.c | 14 +++++++------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/torture/pr61136.c | 5 +++++ gcc/wide-int.h | 12 ++++++++++++ 5 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr61136.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 67bfdbf..083aca3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2014-05-11 Richard Sandiford + + PR tree-optimization/61136 + * wide-int.h (multiple_of_p): Define a version that doesn't return + the quotient. + * fold-const.c (extract_muldiv_1): Use wi::multiple_of_p instead of an + integer_zerop/const_binop pair. + (multiple_of_p): Likewise, converting both operands to widest_int + precision. + 2014-05-09 Teresa Johnson * cgraphunit.c (analyze_functions): Use correct dump file. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c5bf811..0fcb87f 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -5708,7 +5708,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, /* For a constant, we can always simplify if we are a multiply or (for divide and modulus) if it is a multiple of our constant. */ if (code == MULT_EXPR - || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c))) + || wi::multiple_of_p (t, c, TYPE_SIGN (type))) return const_binop (code, fold_convert (ctype, t), fold_convert (ctype, c)); break; @@ -5888,7 +5888,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, /* If it's a multiply or a division/modulus operation of a multiple of our constant, do the operation and verify it doesn't overflow. */ if (code == MULT_EXPR - || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c))) + || wi::multiple_of_p (op1, c, TYPE_SIGN (type))) { op1 = const_binop (code, fold_convert (ctype, op1), fold_convert (ctype, c)); @@ -5932,7 +5932,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, /* If the multiplication can overflow we cannot optimize this. */ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)) && TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST - && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c))) + && wi::multiple_of_p (op1, c, TYPE_SIGN (type))) { *strict_overflow_p = true; return omit_one_operand (type, integer_zero_node, op0); @@ -5989,7 +5989,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, && code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR && code != MULT_EXPR))) { - if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c))) + if (wi::multiple_of_p (op1, c, TYPE_SIGN (type))) { if (TYPE_OVERFLOW_UNDEFINED (ctype)) *strict_overflow_p = true; @@ -5998,7 +5998,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, const_binop (TRUNC_DIV_EXPR, op1, c))); } - else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1))) + else if (wi::multiple_of_p (c, op1, TYPE_SIGN (type))) { if (TYPE_OVERFLOW_UNDEFINED (ctype)) *strict_overflow_p = true; @@ -15314,8 +15314,8 @@ multiple_of_p (tree type, const_tree top, const_tree bottom) && (tree_int_cst_sgn (top) < 0 || tree_int_cst_sgn (bottom) < 0))) return 0; - return integer_zerop (int_const_binop (TRUNC_MOD_EXPR, - top, bottom)); + return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom), + SIGNED); default: return 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bcf4038..7459796 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-11 Richard Sandiford + + * gcc.dg/torture/pr61136.c: New test. + 2014-05-11 Paolo Carlini PR c++/59705 diff --git a/gcc/testsuite/gcc.dg/torture/pr61136.c b/gcc/testsuite/gcc.dg/torture/pr61136.c new file mode 100644 index 0000000..4fc908a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr61136.c @@ -0,0 +1,5 @@ +unsigned long long +foo (int a) +{ + return a * 7 & 1ULL << 63; +} diff --git a/gcc/wide-int.h b/gcc/wide-int.h index 46a1c22..d5ab428 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -530,6 +530,9 @@ namespace wi BINARY_FUNCTION mod_round (const T1 &, const T2 &, signop, bool * = 0); template + bool multiple_of_p (const T1 &, const T2 &, signop); + + template bool multiple_of_p (const T1 &, const T2 &, signop, WI_BINARY_RESULT (T1, T2) *); @@ -2791,6 +2794,15 @@ wi::mod_round (const T1 &x, const T2 &y, signop sgn, bool *overflow) return remainder; } +/* Return true if X is a multiple of Y. Treat X and Y as having the + signedness given by SGN. */ +template +inline bool +wi::multiple_of_p (const T1 &x, const T2 &y, signop sgn) +{ + return wi::mod_trunc (x, y, sgn) == 0; +} + /* Return true if X is a multiple of Y, storing X / Y in *RES if so. Treat X and Y as having the signedness given by SGN. */ template -- 2.7.4