OSDN Git Service

* reload1.c (move2add_last_cc0): New.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 7792537..f7c9852 100644 (file)
@@ -1065,8 +1065,6 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
 
   /* Don't eliminate a store in the stack pointer.  */
   if (dest == stack_pointer_rtx
-      /* If we couldn't eliminate a field assignment, we can't combine.  */
-      || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART
       /* Don't combine with an insn that sets a register to itself if it has
         a REG_EQUAL note.  This may be part of a REG_NO_CONFLICT sequence.  */
       || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
@@ -1319,46 +1317,16 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
 
   if (GET_CODE (x) == SET)
     {
-      rtx set = expand_field_assignment (x);
+      rtx set = ;
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
       rtx inner_dest = dest;
 
-#if 0
-      rtx inner_src = src;
-#endif
-
-      SUBST (*loc, set);
-
       while (GET_CODE (inner_dest) == STRICT_LOW_PART
             || GET_CODE (inner_dest) == SUBREG
             || GET_CODE (inner_dest) == ZERO_EXTRACT)
        inner_dest = XEXP (inner_dest, 0);
 
-  /* We probably don't need this any more now that LIMIT_RELOAD_CLASS
-     was added.  */
-#if 0
-      while (GET_CODE (inner_src) == STRICT_LOW_PART
-            || GET_CODE (inner_src) == SUBREG
-            || GET_CODE (inner_src) == ZERO_EXTRACT)
-       inner_src = XEXP (inner_src, 0);
-
-      /* If it is better that two different modes keep two different pseudos,
-        avoid combining them.  This avoids producing the following pattern
-        on a 386:
-         (set (subreg:SI (reg/v:QI 21) 0)
-              (lshiftrt:SI (reg/v:SI 20)
-                  (const_int 24)))
-        If that were made, reload could not handle the pair of
-        reg 20/21, since it would try to get any GENERAL_REGS
-        but some of them don't handle QImode.  */
-
-      if (rtx_equal_p (inner_src, i2dest)
-         && GET_CODE (inner_dest) == REG
-         && ! MODES_TIEABLE_P (GET_MODE (i2dest), GET_MODE (inner_dest)))
-       return 0;
-#endif
-
       /* Check for the case where I3 modifies its output, as
         discussed above.  */
       if ((inner_dest != dest
@@ -1467,10 +1435,10 @@ cant_combine_insn_p (insn)
   if (! INSN_P (insn))
     return 1;
 
-  /* Never combine loads and stores involving hard regs.  The register
-     allocator can usually handle such reg-reg moves by tying.  If we allow
-     the combiner to make substitutions of hard regs, we risk aborting in
-     reload on machines that have SMALL_REGISTER_CLASSES.
+  /* Never combine loads and stores involving hard regs that are likely
+     to be spilled.  The register allocator can usually handle such
+     reg-reg moves by tying.  If we allow the combiner to make 
+     substitutions of likely-spilled regs, we may abort in reload.
      As an exception, we allow combinations involving fixed regs; these are
      not available to the register allocator so there's no risk involved.  */
 
@@ -1485,9 +1453,11 @@ cant_combine_insn_p (insn)
     dest = SUBREG_REG (dest);
   if (REG_P (src) && REG_P (dest)
       && ((REGNO (src) < FIRST_PSEUDO_REGISTER
-          && ! fixed_regs[REGNO (src)])
+          && ! fixed_regs[REGNO (src)]
+          && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
          || (REGNO (dest) < FIRST_PSEUDO_REGISTER
-             && ! fixed_regs[REGNO (dest)])))
+             && ! fixed_regs[REGNO (dest)]
+             && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
     return 1;
 
   return 0;
@@ -1689,7 +1659,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            abort ();
 
          lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
-         lo |= (INTVAL (SET_SRC (PATTERN (i3))) 
+         lo |= (INTVAL (SET_SRC (PATTERN (i3)))
                 & (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
        }
       else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
@@ -2856,7 +2826,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            || GET_CODE (temp) != BARRIER)
          emit_barrier_after (undobuf.other_insn);
       }
-       
+
     /* An NOOP jump does not need barrier, but it does need cleaning up
        of CFG.  */
     if (GET_CODE (newpat) == SET
@@ -4044,7 +4014,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1));
        }
 
-      /* (neg (mult A B)) becomes (mult (neg A) B).  
+      /* (neg (mult A B)) becomes (mult (neg A) B).
          This works even for floating-point values.  */
       if (GET_CODE (XEXP (x, 0)) == MULT)
        {
@@ -4185,15 +4155,15 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
        return XEXP (XEXP (x, 0), 0);
 
-      /* (float_truncate:SF (float_truncate:DF foo:XF)) 
-         = (float_truncate:SF foo:XF). 
+      /* (float_truncate:SF (float_truncate:DF foo:XF))
+         = (float_truncate:SF foo:XF).
         This may elliminate double rounding, so it is unsafe.
 
-         (float_truncate:SF (float_extend:XF foo:DF)) 
-         = (float_truncate:SF foo:DF). 
+         (float_truncate:SF (float_extend:XF foo:DF))
+         = (float_truncate:SF foo:DF).
 
-         (float_truncate:DF (float_extend:XF foo:SF)) 
-         = (float_extend:SF foo:DF). */
+         (float_truncate:DF (float_extend:XF foo:SF))
+         = (float_extend:SF foo:DF).  */
       if ((GET_CODE (XEXP (x, 0)) == FLOAT_TRUNCATE
           && flag_unsafe_math_optimizations)
          || GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND)
@@ -4233,9 +4203,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       break;
     case FLOAT_EXTEND:
       /*  (float_extend (float_extend x)) is (float_extend x)
-        
+
          (float_extend (float x)) is (float x) assuming that double
-         rounding can't happen. 
+         rounding can't happen.
           */
       if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
          || (GET_CODE (XEXP (x, 0)) == FLOAT
@@ -4288,11 +4258,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
     case PLUS:
       /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).
        */
-      if (GET_CODE (XEXP (x, 0)) == MULT 
+      if (GET_CODE (XEXP (x, 0)) == MULT
          && GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
        {
          rtx in1, in2;
-        
+
          in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
          in2 = XEXP (XEXP (x, 0), 1);
          return gen_binary (MINUS, mode, XEXP (x, 1),
@@ -4407,24 +4377,24 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
       /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A).
        */
-      if (GET_CODE (XEXP (x, 1)) == MULT 
+      if (GET_CODE (XEXP (x, 1)) == MULT
          && GET_CODE (XEXP (XEXP (x, 1), 0)) == NEG)
        {
          rtx in1, in2;
-        
+
          in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
          in2 = XEXP (XEXP (x, 1), 1);
          return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2),
                             XEXP (x, 0));
        }
 
-      /* Canonicalize (minus (neg A) (mult B C)) to 
+      /* Canonicalize (minus (neg A) (mult B C)) to
         (minus (mult (neg B) C) A).  */
-      if (GET_CODE (XEXP (x, 1)) == MULT 
+      if (GET_CODE (XEXP (x, 1)) == MULT
          && GET_CODE (XEXP (x, 0)) == NEG)
        {
          rtx in1, in2;
-        
+
          in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
          in2 = XEXP (XEXP (x, 1), 1);
          return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2),
@@ -4494,10 +4464,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
         with it.  */
       if (GET_CODE (XEXP (x, 0)) == COMPARE
          || (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC
-#ifdef HAVE_cc0
-             && XEXP (x, 0) != cc0_rtx
-#endif
-             ))
+             && ! CC0_P (XEXP (x, 0))))
        {
          rtx op0 = XEXP (x, 0);
          rtx op1 = XEXP (x, 1);
@@ -4972,7 +4939,9 @@ simplify_if_then_else (x)
      neither 1 or -1, but it isn't worth checking for.  */
 
   if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
-      && comparison_p && mode != VOIDmode && ! side_effects_p (x))
+      && comparison_p
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && ! side_effects_p (x))
     {
       rtx t = make_compound_operation (true_rtx, SET);
       rtx f = make_compound_operation (false_rtx, SET);
@@ -5314,7 +5283,7 @@ simplify_set (x)
 #ifdef CANNOT_CHANGE_MODE_CLASS
       && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
            && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
-                                        GET_MODE (SUBREG_REG (src)), 
+                                        GET_MODE (SUBREG_REG (src)),
                                         GET_MODE (src)))
 #endif
       && (GET_CODE (dest) == REG
@@ -7361,7 +7330,8 @@ force_to_mode (x, mode, mask, reg, just_select)
              < GET_MODE_BITSIZE (GET_MODE (x)))
          && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT)
        {
-         temp = GEN_INT (mask << INTVAL (XEXP (XEXP (x, 0), 1)));
+         temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
+                              GET_MODE (x));
          temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp);
          x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1));
 
@@ -7925,6 +7895,17 @@ make_field_assignment (x)
                       : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                       dest, 0);
 
+  /* If SRC is masked by an AND that does not make a difference in
+     the value being stored, strip it.  */
+  if (GET_CODE (assign) == ZERO_EXTRACT
+      && GET_CODE (XEXP (assign, 1)) == CONST_INT
+      && INTVAL (XEXP (assign, 1)) < HOST_BITS_PER_WIDE_INT
+      && GET_CODE (src) == AND
+      && GET_CODE (XEXP (src, 1)) == CONST_INT
+      && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (src, 1))
+         == ((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (assign, 1))) - 1))
+    src = XEXP (src, 0);
+
   return gen_rtx_SET (VOIDmode, assign, src);
 }
 \f
@@ -9252,7 +9233,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
          op0 = AND, *pcomp_p = 1;
        else /* op1 == IOR */
          /* (a | b) ^ b == a & ~b */
-         op0 = AND, *pconst0 = ~const0;
+         op0 = AND, const0 = ~const0;
        break;
 
       case AND:
@@ -9434,12 +9415,12 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
       if (code == LSHIFTRT
          && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
          && !(nonzero_bits (varop, shift_mode) >> count))
-       return const0_rtx;
+       varop = const0_rtx;
       if (code == ASHIFT
          && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
          && !((nonzero_bits (varop, shift_mode) << count)
               & GET_MODE_MASK (shift_mode)))
-       return const0_rtx;
+       varop = const0_rtx;
 
       switch (GET_CODE (varop))
        {
@@ -10204,8 +10185,9 @@ gen_lowpart_for_combine (mode, x)
       && GET_CODE (result) == SUBREG
       && GET_CODE (SUBREG_REG (result)) == REG
       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
-    SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
-                      REGNO (SUBREG_REG (result)));
+    bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result))
+                                     * MAX_MACHINE_MODE
+                                     + GET_MODE (result));
 #endif
 
   if (result)
@@ -11010,9 +10992,7 @@ simplify_comparison (code, pop0, pop1)
          /* We can't do anything if OP0 is a condition code value, rather
             than an actual data value.  */
          if (const_op != 0
-#ifdef HAVE_cc0
-             || XEXP (op0, 0) == cc0_rtx
-#endif
+             || CC0_P (XEXP (op0, 0))
              || GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
            break;
 
@@ -11130,46 +11110,45 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
 
-         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 fits
-            in both M1 and M2 and the SUBREG is either paradoxical or
-            represents the low part, permute the SUBREG and the AND and
-            try again.  */
-         if (GET_CODE (XEXP (op0, 0)) == SUBREG
-             /* It is unsafe to commute the AND into the SUBREG if the SUBREG
-                is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
-                As originally written the upper bits have a defined value
-                due to the AND operation.  However, if we commute the AND
-                inside the SUBREG then they no longer have defined values
-                and the meaning of the code has been changed.  */
-             && (0
+         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1
+            fits in both M1 and M2 and the SUBREG is either paradoxical
+            or represents the low part, permute the SUBREG and the AND
+            and try again.  */
+         if (GET_CODE (XEXP (op0, 0)) == SUBREG)
+           {
+             unsigned HOST_WIDE_INT c1;
+             tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
+             /* Require an integral mode, to avoid creating something like
+                (AND:SF ...).  */
+             if (SCALAR_INT_MODE_P (tmode)
+                 /* It is unsafe to commute the AND into the SUBREG if the
+                    SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
+                    not defined.  As originally written the upper bits
+                    have a defined value due to the AND operation.
+                    However, if we commute the AND inside the SUBREG then
+                    they no longer have defined values and the meaning of
+                    the code has been changed.  */
+                 && (0
 #ifdef WORD_REGISTER_OPERATIONS
-                 || ((mode_width
-                      > (GET_MODE_BITSIZE
-                          (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-                     && mode_width <= BITS_PER_WORD)
+                     || (mode_width > GET_MODE_BITSIZE (tmode)
+                         && mode_width <= BITS_PER_WORD)
 #endif
-                 || ((mode_width
-                      <= (GET_MODE_BITSIZE
-                          (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-                     && subreg_lowpart_p (XEXP (op0, 0))))
-             && GET_CODE (XEXP (op0, 1)) == CONST_INT
-             && mode_width <= HOST_BITS_PER_WIDE_INT
-             && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-                 <= HOST_BITS_PER_WIDE_INT)
-             && (INTVAL (XEXP (op0, 1)) & ~mask) == 0
-             && 0 == (~GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-                      & INTVAL (XEXP (op0, 1)))
-             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
-             && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
-                 != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-
-           {
-             op0
-               = gen_lowpart_for_combine
-                 (mode,
-                  gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))),
-                              SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1)));
-             continue;
+                     || (mode_width <= GET_MODE_BITSIZE (tmode)
+                         && subreg_lowpart_p (XEXP (op0, 0))))
+                 && GET_CODE (XEXP (op0, 1)) == CONST_INT
+                 && mode_width <= HOST_BITS_PER_WIDE_INT
+                 && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
+                 && ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0
+                 && (c1 & ~GET_MODE_MASK (tmode)) == 0
+                 && c1 != mask
+                 && c1 != GET_MODE_MASK (tmode))
+               {
+                 op0 = gen_binary (AND, tmode,
+                                   SUBREG_REG (XEXP (op0, 0)),
+                                   gen_int_mode (c1, tmode));
+                 op0 = gen_lowpart_for_combine (mode, op0);
+                 continue;
+               }
            }
 
          /* Convert (ne (and (lshiftrt (not X)) 1) 0) to
@@ -11585,7 +11564,7 @@ update_table_tick (x)
                break;
              }
          }
-         
+
        update_table_tick (XEXP (x, i));
       }
 }