From fba2c0cdbcf92d860a2acd8a2667a68b723dc8c0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 23 Feb 2001 13:28:07 +0100 Subject: [PATCH] fold-const.c (extract_muldiv): If not MULT_EXPR, check if either operand is divisible by C. * fold-const.c (extract_muldiv) [case PLUS_EXPR]: If not MULT_EXPR, check if either operand is divisible by C. (multiple_of_p): Handle LSHIFT_EXPR with small constant shift. If type is signed, consider negative numbers as well. * gcc.c-torture/execute/20010222-1.c: New test. From-SVN: r39996 --- gcc/ChangeLog | 7 ++++ gcc/fold-const.c | 33 ++++++++++++++++--- gcc/testsuite/ChangeLog | 4 +++ .../gcc.c-torture/execute/20010222-1.c | 9 +++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20010222-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a6eabc75fa..f3ad2434057 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2001-02-23 Jakub Jelinek + + * fold-const.c (extract_muldiv) [case PLUS_EXPR]: If not MULT_EXPR, + check if either operand is divisible by C. + (multiple_of_p): Handle LSHIFT_EXPR with small constant shift. + If type is signed, consider negative numbers as well. + 2001-02-22 Richard Henderson * config/ia64/crtbegin.asm (.fini): Use pc-relative relocs to diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1793f555680..99a602cd297 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -4487,7 +4487,12 @@ extract_muldiv (t, c, code, wide_type) constant. */ t1 = extract_muldiv (op0, c, code, wide_type); t2 = extract_muldiv (op1, c, code, wide_type); - if (t1 != 0 && t2 != 0) + if (t1 != 0 && t2 != 0 + && (code == MULT_EXPR + /* If not multiplication, we can only do this if either operand + is divisible by c. */ + || multiple_of_p (ctype, op0, c) + || multiple_of_p (ctype, op1, c))) return fold (build (tcode, ctype, convert (ctype, t1), convert (ctype, t2))); @@ -7280,6 +7285,25 @@ multiple_of_p (type, top, bottom) return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom) && multiple_of_p (type, TREE_OPERAND (top, 1), bottom)); + case LSHIFT_EXPR: + if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST) + { + tree op1, t1; + + op1 = TREE_OPERAND (top, 1); + /* const_binop may not detect overflow correctly, + so check for it explicitly here. */ + if (TYPE_PRECISION (TREE_TYPE (size_one_node)) + > TREE_INT_CST_LOW (op1) + && TREE_INT_CST_HIGH (op1) == 0 + && 0 != (t1 = convert (type, + const_binop (LSHIFT_EXPR, size_one_node, + op1, 0))) + && ! TREE_OVERFLOW (t1)) + return multiple_of_p (type, t1, bottom); + } + return 0; + case NOP_EXPR: /* Can't handle conversions from non-integral or wider integral type. */ if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE) @@ -7293,9 +7317,10 @@ multiple_of_p (type, top, bottom) return multiple_of_p (type, TREE_OPERAND (top, 0), bottom); case INTEGER_CST: - if ((TREE_CODE (bottom) != INTEGER_CST) - || (tree_int_cst_sgn (top) < 0) - || (tree_int_cst_sgn (bottom) < 0)) + if (TREE_CODE (bottom) != INTEGER_CST + || (TREE_UNSIGNED (type) + && (tree_int_cst_sgn (top) < 0 + || tree_int_cst_sgn (bottom) < 0))) return 0; return integer_zerop (const_binop (TRUNC_MOD_EXPR, top, bottom, 0)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a41d374f5c8..be04efbfb8c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-02-23 Jakub Jelinek + + * gcc.c-torture/execute/20010222-1.c: New test. + 2001-02-22 Jakub Jelinek * g++.old-deja/g++.other/inline20.C: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/20010222-1.c b/gcc/testsuite/gcc.c-torture/execute/20010222-1.c new file mode 100644 index 00000000000..c3a2b18e5f0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20010222-1.c @@ -0,0 +1,9 @@ +int a[2] = { 18, 6 }; + +int main () +{ + int b = (-3 * a[0] -3 * a[1]) / 12; + if (b != -6) + abort (); + exit (0); +} -- 2.30.2