* reload1.c (maybe_fix_stack_asms): New static function.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Oct 1998 01:21:06 +0000 (01:21 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Oct 1998 01:21:06 +0000 (01:21 +0000)
(reload): Call it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23075 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/reload1.c

index 2168f56..9351a57 100644 (file)
@@ -1,5 +1,8 @@
 Tue Oct 13 22:12:11 1998  Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
 
+       * reload1.c (maybe_fix_stack_asms): New static function.
+       (reload): Call it.
+
        * reload.h (compute_use_by_pseudos): Declare.
 
        * reload1.c (spilled_pseudos, insns_need_reload): New variables.
index a9925cb..34f4954 100644 (file)
@@ -357,6 +357,7 @@ static int num_labels;
 struct hard_reg_n_uses { int regno; int uses; };
 \f
 static void dump_needs                 PROTO((FILE *));
+static void maybe_fix_stack_asms       PROTO((void));
 static int calculate_needs_all_insns   PROTO((int));
 static int calculate_needs             PROTO((struct insn_chain *, rtx, int));
 static int find_reload_regs            PROTO((int, FILE *));
@@ -868,6 +869,8 @@ reload (first, global, dumpfile)
 
   order_regs_for_reload ();
 
+  maybe_fix_stack_asms ();
+
   /* So far, no hard regs have been spilled.  */
   n_spills = 0;
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -1280,6 +1283,119 @@ reload (first, global, dumpfile)
   return failure;
 }
 
+/* Yet another special case.  Unfortunately, reg-stack forces people to
+   write incorrect clobbers in asm statements.  These clobbers must not
+   cause the register to appear in bad_spill_regs, otherwise we'll call
+   fatal_insn later.  We clear the corresponding regnos in the live
+   register sets to avoid this.
+   The whole thing is rather sick, I'm afraid.  */
+static void
+maybe_fix_stack_asms ()
+{
+#ifdef STACK_REGS
+  char *constraints[MAX_RECOG_OPERANDS];
+  enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+  struct insn_chain *chain;
+
+  for (chain = reload_insn_chain; chain != 0; chain = chain->next)
+    {
+      int i, noperands;
+      HARD_REG_SET clobbered, allowed;
+      rtx pat;
+
+      if (GET_RTX_CLASS (GET_CODE (chain->insn)) != 'i'
+         || (noperands = asm_noperands (PATTERN (chain->insn))) < 0)
+       continue;
+      pat = PATTERN (chain->insn);
+      if (GET_CODE (pat) != PARALLEL)
+       continue;
+
+      CLEAR_HARD_REG_SET (clobbered);
+      CLEAR_HARD_REG_SET (allowed);
+
+      /* First, make a mask of all stack regs that are clobbered.  */
+      for (i = 0; i < XVECLEN (pat, 0); i++)
+       {
+         rtx t = XVECEXP (pat, 0, i);
+         if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
+           SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+       }
+
+      /* Get the operand values and constraints out of the insn.  */
+      decode_asm_operands (pat, recog_operand, recog_operand_loc,
+                          constraints, operand_mode);
+
+      /* For every operand, see what registers are allowed.  */
+      for (i = 0; i < noperands; i++)
+       {
+         char *p = constraints[i];
+         /* For every alternative, we compute the class of registers allowed
+            for reloading in CLS, and merge its contents into the reg set
+            ALLOWED.  */
+         int cls = (int) NO_REGS;
+
+         for (;;)
+           {
+             char c = *p++;
+
+             if (c == '\0' || c == ',' || c == '#')
+               {
+                 /* End of one alternative - mark the regs in the current
+                    class, and reset the class.  */
+                 IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
+                 cls = NO_REGS;
+                 if (c == '#')
+                   do {
+                     c = *p++;
+                   } while (c != '\0' && c != ',');
+                 if (c == '\0')
+                   break;
+                 continue;
+               }
+
+             switch (c)
+               {
+               case '=': case '+': case '*': case '%': case '?': case '!':
+               case '0': case '1': case '2': case '3': case '4': case 'm':
+               case '<': case '>': case 'V': case 'o': case '&': case 'E':
+               case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
+               case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
+               case 'P':
+#ifdef EXTRA_CONSTRAINT
+               case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+                 break;
+
+               case 'p':
+                 cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
+                 break;
+
+               case 'g':
+               case 'r':
+                 cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
+                 break;
+
+               default:
+                 cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
+               
+               }
+           }
+       }
+      /* Those of the registers which are clobbered, but allowed by the
+        constraints, must be usable as reload registers.  So clear them
+        out of the life information.  */
+      AND_HARD_REG_SET (allowed, clobbered);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (TEST_HARD_REG_BIT (allowed, i))
+         {
+           CLEAR_REGNO_REG_SET (chain->live_before, i);
+           CLEAR_REGNO_REG_SET (chain->live_after, i);
+         }
+    }
+
+#endif
+}
+
 /* Walk the insns of the current function, starting with FIRST, and collect
    information about the need to do register elimination and the need to
    perform reloads.  */