OSDN Git Service

2006-03-09 Roger Sayle <roger@eyesopen.com>
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 14:54:11 +0000 (14:54 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 14:54:11 +0000 (14:54 +0000)
    Eric Botcazou  <ebotcazou@libertysurf.fr>

PR middle-end/26561
* fold-const.c (fold_div_compare): When optimizing X/C1 op C2 as
X op C3, consider whether C3 overflows towards +Inf or -Inf.

* gcc.c-torture/execute/divcmp-5.c: New test case.

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

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

index 047033c..5539174 100644 (file)
@@ -1,3 +1,9 @@
+2006-03-09  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/26561
+       * fold-const.c (fold_div_compare): When optimizing X/C1 op C2 as
+       X op C3, consider whether C3 overflows towards +Inf or -Inf.
+
 2006-03-08  DJ Delorie  <dj@redhat.com>
 
        * config/m32c/addsub.md (addqi3): Disparage a0/a1.
 2006-03-08  DJ Delorie  <dj@redhat.com>
 
        * config/m32c/addsub.md (addqi3): Disparage a0/a1.
index 2e89969..be0c461 100644 (file)
@@ -6014,6 +6014,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
   tree arg01 = TREE_OPERAND (arg0, 1);
   unsigned HOST_WIDE_INT lpart;
   HOST_WIDE_INT hpart;
   tree arg01 = TREE_OPERAND (arg0, 1);
   unsigned HOST_WIDE_INT lpart;
   HOST_WIDE_INT hpart;
+  bool neg_overflow;
   int overflow;
 
   /* We have to do this the hard way to detect unsigned overflow.
   int overflow;
 
   /* We have to do this the hard way to detect unsigned overflow.
@@ -6024,6 +6025,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
   prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
   prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
+  neg_overflow = false;
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
     {
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
     {
@@ -6046,6 +6048,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
       switch (tree_int_cst_sgn (arg1))
        {
        case -1:
       switch (tree_int_cst_sgn (arg1))
        {
        case -1:
+         neg_overflow = true;
          lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
          hi = prod;
          break;
          lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
          hi = prod;
          break;
@@ -6083,7 +6086,8 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        case  1:
          break;
 
        case  1:
-          lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+         neg_overflow = true;
+         lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
          hi = prod;
          break;
 
          hi = prod;
          break;
 
@@ -6114,22 +6118,34 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
 
     case LT_EXPR:
       if (TREE_OVERFLOW (lo))
 
     case LT_EXPR:
       if (TREE_OVERFLOW (lo))
-       return omit_one_operand (type, integer_one_node, arg00);
+       {
+         tmp = neg_overflow ? integer_zero_node : integer_one_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (LT_EXPR, type, arg00, lo);
 
     case LE_EXPR:
       if (TREE_OVERFLOW (hi))
       return fold_build2 (LT_EXPR, type, arg00, lo);
 
     case LE_EXPR:
       if (TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_one_node, arg00);
+       {
+         tmp = neg_overflow ? integer_zero_node : integer_one_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (LE_EXPR, type, arg00, hi);
 
     case GT_EXPR:
       if (TREE_OVERFLOW (hi))
       return fold_build2 (LE_EXPR, type, arg00, hi);
 
     case GT_EXPR:
       if (TREE_OVERFLOW (hi))
-       return omit_one_operand (type, integer_zero_node, arg00);
+       {
+         tmp = neg_overflow ? integer_one_node : integer_zero_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (GT_EXPR, type, arg00, hi);
 
     case GE_EXPR:
       if (TREE_OVERFLOW (lo))
       return fold_build2 (GT_EXPR, type, arg00, hi);
 
     case GE_EXPR:
       if (TREE_OVERFLOW (lo))
-       return omit_one_operand (type, integer_zero_node, arg00);
+       {
+         tmp = neg_overflow ? integer_one_node : integer_zero_node;
+         return omit_one_operand (type, tmp, arg00);
+       }
       return fold_build2 (GE_EXPR, type, arg00, lo);
 
     default:
       return fold_build2 (GE_EXPR, type, arg00, lo);
 
     default:
index 3dff55c..b082e56 100644 (file)
@@ -1,3 +1,9 @@
+2006-03-09  Roger Sayle  <roger@eyesopen.com>
+           Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR middle-end/26561
+       * gcc.c-torture/execute/divcmp-5.c: New test case.
+
 2006-03-09 Paul Thomas <pault@gcc.gnu.org>
 
        * PR fortran/26257
 2006-03-09 Paul Thomas <pault@gcc.gnu.org>
 
        * PR fortran/26257
diff --git a/gcc/testsuite/gcc.c-torture/execute/divcmp-5.c b/gcc/testsuite/gcc.c-torture/execute/divcmp-5.c
new file mode 100644 (file)
index 0000000..f6d1af3
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR middle-end/26561 */
+
+extern void abort(void);
+
+int always_one_1 (int a)
+{
+  if (a/100 >= -999999999)
+    return 1;
+  else
+    return 0;
+}
+
+int always_one_2 (int a)
+{
+  if (a/100 < -999999999)
+    return 0;
+  else
+    return 1;
+}
+
+int main(void)
+{
+  if (always_one_1 (0) != 1)
+    abort ();
+
+  if (always_one_2 (0) != 1)
+    abort ();
+
+  return 0;
+}
+