*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Wed, 15 Jan 1992 21:58:02 +0000 (16:58 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Wed, 15 Jan 1992 21:58:02 +0000 (16:58 -0500)
From-SVN: r192

gcc/machmode.h
gcc/output.h
gcc/print-rtl.c
gcc/recog.c
gcc/regclass.c
gcc/reload1.c
gcc/rtl.c
gcc/rtl.h

index 4f88de0f8597e3011710090a1ecdbfddabf58d96..67bcb355fd38d62ac72c4a668092a4d5532be083 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine mode definitions for GNU C-Compiler; included by rtl.h and tree.h.
-   Copyright (C) 1990-1991 Free Software Foundation, Inc.
+   Copyright (C) 199 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
index 27a9d5327405fa130414b966c6c30e4f258a3212..edf68ffed34c8821c2be4f214e146b131aa64c7f 100644 (file)
@@ -1,6 +1,6 @@
 /* Declarations for insn-output.c.  These functions are defined in recog.c,
    final.c, and varasm.c.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 19871991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
index 75d0c0afa4b64513248b467b9fab8befc2ce24b2..ca048d66a2eebdb86e6dd737f3d20302d5912821 100644 (file)
@@ -1,5 +1,5 @@
 /* Print RTL for GNU C Compiler.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 19871991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
index 5828f759c481ffd44d6d66d02d9b1d9c83303eb5..c347bdf19241e7e689835e9daddfa03bc3e222af 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used by or related to instruction recognition.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
index 8416a7cf6dfca56f17d6760940e0302136e2569b..76df1e486ef8b7866db72b53bcf772180c996522 100644 (file)
@@ -1,5 +1,5 @@
 /* Compute register class preferences for pseudo-registers.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -327,7 +327,7 @@ fix_register (name, fixed, call_used)
      the register info.  */
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (!strcmp (reg_names[i], name))
+    if (reg_names[i][0] && ! strcmp (reg_names[i], name))
       {
        fixed_regs[i] = fixed;
        call_used_regs[i] = call_used;
index 8af7b0caa5876c8ebbde501dda1f08b585410bb8..b4f6fa3ac756c00fb1005d3bc49a84def7b92d2a 100644 (file)
@@ -1,5 +1,5 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -266,6 +266,7 @@ static struct elim_table
   int can_eliminate_previous;  /* Value of CAN_ELIMINATE in previous scan over
                                   insns made by reload. */
   int offset;                  /* Current offset between the two regs. */
+  int max_offset;              /* Maximum offset between the two regs. */
   int previous_offset;         /* Offset at end of previous insn. */
   int ref_outside_mem;         /* "to" has been referenced outside a MEM. */
   rtx from_rtx;                        /* REG rtx for the register to be eliminated.
@@ -493,7 +494,8 @@ reload (first, global, dumpfile)
   int something_needs_reloads;
   int something_needs_elimination;
   int new_basic_block_needs;
-  int caller_save_needs_spill;
+  enum reg_class caller_save_spill_class = NO_REGS;
+  int caller_save_group_size = 1;
 
   /* The basic block number currently being processed for INSN.  */
   int this_block;
@@ -516,9 +518,9 @@ reload (first, global, dumpfile)
   bzero (spill_stack_slot, sizeof spill_stack_slot);
   bzero (spill_stack_slot_width, sizeof spill_stack_slot_width);
 
-  /* If caller-saves are requested, initialize the required save areas.  */
-  if (flag_caller_saves)
-    init_save_areas ();
+  /* Initialize the save area information for caller-save, in case some
+     are needed.  */
+  init_save_areas ();
     
   /* Compute which hard registers are now in use
      as homes for pseudo registers.
@@ -566,7 +568,12 @@ reload (first, global, dumpfile)
       if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
        {
          rtx note = find_reg_note (insn, REG_EQUIV, 0);
-         if (note)
+         if (note
+#ifdef LEGITIMATE_PIC_OPERAND_P
+             && (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic 
+                 || LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))
+#endif
+             )
            {
              rtx x = XEXP (note, 0);
              i = REGNO (SET_DEST (set));
@@ -792,7 +799,8 @@ reload (first, global, dumpfile)
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        {
          INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
-         ep->previous_offset = ep->offset = ep->initial_offset;
+         ep->previous_offset = ep->offset
+           = ep->max_offset = ep->initial_offset;
        }
 #else
 #ifdef INITIAL_FRAME_POINTER_OFFSET
@@ -802,7 +810,7 @@ reload (first, global, dumpfile)
        abort ();
       reg_eliminate[0].initial_offset = 0;
 #endif
-      reg_eliminate[0].previous_offset
+      reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset
        = reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
 #endif
 
@@ -877,6 +885,15 @@ reload (first, global, dumpfile)
       if (something_changed)
        continue;
 
+      /* If caller-saves needs a group, initialize the group to include
+        the size and mode required for caller-saves.  */
+
+      if (caller_save_group_size > 1)
+       {
+         group_mode[(int) caller_save_spill_class] = Pmode;
+         group_size[(int) caller_save_spill_class] = caller_save_group_size;
+       }
+
       /* Compute the most additional registers needed by any instruction.
         Collect information separately for each class of regs.  */
 
@@ -927,14 +944,6 @@ reload (first, global, dumpfile)
              int insn_groups_for_operands[N_REG_CLASSES];
              int insn_total_groups_for_operands = 0;
 
-             for (i = 0; i < N_REG_CLASSES; i++)
-               {
-                 insn_needs[i] = 0, insn_groups[i] = 0;
-                 insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;
-                 insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;
-                 insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;
-               }
-
 #if 0  /* This wouldn't work nowadays, since optimize_bit_field
          looks for non-strict memory addresses.  */
              /* Optimization: a bit-field instruction whose field
@@ -1014,11 +1023,25 @@ reload (first, global, dumpfile)
                  something_needs_elimination = 1;
                }
 
-             if (n_reloads == 0)
+             /* If this insn has no reloads, we need not do anything except
+                in the case of a CALL_INSN when we have caller-saves and 
+                caller-save needs reloads.  */
+
+             if (n_reloads == 0
+                 && ! (GET_CODE (insn) == CALL_INSN
+                       && caller_save_spill_class != NO_REGS))
                continue;
 
              something_needs_reloads = 1;
 
+             for (i = 0; i < N_REG_CLASSES; i++)
+               {
+                 insn_needs[i] = 0, insn_groups[i] = 0;
+                 insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;
+                 insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;
+                 insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;
+               }
+
              /* Count each reload once in every class
                 containing the reload's own class.  */
 
@@ -1145,18 +1168,59 @@ reload (first, global, dumpfile)
                  if (insn_groups_for_operands[i] > this_max)
                    this_max = insn_groups_for_operands[i];
                  insn_groups[i] += this_max;
-
-                 if (global && (insn_needs[i] || insn_groups[i])
-                     && ! basic_block_needs[i][this_block])
-                   {
-                     new_basic_block_needs = 1;
-                     basic_block_needs[i][this_block] = 1;
-                   }
                }
+
              insn_total_groups += MAX (insn_total_groups_for_inputs,
                                        MAX (insn_total_groups_for_outputs,
                                             insn_total_groups_for_operands));
 
+             /* If this is a CALL_INSN and caller-saves will need
+                a spill register, act as if the spill register is
+                needed for this insn.   However, the spill register
+                can be used by any reload of this insn, so we only
+                need do something if no need for that class has
+                been recorded. 
+
+                The assumption that every CALL_INSN will trigger a
+                caller-save is highly conservative, however, the number
+                of cases where caller-saves will need a spill register but
+                a block containing a CALL_INSN won't need a spill register
+                of that class should be quite rare.
+
+                If a group is needed, the size and mode of the group will
+                have been set up at the begining of this loop.  */
+
+             if (GET_CODE (insn) == CALL_INSN
+                 && caller_save_spill_class != NO_REGS)
+               {
+                 int *caller_save_needs
+                   = (caller_save_group_size > 1 ? insn_groups : insn_needs);
+
+                 if (caller_save_needs[(int) caller_save_spill_class] == 0)
+                   {
+                     register enum reg_class *p
+                       = reg_class_superclasses[(int) caller_save_spill_class];
+
+                     caller_save_needs[(int) caller_save_spill_class]++;
+
+                     while (*p != LIM_REG_CLASSES)
+                       caller_save_needs[*p++] += 1;
+                   }
+
+                 if (caller_save_group_size > 1)
+                   insn_total_groups = MAX (insn_total_groups, 1);
+               }
+
+             /* Update the basic block needs.  */
+
+             for (i = 0; i < N_REG_CLASSES; i++)
+               if (global && (insn_needs[i] || insn_groups[i])
+                   && ! basic_block_needs[i][this_block])
+                 {
+                   new_basic_block_needs = 1;
+                   basic_block_needs[i][this_block] = 1;
+                 }
+
 #ifdef SMALL_REGISTER_CLASSES
              /* If this insn stores the value of a function call,
                 and that value is in a register that has been spilled,
@@ -1205,20 +1269,21 @@ reload (first, global, dumpfile)
        }
 
       /* If we have caller-saves, set up the save areas and see if caller-save
-        will need a spill register.  If it will and we don't already have a
-        need of class BASE_REG_CLASS, create such a need.  */
+        will need a spill register.  */
 
       if (caller_save_needed
-         && 0 != (caller_save_needs_spill
-                  = ! setup_save_areas (&something_changed))
-         && max_needs[(int) BASE_REG_CLASS] == 0)
+         && ! setup_save_areas (&something_changed)
+         && caller_save_spill_class  == NO_REGS)
        {
-         register enum reg_class *p
-           = reg_class_superclasses[(int) BASE_REG_CLASS];
-
-         max_needs[(int) BASE_REG_CLASS] = 1;
-         while (*p != LIM_REG_CLASSES)
-           max_needs[(int) *p++] += 1;
+         /* The class we will need depends on whether the machine
+            supports the sum of two registers for an address; see
+            find_address_reloads for details.  */
+
+         caller_save_spill_class 
+           = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
+         caller_save_group_size
+           = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
+         something_changed = 1;
        }
 
       /* Now deduct from the needs for the registers already
@@ -1569,22 +1634,13 @@ reload (first, global, dumpfile)
   reload_in_progress = 1;
 
   /* Insert code to save and restore call-clobbered hard regs
-     around calls.  If caller-save needs a spill register, find one
-     for it to use.  */
+     around calls.  Tell if what mode to use so that we will process
+     those insns in reload_as_needed if we have to.  */
 
   if (caller_save_needed)
-    {
-      register int regno = -1;
-
-      if (caller_save_needs_spill)
-       for (i = 0; i < n_spills; i++)
-         if (TEST_HARD_REG_BIT (reg_class_contents[(int) BASE_REG_CLASS],
-                               spill_regs[i])
-             && HARD_REGNO_MODE_OK (spill_regs[i], Pmode))
-           regno = spill_regs[i];
-
-      save_call_clobbered_regs (regno);
-    }
+    save_call_clobbered_regs (num_eliminable ? QImode
+                             : caller_save_spill_class != NO_REGS ? HImode
+                             : VOIDmode);
 
   /* If a pseudo has no hard reg, delete the insns that made the equivalence.
      If that insn didn't set the register (i.e., it copied the register to
@@ -1611,7 +1667,9 @@ reload (first, global, dumpfile)
      by generating move instructions to move the must-be-register
      values into or out of the reload registers.  */
 
-  if (something_needs_reloads || something_needs_elimination)
+  if (something_needs_reloads || something_needs_elimination
+      || (caller_save_needed && num_eliminable)
+      || caller_save_spill_class != NO_REGS)
     reload_as_needed (first, global);
 
   reload_in_progress = 0;
@@ -2765,6 +2823,9 @@ eliminate_regs_in_insn (insn, replace)
   /* Loop through all elimination pairs.  See if any have changed and
      recalculate the number not at initial offset.
 
+     Compute the maximum offset (minimum offset if the stack does not
+     grow downward) for each elimination pair.
+
      We also detect a cases where register elimination cannot be done,
      namely, if a register would be both changed and referenced outside a MEM
      in the resulting insn since such an insn is often undefined and, even if
@@ -2788,6 +2849,12 @@ eliminate_regs_in_insn (insn, replace)
       ep->previous_offset = ep->offset;
       if (ep->can_eliminate && ep->offset != ep->initial_offset)
        num_not_at_initial_offset++;
+
+#ifdef STACK_GROWS_DOWNWARD
+      ep->max_offset = MAX (ep->max_offset, ep->offset);
+#else
+      ep->max_offset = MIN (ep->max_offset, ep->offset);
+#endif
     }
 
  done:
@@ -4362,6 +4429,7 @@ emit_reload_insns (insn)
 {
   register int j;
   rtx following_insn = NEXT_INSN (insn);
+  rtx before_insn = insn;
   rtx first_output_reload_insn = NEXT_INSN (insn);
   rtx first_other_reload_insn = insn;
   rtx first_operand_address_reload_insn = insn;
@@ -4369,6 +4437,16 @@ emit_reload_insns (insn)
   /* Values to be put in spill_reg_store are put here first.  */
   rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
 
+  /* If this is a CALL_INSN preceeded by USE insns, any reload insns
+     must go in front of the first USE insn, not in front of INSN.  */
+
+  if (GET_CODE (insn) == CALL_INSN && GET_CODE (PREV_INSN (insn)) == INSN
+      && GET_CODE (PATTERN (PREV_INSN (insn))) == USE)
+    while (GET_CODE (PREV_INSN (before_insn)) == INSN
+          && GET_CODE (PATTERN (PREV_INSN (before_insn))) == USE)
+      first_other_reload_insn = first_operand_address_reload_insn
+       = before_insn = PREV_INSN (before_insn);
+
   /* Now output the instructions to copy the data into and out of the
      reload registers.  Do these in the order that the reloads were reported,
      since reloads of base and index registers precede reloads of operands
@@ -4520,7 +4598,7 @@ emit_reload_insns (insn)
              where = first_output_reload_insn;
              break;
            case RELOAD_FOR_OPERAND_ADDRESS:
-             where = insn;
+             where = before_insn;
            }
 
          special = 0;
@@ -4761,9 +4839,9 @@ emit_reload_insns (insn)
                  first_other_reload_insn = this_reload_insn;
                break;
              case RELOAD_FOR_OPERAND_ADDRESS:
-               if (first_operand_address_reload_insn == insn)
+               if (first_operand_address_reload_insn == before_insn)
                  first_operand_address_reload_insn = this_reload_insn;
-               if (first_other_reload_insn == insn)
+               if (first_other_reload_insn == before_insn)
                  first_other_reload_insn = this_reload_insn;
              }
 
index 8b8a1372994965044d7418af4af72065a8457f74..b82e5f139688d0869f39af167840181618c7bd99 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -1,5 +1,5 @@
 /* Allocate and read RTL for GNU C Compiler.
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
index 62a7811d07a6413e5c8b1e60ed1bd62d91998d6e..814068d7e0d4e19194561f5af70a8457ad08a524 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1,5 +1,5 @@
 /* Register Transfer Language (RTL) definitions for GNU C-Compiler
-   Copyright (C) 1987-1991 Free Software Foundation, Inc.
+   Copyright (C) 19871991 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -649,22 +649,21 @@ extern rtx pc_rtx;
 extern rtx cc0_rtx;
 extern rtx const0_rtx;
 extern rtx const1_rtx;
+extern rtx const2_rtx;
 extern rtx constm1_rtx;
 extern rtx const_true_rtx;
-extern rtx fconst0_rtx;
-extern rtx fconst1_rtx;
-extern rtx fconst2_rtx;
-extern rtx dconst0_rtx;
-extern rtx dconst1_rtx;
-extern rtx dconst2_rtx;
-
-/* Returns a constant 0 rtx in mode MODE.  */
-
-#define CONST0_RTX(MODE) \
- ((MODE == SFmode) ? fconst0_rtx                       \
-  : ((MODE == DFmode) ? dconst0_rtx                    \
-     : ((GET_MODE_CLASS (MODE) == MODE_INT) ? const0_rtx       \
-        : (abort (), NULL_RTX))))
+
+extern rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
+
+/* Returns a constant 0 rtx in mode MODE.  Integer modes are treated the 
+   same as VOIDmode.  */
+
+#define CONST0_RTX(MODE) (const_tiny_rtx[0][(int) (MODE)])
+
+/* Likewise, for the constants 1 and 2.  */
+
+#define CONST1_RTX(MODE) (const_tiny_rtx[1][(int) (MODE)])
+#define CONST2_RTX(MODE) (const_tiny_rtx[2][(int) (MODE)])
 
 /* All references to certain hard regs, except those created
    by allocating pseudo regs into them (when that's possible),