OSDN Git Service

* pa/pa.c (basereg_operand): Never accept a CONST_INT.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index a5aa1fb..4b30a2d 100644 (file)
@@ -1,5 +1,5 @@
 /* Data flow analysis for GNU compiler.
-   Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file contains the data flow analysis pass of the compiler.
@@ -286,7 +287,7 @@ static HARD_REG_SET elim_reg_set;
 
 /* Forward declarations */
 static void find_basic_blocks          PROTO((rtx, rtx));
-static int uses_reg_or_mem             PROTO((rtx));
+static int jmp_uses_reg_or_mem         PROTO((rtx));
 static void mark_label_ref             PROTO((rtx, rtx, int));
 static void life_analysis              PROTO((rtx, int));
 void allocate_for_life_analysis                PROTO((void));
@@ -552,12 +553,12 @@ find_basic_blocks (f, nonlocal_label_list)
                  for (i = len - 1; i >= 0; i--)
                    if (GET_CODE (XVECEXP (pat, 0, i)) == SET
                        && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
-                       && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
+                       && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
                      computed_jump = 1;
              }
            else if (GET_CODE (pat) == SET
                     && SET_DEST (pat) == pc_rtx
-                    && uses_reg_or_mem (SET_SRC (pat)))
+                    && jmp_uses_reg_or_mem (SET_SRC (pat)))
              computed_jump = 1;
                    
            if (computed_jump)
@@ -758,32 +759,50 @@ find_basic_blocks (f, nonlocal_label_list)
 \f
 /* Subroutines of find_basic_blocks.  */
 
-/* Return 1 if X contain a REG or MEM that is not in the constant pool.  */
+/* Return 1 if X, the SRC_SRC of  SET of (pc) contain a REG or MEM that is
+   not in the constant pool and not in the condition of an IF_THEN_ELSE.  */
 
 static int
-uses_reg_or_mem (x)
+jmp_uses_reg_or_mem (x)
      rtx x;
 {
   enum rtx_code code = GET_CODE (x);
   int i, j;
   char *fmt;
 
-  if (code == REG
-      || (code == MEM
-         && ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
-               && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))))
-    return 1;
+  switch (code)
+    {
+    case CONST:
+    case LABEL_REF:
+    case PC:
+      return 0;
+
+    case REG:
+      return 1;
+
+    case MEM:
+      return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+               && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
+
+    case IF_THEN_ELSE:
+      return (jmp_uses_reg_or_mem (XEXP (x, 1))
+             || jmp_uses_reg_or_mem (XEXP (x, 2)));
+
+    case PLUS:  case MINUS:  case MULT:
+      return (jmp_uses_reg_or_mem (XEXP (x, 0))
+             || jmp_uses_reg_or_mem (XEXP (x, 1)));
+    }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e'
-         && uses_reg_or_mem (XEXP (x, i)))
+         && jmp_uses_reg_or_mem (XEXP (x, i)))
        return 1;
 
       if (fmt[i] == 'E')
        for (j = 0; j < XVECLEN (x, i); j++)
-         if (uses_reg_or_mem (XVECEXP (x, i, j)))
+         if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
            return 1;
     }
 
@@ -1603,12 +1622,13 @@ propagate_block (old, first, last, final, significant, bnum)
                                      final, insn);
 
                  /* Each call clobbers all call-clobbered regs that are not
-                    global.  Note that the function-value reg is a
+                    global or fixed.  Note that the function-value reg is a
                     call-clobbered reg, and mark_set_regs has already had
                     a chance to handle it.  */
 
                  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   if (call_used_regs[i] && ! global_regs[i])
+                   if (call_used_regs[i] && ! global_regs[i]
+                       && ! fixed_regs[i])
                      dead[i / REGSET_ELT_BITS]
                        |= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS));
 
@@ -1861,7 +1881,7 @@ libcall_dead_p (x, needed, note, insn)
 
 /* Return 1 if register REGNO was used before it was set.
    In other words, if it is live at function entry.
-   Don't count global regster variables, though.  */
+   Don't count global register variables, though.  */
 
 int
 regno_uninitialized (regno)
@@ -1986,8 +2006,8 @@ mark_set_1 (needed, dead, x, insn, significant)
       register int offset = regno / REGSET_ELT_BITS;
       register REGSET_ELT_TYPE bit
        = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
-      REGSET_ELT_TYPE all_needed = (needed[offset] & bit);
       REGSET_ELT_TYPE some_needed = (needed[offset] & bit);
+      REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
 
       /* Mark it as a significant register for this basic block.  */
       if (significant)
@@ -2010,17 +2030,17 @@ mark_set_1 (needed, dead, x, insn, significant)
          n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
          while (--n > 0)
            {
+             REGSET_ELT_TYPE n_bit
+               = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+
              if (significant)
-               significant[(regno + n) / REGSET_ELT_BITS]
-                 |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
-             dead[(regno + n) / REGSET_ELT_BITS]
-               |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+               significant[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+
+             dead[(regno + n) / REGSET_ELT_BITS] |= n_bit;
              some_needed
-               |= (needed[(regno + n) / REGSET_ELT_BITS]
-                   & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
-             all_needed
-               &= (needed[(regno + n) / REGSET_ELT_BITS]
-                   & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+               |= (needed[(regno + n) / REGSET_ELT_BITS] & n_bit);
+             some_not_needed
+               |= ((~ needed[(regno + n) / REGSET_ELT_BITS]) & n_bit);
            }
        }
       /* Additional data to record if this is the final pass.  */
@@ -2072,7 +2092,7 @@ mark_set_1 (needed, dead, x, insn, significant)
              reg_live_length[regno]++;
            }
 
-         if (all_needed)
+         if (! some_not_needed)
            {
              /* Make a logical link from the next following insn
                 that uses this register, back to this insn.
@@ -2211,7 +2231,11 @@ find_auto_inc (needed, x, insn)
          else if (GET_CODE (q) == REG
                   /* PREV_INSN used here to check the semi-open interval
                      [insn,incr).  */
-                  && ! reg_used_between_p (q,  PREV_INSN (insn), incr))
+                  && ! reg_used_between_p (q,  PREV_INSN (insn), incr)
+                  /* We must also check for sets of q as q may be
+                     a call clobbered hard register and there may
+                     be a call between PREV_INSN (insn) and incr.  */
+                  && ! reg_set_between_p (q,  PREV_INSN (insn), incr))
            {
              /* We have *p followed sometime later by q = p+size.
                 Both p and q must be live afterward,
@@ -2411,10 +2435,11 @@ mark_used_regs (needed, live, x, final, insn)
        register int offset = regno / REGSET_ELT_BITS;
        register REGSET_ELT_TYPE bit
          = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
-       REGSET_ELT_TYPE all_needed = needed[offset] & bit;
        REGSET_ELT_TYPE some_needed = needed[offset] & bit;
+       REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
 
        live[offset] |= bit;
+
        /* A hard reg in a wide mode may really be multiple registers.
           If so, mark all of them just like the first.  */
        if (regno < FIRST_PSEUDO_REGISTER)
@@ -2455,14 +2480,13 @@ mark_used_regs (needed, live, x, final, insn)
            n = HARD_REGNO_NREGS (regno, GET_MODE (x));
            while (--n > 0)
              {
-               live[(regno + n) / REGSET_ELT_BITS]
-                 |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
-               some_needed
-                 |= (needed[(regno + n) / REGSET_ELT_BITS]
-                     & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
-               all_needed
-                 &= (needed[(regno + n) / REGSET_ELT_BITS]
-                     & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+               REGSET_ELT_TYPE n_bit
+                 = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+
+               live[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+               some_needed |= (needed[(regno + n) / REGSET_ELT_BITS] & n_bit);
+               some_not_needed
+                 |= ((~ needed[(regno + n) / REGSET_ELT_BITS]) & n_bit);
              }
          }
        if (final)
@@ -2506,7 +2530,7 @@ mark_used_regs (needed, live, x, final, insn)
               we do not make a REG_DEAD note; likewise if we already
               made such a note.  */
 
-           if (! all_needed
+           if (some_not_needed
                && ! dead_or_set_p (insn, x)
 #if 0
                && (regno >= FIRST_PSEUDO_REGISTER || ! fixed_regs[regno])