OSDN Git Service

Don't include sys/file.h for winnt; use process.h instead.
[pf3gnuchains/gcc-fork.git] / gcc / stupid.c
index b4b15fb..e10f2dc 100644 (file)
@@ -82,6 +82,11 @@ static int *reg_order;
 
 static char *regs_live;
 
+/* Indexed by reg number, nonzero if reg was used in a SUBREG that changes
+   its size.  */
+
+static char *regs_change_size;
+
 /* Indexed by insn's suid, the set of hard regs live after that insn.  */
 
 static HARD_REG_SET *after_insn_hard_regs;
@@ -93,7 +98,7 @@ static HARD_REG_SET *after_insn_hard_regs;
 
 static int stupid_reg_compare  PROTO((int *, int *));
 static int stupid_find_reg     PROTO((int, enum reg_class, enum machine_mode,
-                                      int, int));
+                                      int, int, int));
 static void stupid_mark_refs   PROTO((rtx, rtx));
 \f
 /* Stupid life analysis is for the case where only variables declared
@@ -149,13 +154,16 @@ stupid_life_analysis (f, nregs, file)
   /* Allocate tables to record info about regs.  */
 
   reg_where_dead = (int *) alloca (nregs * sizeof (int));
-  bzero (reg_where_dead, nregs * sizeof (int));
+  bzero ((char *) reg_where_dead, nregs * sizeof (int));
 
   reg_where_born = (int *) alloca (nregs * sizeof (int));
-  bzero (reg_where_born, nregs * sizeof (int));
+  bzero ((char *) reg_where_born, nregs * sizeof (int));
 
   reg_order = (int *) alloca (nregs * sizeof (int));
-  bzero (reg_order, nregs * sizeof (int));
+  bzero ((char *) reg_order, nregs * sizeof (int));
+
+  regs_change_size = (char *) alloca (nregs * sizeof (char));
+  bzero ((char *) regs_change_size, nregs * sizeof (char));
 
   reg_renumber = (short *) oballoc (nregs * sizeof (short));
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -167,7 +175,7 @@ stupid_life_analysis (f, nregs, file)
   after_insn_hard_regs
     = (HARD_REG_SET *) alloca (max_suid * sizeof (HARD_REG_SET));
 
-  bzero (after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
+  bzero ((char *) after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
 
   /* Allocate and zero out many data structures
      that will record the data from lifetime analysis.  */
@@ -199,6 +207,13 @@ stupid_life_analysis (f, nregs, file)
        if (regs_live[i])
          SET_HARD_REG_BIT (*p, i);
 
+      /* Update which hard regs are currently live
+        and also the birth and death suids of pseudo regs
+        based on the pattern of this insn.  */
+
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+       stupid_mark_refs (PATTERN (insn), insn);
+
       /* Mark all call-clobbered regs as live after each call insn
         so that a pseudo whose life span includes this insn
         will not go in one of them.
@@ -214,14 +229,12 @@ stupid_life_analysis (f, nregs, file)
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
            if (call_used_regs[i])
              regs_live[i] = 0;
-       }
-
-      /* Update which hard regs are currently live
-        and also the birth and death suids of pseudo regs
-        based on the pattern of this insn.  */
 
-      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-       stupid_mark_refs (PATTERN (insn), insn);
+         /* It is important that this be done after processing the insn's
+            pattern because we want the function result register to still
+            be live if it's also used to pass arguments.  */
+         stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
+       }
     }
 
   /* Now decide the order in which to allocate the pseudo registers.  */
@@ -249,7 +262,8 @@ stupid_life_analysis (f, nregs, file)
                                           reg_preferred_class (r),
                                           PSEUDO_REGNO_MODE (r),
                                           reg_where_born[r],
-                                          reg_where_dead[r]);
+                                          reg_where_dead[r],
+                                          regs_change_size[r]);
 
       /* If no reg available in that class, try alternate class.  */
       if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS)
@@ -257,7 +271,8 @@ stupid_life_analysis (f, nregs, file)
                                           reg_alternate_class (r),
                                           PSEUDO_REGNO_MODE (r),
                                           reg_where_born[r],
-                                          reg_where_dead[r]);
+                                          reg_where_dead[r],
+                                          regs_change_size[r]);
     }
 
   if (file)
@@ -298,14 +313,19 @@ stupid_reg_compare (r1p, r2p)
    Return -1 if such a block cannot be found.
 
    If CALL_PRESERVED is nonzero, insist on registers preserved
-   over subroutine calls, and return -1 if cannot find such.  */
+   over subroutine calls, and return -1 if cannot find such.
+
+   If CHANGES_SIZE is nonzero, it means this register was used as the
+   operand of a SUBREG that changes its size.  */
 
 static int
-stupid_find_reg (call_preserved, class, mode, born_insn, dead_insn)
+stupid_find_reg (call_preserved, class, mode,
+                born_insn, dead_insn, changes_size)
      int call_preserved;
      enum reg_class class;
      enum machine_mode mode;
      int born_insn, dead_insn;
+     int changes_size;
 {
   register int i, ins;
 #ifdef HARD_REG_SET
@@ -334,6 +354,12 @@ stupid_find_reg (call_preserved, class, mode, born_insn, dead_insn)
 
   IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
 
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+  if (changes_size)
+    IOR_HARD_REG_SET (used,
+                     reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
+#endif
+
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
 #ifdef REG_ALLOC_ORDER
@@ -385,10 +411,15 @@ static void
 stupid_mark_refs (x, insn)
      rtx x, insn;
 {
-  register RTX_CODE code = GET_CODE (x);
+  register RTX_CODE code;
   register char *fmt;
   register int regno, i;
 
+  if (x == 0)
+    return;
+
+  code = GET_CODE (x);
+
   if (code == SET || code == CLOBBER)
     {
       if (SET_DEST (x) != 0 && GET_CODE (SET_DEST (x)) == REG)
@@ -461,9 +492,18 @@ stupid_mark_refs (x, insn)
       return;
     }
 
+  else if (code == SUBREG
+          && GET_CODE (SUBREG_REG (x)) == REG
+          && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
+          && (GET_MODE_SIZE (GET_MODE (x))
+              != GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+          && (INTEGRAL_MODE_P (GET_MODE (x))
+              || INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (x)))))
+    regs_change_size[REGNO (SUBREG_REG (x))] = 1;
+
   /* Register value being used, not set.  */
 
-  if (code == REG)
+  else if (code == REG)
     {
       regno = REGNO (x);
       if (regno < FIRST_PSEUDO_REGISTER)