aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2001-02-23 13:28:07 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2001-02-23 13:28:07 +0100
commitfba2c0cdbcf92d860a2acd8a2667a68b723dc8c0 (patch)
treee1f9f314834b3eca87bb067c1aa26c0f4f9580ef
parent487f145008ff00d3d03b0aa1f6d6bcea4a84a404 (diff)
downloadgcc-fba2c0cdbcf92d860a2acd8a2667a68b723dc8c0.zip
gcc-fba2c0cdbcf92d860a2acd8a2667a68b723dc8c0.tar.gz
gcc-fba2c0cdbcf92d860a2acd8a2667a68b723dc8c0.tar.bz2
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c33
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20010222-1.c9
4 files changed, 49 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3a6eabc..f3ad243 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2001-02-23 Jakub Jelinek <jakub@redhat.com>
+
+ * 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 <rth@redhat.com>
* config/ia64/crtbegin.asm (.fini): Use pc-relative relocs to
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 1793f55..99a602cd 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 a41d374..be04efb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-02-23 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/20010222-1.c: New test.
+
2001-02-22 Jakub Jelinek <jakub@redhat.com>
* 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 0000000..c3a2b18
--- /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);
+}