OSDN Git Service

2000-08-10 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 270371c..e97e7b7 100644 (file)
@@ -92,6 +92,12 @@ Boston, MA 02111-1307, USA.  */
           || XEXP (X, 0) == virtual_outgoing_args_rtx))        \
    || GET_CODE (X) == ADDRESSOF)
 
+/* Much code operates on (low, high) pairs; the low value is an
+   unsigned wide int, the high value a signed wide int.  We
+   occasionally need to sign extend from low to high as if low were a
+   signed wide int.  */
+#define HWI_SIGN_EXTEND(low) \
+ ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
 
 static rtx simplify_plus_minus         PARAMS ((enum rtx_code,
                                                 enum machine_mode, rtx, rtx));
@@ -246,7 +252,7 @@ simplify_unary_operation (code, mode, op, op_mode)
       REAL_VALUE_TYPE d;
 
       if (GET_CODE (op) == CONST_INT)
-       lv = INTVAL (op), hv = INTVAL (op) < 0 ? -1 : 0;
+       lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
       else
        lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
 
@@ -279,7 +285,7 @@ simplify_unary_operation (code, mode, op, op_mode)
       REAL_VALUE_TYPE d;
 
       if (GET_CODE (op) == CONST_INT)
-       lv = INTVAL (op), hv = INTVAL (op) < 0 ? -1 : 0;
+       lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv);
       else
        lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
 
@@ -399,12 +405,13 @@ simplify_unary_operation (code, mode, op, op_mode)
   else if (GET_MODE (op) == VOIDmode && width <= HOST_BITS_PER_INT * 2
           && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
     {
-      HOST_WIDE_INT l1, h1, lv, hv;
+      unsigned HOST_WIDE_INT l1, lv;
+      HOST_WIDE_INT h1, hv;
 
       if (GET_CODE (op) == CONST_DOUBLE)
        l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op);
       else
-       l1 = INTVAL (op), h1 = l1 < 0 ? -1 : 0;
+       l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1);
 
       switch (code)
        {
@@ -458,7 +465,7 @@ simplify_unary_operation (code, mode, op, op_mode)
                            << (GET_MODE_BITSIZE (op_mode) - 1))) != 0)
                lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
 
-             hv = (lv < 0) ? ~ (HOST_WIDE_INT) 0 : 0;
+             hv = HWI_SIGN_EXTEND (lv);
            }
          break;
 
@@ -709,17 +716,18 @@ simplify_binary_operation (code, mode, op0, op1)
       && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
       && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
     {
-      HOST_WIDE_INT l1, l2, h1, h2, lv, hv;
+      unsigned HOST_WIDE_INT l1, l2, lv;
+      HOST_WIDE_INT h1, h2, hv;
 
       if (GET_CODE (op0) == CONST_DOUBLE)
        l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0);
       else
-       l1 = INTVAL (op0), h1 = l1 < 0 ? -1 : 0;
+       l1 = INTVAL (op0), h1 = HWI_SIGN_EXTEND (l1);
 
       if (GET_CODE (op1) == CONST_DOUBLE)
        l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1);
       else
-       l2 = INTVAL (op1), h2 = l2 < 0 ? -1 : 0;
+       l2 = INTVAL (op1), h2 = HWI_SIGN_EXTEND (l2);
 
       switch (code)
        {
@@ -803,7 +811,7 @@ simplify_binary_operation (code, mode, op0, op1)
            l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
 #endif
 
-         if (h2 != 0 || l2 < 0 || l2 >= GET_MODE_BITSIZE (mode))
+         if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode))
            return 0;
 
          if (code == LSHIFTRT || code == ASHIFTRT)
@@ -940,11 +948,29 @@ simplify_binary_operation (code, mode, op0, op1)
               || ! FLOAT_MODE_P (mode) || flag_fast_math)
              && op1 == CONST0_RTX (mode))
            return op0;
+#endif
+
+         /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags).  */
+         if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT)
+              || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU))
+             && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx)
+           {
+             rtx xop00 = XEXP (op0, 0);
+             rtx xop10 = XEXP (op1, 0);
+
+#ifdef HAVE_cc0
+             if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0)
 #else
-         /* Do nothing here.  */
+             if (GET_CODE (xop00) == REG && GET_CODE (xop10) == REG
+                 && GET_MODE (xop00) == GET_MODE (xop10)
+                 && REGNO (xop00) == REGNO (xop10)
+                 && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC
+                 && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC)
 #endif
-         break;
-             
+               return xop00;
+           }
+
+         break;              
        case MINUS:
          /* None of these optimizations can be done for IEEE
             floating point.  */
@@ -1665,6 +1691,11 @@ simplify_relational_operation (code, mode, op0, op1)
   int equal, op0lt, op0ltu, op1lt, op1ltu;
   rtx tem;
 
+  if (mode == VOIDmode
+      && (GET_MODE (op0) != VOIDmode
+         || GET_MODE (op1) != VOIDmode))
+    abort();
+
   /* If op0 is a compare, extract the comparison arguments from it.  */
   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
     op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
@@ -1752,7 +1783,7 @@ simplify_relational_operation (code, mode, op0, op1)
       else
        {
          l0u = l0s = INTVAL (op0);
-         h0u = h0s = l0s < 0 ? -1 : 0;
+         h0u = h0s = HWI_SIGN_EXTEND (l0s);
        }
          
       if (GET_CODE (op1) == CONST_DOUBLE)
@@ -1763,13 +1794,13 @@ simplify_relational_operation (code, mode, op0, op1)
       else
        {
          l1u = l1s = INTVAL (op1);
-         h1u = h1s = l1s < 0 ? -1 : 0;
+         h1u = h1s = HWI_SIGN_EXTEND (l1s);
        }
 
       /* If WIDTH is nonzero and smaller than HOST_BITS_PER_WIDE_INT,
         we have to sign or zero-extend the values.  */
       if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
-       h0u = h1u = 0, h0s = l0s < 0 ? -1 : 0, h1s = l1s < 0 ? -1 : 0;
+       h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s);
 
       if (width != 0 && width < HOST_BITS_PER_WIDE_INT)
        {
@@ -1784,8 +1815,8 @@ simplify_relational_operation (code, mode, op0, op1)
        }
 
       equal = (h0u == h1u && l0u == l1u);
-      op0lt = (h0s < h1s || (h0s == h1s && l0s < l1s));
-      op1lt = (h1s < h0s || (h1s == h0s && l1s < l0s));
+      op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u));
+      op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u));
       op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u));
       op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u));
     }
@@ -1904,7 +1935,7 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
       if (GET_CODE (op0) == CONST_INT
          && GET_CODE (op1) == CONST_INT
          && GET_CODE (op2) == CONST_INT
-         && INTVAL (op1) + INTVAL (op2) <= GET_MODE_BITSIZE (op0_mode)
+         && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width)
          && width <= (unsigned) HOST_BITS_PER_WIDE_INT)
        {
          /* Extracting a bit-field from a constant */
@@ -1954,8 +1985,11 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
        return op2;
       else if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && ! side_effects_p (op0))
        {
+         enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
+                                       ? GET_MODE (XEXP (op0, 1))
+                                       : GET_MODE (XEXP (op0, 0)));
          rtx temp
-            = simplify_relational_operation (GET_CODE (op0), op0_mode,
+            = simplify_relational_operation (GET_CODE (op0), cmp_mode,
                                              XEXP (op0, 0), XEXP (op0, 1));
 
          /* See if any simplifications were possible.  */
@@ -2509,6 +2543,8 @@ hash_rtx (x, mode, create)
     case PRE_INC:
     case POST_DEC:
     case POST_INC:
+    case POST_MODIFY:
+    case PRE_MODIFY:
     case PC:
     case CC0:
     case CALL:
@@ -3153,7 +3189,7 @@ cselib_process_insn (insn)
       return;
     }
 
-  if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+  if (! INSN_P (insn))
     {
       cselib_current_insn = 0;
       return;