OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 4bcaf38..6010cb7 100644 (file)
@@ -646,12 +646,22 @@ combine_instructions (f, nregs)
          /* Try each sequence of three linked insns ending with this one.  */
 
          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks;
-                nextlinks = XEXP (nextlinks, 1))
-             if ((next = try_combine (insn, XEXP (links, 0),
-                                      XEXP (nextlinks, 0),
-                                      &new_direct_jump_p)) != 0)
-               goto retry;
+           {
+             rtx link = XEXP (links, 0);
+
+             /* If the linked insn has been replaced by a note, then there
+                is no point in persuing this chain any further.  */
+             if (GET_CODE (link) == NOTE)
+               break;
+
+             for (nextlinks = LOG_LINKS (link);
+                  nextlinks;
+                  nextlinks = XEXP (nextlinks, 1))
+               if ((next = try_combine (insn, XEXP (links, 0),
+                                        XEXP (nextlinks, 0),
+                                        &new_direct_jump_p)) != 0)
+                 goto retry;
+           }
 
 #ifdef HAVE_cc0
          /* Try to combine a jump insn that uses CC0
@@ -1470,7 +1480,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
      register rtx i3, i2, i1;
      register int *new_direct_jump_p;
 {
-  /* New patterns for I3 and I3, respectively.  */
+  /* New patterns for I3 and I2, respectively.  */
   rtx newpat, newi2pat = 0;
   /* Indicates need to preserve SET in I1 or I2 in I3 if it is not dead.  */
   int added_sets_1, added_sets_2;
@@ -2502,7 +2512,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        actually came from I3, so that REG_UNUSED notes from I2 will be
        properly handled.  */
 
-    if (i3_subst_into_i2)
+    if (i3_subst_into_i2 && GET_CODE (PATTERN (i2)) == PARALLEL)
       {
        if (GET_CODE (PATTERN (i2)) == PARALLEL)
          {
@@ -2714,11 +2724,11 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       }
 
     /* Update reg_nonzero_bits et al for any changes that may have been made
-       to this insn.  */
-
-    note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
+       to this insn.  The order of set_nonzero_bits_and_sign_copies() is 
+       important.  Because newi2pat can affect nonzero_bits of newpat */
     if (newi2pat)
       note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
+    note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
 
     /* Set new_direct_jump_p if a new return or simple jump instruction
        has been created.
@@ -2727,7 +2737,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        BARRIER following it since it may have initially been a
        conditional jump.  It may also be the last nonnote insn.  */
     
-    if (GET_CODE (newpat) == RETURN || simplejump_p (i3))
+    if (GET_CODE (newpat) == RETURN || any_uncondjump_p (i3))
       {
        *new_direct_jump_p = 1;
 
@@ -3390,6 +3400,18 @@ subst (x, from, to, in_dest, unique_copy)
                      )
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 
+#ifdef CLASS_CANNOT_CHANGE_MODE
+                 if (code == SUBREG
+                     && GET_CODE (to) == REG
+                     && REGNO (to) < FIRST_PSEUDO_REGISTER
+                     && (TEST_HARD_REG_BIT
+                         (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
+                          REGNO (to)))
+                     && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
+                                                    GET_MODE (x)))
+                   return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
+#endif
+
                  new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
                  n_occurrences++;
                }
@@ -3567,37 +3589,44 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          true = subst (true, pc_rtx, pc_rtx, 0, 0);
          false = subst (false, pc_rtx, pc_rtx, 0, 0);
 
-         /* Restarting if we generate a store-flag expression will cause
-            us to loop.  Just drop through in this case.  */
-
-         /* If the result values are STORE_FLAG_VALUE and zero, we can
-            just make the comparison operation.  */
-         if (true == const_true_rtx && false == const0_rtx)
-           x = gen_binary (cond_code, mode, cond, cop1);
-         else if (true == const0_rtx && false == const_true_rtx)
-           x = gen_binary (reverse_condition (cond_code), mode, cond, cop1);
-
-         /* Likewise, we can make the negate of a comparison operation
-            if the result values are - STORE_FLAG_VALUE and zero.  */
-         else if (GET_CODE (true) == CONST_INT
-                  && INTVAL (true) == - STORE_FLAG_VALUE
-                  && false == const0_rtx)
-           x = gen_unary (NEG, mode, mode,
-                          gen_binary (cond_code, mode, cond, cop1));
-         else if (GET_CODE (false) == CONST_INT
-                  && INTVAL (false) == - STORE_FLAG_VALUE
-                  && true == const0_rtx)
-           x = gen_unary (NEG, mode, mode,
-                          gen_binary (reverse_condition (cond_code), 
-                                      mode, cond, cop1));
-         else
-           return gen_rtx_IF_THEN_ELSE (mode,
-                                        gen_binary (cond_code, VOIDmode,
-                                                    cond, cop1),
-                                        true, false);
+         /* If true and false are not general_operands, an if_then_else
+            is unlikely to be simpler.  */
+         if (general_operand (true, VOIDmode)
+             && general_operand (false, VOIDmode))
+           {
+             /* Restarting if we generate a store-flag expression will cause
+                us to loop.  Just drop through in this case.  */
+
+             /* If the result values are STORE_FLAG_VALUE and zero, we can
+                just make the comparison operation.  */
+             if (true == const_true_rtx && false == const0_rtx)
+               x = gen_binary (cond_code, mode, cond, cop1);
+             else if (true == const0_rtx && false == const_true_rtx)
+               x = gen_binary (reverse_condition (cond_code),
+                               mode, cond, cop1);
+
+             /* Likewise, we can make the negate of a comparison operation
+                if the result values are - STORE_FLAG_VALUE and zero.  */
+             else if (GET_CODE (true) == CONST_INT
+                      && INTVAL (true) == - STORE_FLAG_VALUE
+                      && false == const0_rtx)
+               x = gen_unary (NEG, mode, mode,
+                              gen_binary (cond_code, mode, cond, cop1));
+             else if (GET_CODE (false) == CONST_INT
+                      && INTVAL (false) == - STORE_FLAG_VALUE
+                      && true == const0_rtx)
+               x = gen_unary (NEG, mode, mode,
+                              gen_binary (reverse_condition (cond_code), 
+                                          mode, cond, cop1));
+             else
+               return gen_rtx_IF_THEN_ELSE (mode,
+                                            gen_binary (cond_code, VOIDmode,
+                                                        cond, cop1),
+                                            true, false);
 
-         code = GET_CODE (x);
-         op0_mode = VOIDmode;
+             code = GET_CODE (x);
+             op0_mode = VOIDmode;
+           }
        }
     }
 
@@ -3730,7 +3759,6 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
                           plus_constant (XEXP (inner, 0),
                                          (SUBREG_WORD (x) * UNITS_PER_WORD
                                           + endian_offset)));
-         RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
          MEM_COPY_ATTRIBUTES (x, inner);
          return x;
        }
@@ -4208,7 +4236,17 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (XEXP (x, 0), mode)
              & nonzero_bits (XEXP (x, 1), mode)) == 0)
-       return gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+       {
+         /* Try to simplify the expression further.  */
+         rtx tor = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+         temp = combine_simplify_rtx (tor, mode, last, in_dest);
+
+         /* If we could, great.  If not, do not go ahead with the IOR
+            replacement, since PLUS appears in many special purpose
+            address arithmetic instructions.  */
+         if (GET_CODE (temp) != CLOBBER && temp != tor)
+           return temp;
+       }
       break;
 
     case MINUS:
@@ -4998,13 +5036,13 @@ simplify_set (x)
       && (GET_MODE_SIZE (GET_MODE (src))
          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
 #endif
-#ifdef CLASS_CANNOT_CHANGE_SIZE
+#ifdef CLASS_CANNOT_CHANGE_MODE
       && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
            && (TEST_HARD_REG_BIT
-               (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
+               (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
                 REGNO (dest)))
-           && (GET_MODE_SIZE (GET_MODE (src))
-               != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
+           && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
+                                          GET_MODE (SUBREG_REG (src))))
 #endif                           
       && (GET_CODE (dest) == REG
          || (GET_CODE (dest) == SUBREG
@@ -5912,7 +5950,6 @@ make_extraction (mode, inner, pos, pos_rtx, len,
            offset = pos / BITS_PER_UNIT;
 
          new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
-         RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
          MEM_COPY_ATTRIBUTES (new, inner);
        }
       else if (GET_CODE (inner) == REG)
@@ -6137,7 +6174,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
        {
          rtx newmem = gen_rtx_MEM (wanted_inner_mode,
                                    plus_constant (XEXP (inner, 0), offset));
-         RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
+
          MEM_COPY_ATTRIBUTES (newmem, inner);
          inner = newmem;
        }
@@ -6551,17 +6588,19 @@ get_pos_from_mask (m, plen)
 {
   /* Get the bit number of the first 1 bit from the right, -1 if none.  */
   int pos = exact_log2 (m & - m);
+  int len;
 
   if (pos < 0)
     return -1;
 
   /* Now shift off the low-order zero bits and see if we have a power of
      two minus 1.  */
-  *plen = exact_log2 ((m >> pos) + 1);
+  len = exact_log2 ((m >> pos) + 1);
 
-  if (*plen <= 0)
+  if (len <= 0)
     return -1;
 
+  *plen = len;
   return pos;
 }
 \f
@@ -6809,7 +6848,6 @@ force_to_mode (x, mode, mask, reg, just_select)
 
       /* ... fall through ...  */
 
-    case MINUS:
     case MULT:
       /* For PLUS, MINUS and MULT, we need any bits less significant than the
         most significant bit in MASK since carries from those bits will
@@ -6817,6 +6855,28 @@ force_to_mode (x, mode, mask, reg, just_select)
       mask = fuller_mask;
       goto binop;
 
+    case MINUS:
+      /* If X is (minus C Y) where C's least set bit is larger than any bit
+        in the mask, then we may replace with (neg Y).  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT
+         && (INTVAL (XEXP (x, 0)) & -INTVAL (XEXP (x, 0))) > mask)
+       {
+         x = gen_unary (NEG, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+         return force_to_mode (x, mode, mask, reg, next_select);
+       }
+
+      /* Similarly, if C contains every bit in the mask, then we may
+        replace with (not Y).  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT
+          && (INTVAL (XEXP (x, 0)) | mask) == INTVAL (XEXP (x, 0)))
+       {
+         x = gen_unary (NOT, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+         return force_to_mode (x, mode, mask, reg, next_select);
+       }
+
+      mask = fuller_mask;
+      goto binop;
+
     case IOR:
     case XOR:
       /* If X is (ior (lshiftrt FOO C1) C2), try to commute the IOR and
@@ -8904,7 +8964,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                new = gen_rtx_MEM (tmode,
                                   plus_constant (XEXP (varop, 0),
                                                  count / BITS_PER_UNIT));
-             RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
+
              MEM_COPY_ATTRIBUTES (new, varop);
              varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
                                       : ZERO_EXTEND, mode, new);
@@ -9620,13 +9680,15 @@ gen_lowpart_for_combine (mode, x)
     }
 
   result = gen_lowpart_common (mode, x);
+#ifdef CLASS_CANNOT_CHANGE_MODE
   if (result != 0
       && GET_CODE (result) == SUBREG
       && GET_CODE (SUBREG_REG (result)) == REG
       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
-      && (GET_MODE_SIZE (GET_MODE (result))
-         != GET_MODE_SIZE (GET_MODE (SUBREG_REG (result)))))
-    REG_CHANGES_SIZE (REGNO (SUBREG_REG (result))) = 1;
+      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
+                                    GET_MODE (SUBREG_REG (result))))
+    REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
+#endif
 
   if (result)
     return result;
@@ -9659,7 +9721,6 @@ gen_lowpart_for_combine (mode, x)
                     - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
        }
       new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
-      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
       MEM_COPY_ATTRIBUTES (new, x);
       return new;
     }
@@ -10033,9 +10094,7 @@ simplify_comparison (code, pop0, pop1)
 
       /* Get the constant we are comparing against and turn off all bits
         not on in our mode.  */
-      const_op = INTVAL (op1);
-      if (mode_width <= HOST_BITS_PER_WIDE_INT)
-       const_op &= mask;
+      const_op = trunc_int_for_mode (INTVAL (op1), mode);
 
       /* If we are comparing against a constant power of two and the value
         being compared can only have that single bit nonzero (e.g., it was