* fold-const.c (extract_muldiv) [case PLUS_EXPR]: If not MULT_EXPR,
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Feb 2001 12:28:07 +0000 (12:28 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Feb 2001 12:28:07 +0000 (12:28 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39996 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20010222-1.c [new file with mode: 0644]

index 3a6eabc..f3ad243 100644 (file)
@@ -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
index 1793f55..99a602c 100644 (file)
@@ -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));
index a41d374..be04efb 100644 (file)
@@ -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 (file)
index 0000000..c3a2b18
--- /dev/null
@@ -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);
+}