re PR rtl-optimization/13169 (asm using r30 or r31 confuses global_alloc)
authorAlan Modra <amodra@bigpond.net.au>
Sat, 6 Dec 2003 12:22:31 +0000 (12:22 +0000)
committerAlan Modra <amodra@gcc.gnu.org>
Sat, 6 Dec 2003 12:22:31 +0000 (22:52 +1030)
PR 13169
* basic-block.h (PROP_ASM_SCAN): Define.
* final.c (regs_asm_clobbered): New array.
* regs.h (regs_asm_clobbered): Declare.
* flow.c (life_analysis): Init it.
(mark_set_regs): Set PROP_ASM_SCAN for asms.
(mark_set_1): Set regs_asm_clobbered.
* global.c (global_alloc): Don't set eliminable_regset when
regs_asm_clobbered.

From-SVN: r74363

gcc/ChangeLog
gcc/basic-block.h
gcc/final.c
gcc/flow.c
gcc/global.c
gcc/regs.h

index 6ce8f999b230f6f8303a6fc799c4047f07cae26f..0cf45b6c3ec91662582981d603e54340a9f37d8a 100644 (file)
@@ -1,3 +1,15 @@
+2003-12-06  Alan Modra  <amodra@bigpond.net.au>
+
+       PR 13169
+       * basic-block.h (PROP_ASM_SCAN): Define.
+       * final.c (regs_asm_clobbered): New array.
+       * regs.h (regs_asm_clobbered): Declare.
+       * flow.c (life_analysis): Init it.
+       (mark_set_regs): Set PROP_ASM_SCAN for asms.
+       (mark_set_1): Set regs_asm_clobbered.
+       * global.c (global_alloc): Don't set eliminable_regset when
+       regs_asm_clobbered.
+
 2003-12-05  Mark Mitchell  <mark@codesourcery.com>
 
        * config/ia64/ia64.h (MUST_PASS_IN_STACK): Define.
index 221b2466985c43c33ba296aa9431038cf7df7597..365711a541dc6abcd4705fdf87c0149743f7a425 100644 (file)
@@ -477,6 +477,8 @@ enum update_life_extent
 #define PROP_AUTOINC           64      /* Create autoinc mem references.  */
 #define PROP_EQUAL_NOTES       128     /* Take into account REG_EQUAL notes.  */
 #define PROP_SCAN_DEAD_STORES  256     /* Scan for dead code.  */
+#define PROP_ASM_SCAN          512     /* Internal flag used within flow.c
+                                          to flag analysis of asms.  */
 #define PROP_FINAL             (PROP_DEATH_NOTES | PROP_LOG_LINKS  \
                                 | PROP_REG_INFO | PROP_KILL_DEAD_CODE  \
                                 | PROP_SCAN_DEAD_CODE | PROP_AUTOINC \
index 820cb680ab20addab1624e09c1b3b5ec75a438db..53c9359232c56bd93409b57096656abc0ef210cd 100644 (file)
@@ -170,6 +170,12 @@ CC_STATUS cc_prev_status;
 
 char regs_ever_live[FIRST_PSEUDO_REGISTER];
 
+/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm.
+   Unlike regs_ever_live, elements of this array corresponding to
+   eliminable regs like the frame pointer are set if an asm sets them.  */
+
+char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
+
 /* Nonzero means current function must be given a frame pointer.
    Initialized in function.c to 0.  Set only in reload1.c as per
    the needs of the function.  */
index d131fab5a8b38b7c089b93be05676d3b83e5bcfd..952e7d9eb9252e4470f5836ab992086f3adaa53d 100644 (file)
@@ -464,7 +464,10 @@ life_analysis (rtx f, FILE *file, int flags)
      is not immediately handy.  */
 
   if (flags & PROP_REG_INFO)
-    memset (regs_ever_live, 0, sizeof (regs_ever_live));
+    {
+      memset (regs_ever_live, 0, sizeof (regs_ever_live));
+      memset (regs_asm_clobbered, 0, sizeof (regs_asm_clobbered));
+    }
   update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
 
   /* Clean up.  */
@@ -2445,6 +2448,7 @@ mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn)
   rtx cond = NULL_RTX;
   rtx link;
   enum rtx_code code;
+  int flags = pbi->flags;
 
   if (insn)
     for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
@@ -2453,14 +2457,17 @@ mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn)
          mark_set_1 (pbi, SET, XEXP (link, 0),
                      (GET_CODE (x) == COND_EXEC
                       ? COND_EXEC_TEST (x) : NULL_RTX),
-                     insn, pbi->flags);
+                     insn, flags);
       }
  retry:
   switch (code = GET_CODE (x))
     {
     case SET:
+      if (GET_CODE (XEXP (x, 1)) == ASM_OPERANDS)
+       flags |= PROP_ASM_SCAN;
+      /* Fall thru */
     case CLOBBER:
-      mark_set_1 (pbi, code, SET_DEST (x), cond, insn, pbi->flags);
+      mark_set_1 (pbi, code, SET_DEST (x), cond, insn, flags);
       return;
 
     case COND_EXEC:
@@ -2483,13 +2490,20 @@ mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn)
 
                cond = COND_EXEC_TEST (sub);
                sub = COND_EXEC_CODE (sub);
-               if (GET_CODE (sub) != SET && GET_CODE (sub) != CLOBBER)
-                 break;
-               /* Fall through.  */
+               if (GET_CODE (sub) == SET)
+                 goto mark_set;
+               if (GET_CODE (sub) == CLOBBER)
+                 goto mark_clob;
+               break;
 
              case SET:
+             mark_set:
+               if (GET_CODE (XEXP (sub, 1)) == ASM_OPERANDS)
+                 flags |= PROP_ASM_SCAN;
+               /* Fall thru */
              case CLOBBER:
-               mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, pbi->flags);
+             mark_clob:
+               mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, flags);
                break;
 
              default:
@@ -2713,6 +2727,9 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
                {
                  for (i = regno_first; i <= regno_last; i++)
                    regs_ever_live[i] = 1;
+                 if (flags & PROP_ASM_SCAN)
+                   for (i = regno_first; i <= regno_last; i++)
+                     regs_asm_clobbered[i] = 1;
                }
              else
                {
@@ -2798,6 +2815,14 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
     {
       if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
        pbi->reg_next_use[regno_first] = 0;
+
+      if ((flags & PROP_REG_INFO) != 0
+         && (flags & PROP_ASM_SCAN) != 0
+         &&  regno_first < FIRST_PSEUDO_REGISTER)
+       {
+         for (i = regno_first; i <= regno_last; i++)
+           regs_asm_clobbered[i] = 1;
+       }
     }
 
   /* If this is the last pass and this is a SCRATCH, show it will be dying
index c808e2074067cbb45912974e99c2f169a94a4f4e..c337cd41cfc87d3280e8c05a5073667dadfae0f3 100644 (file)
@@ -343,22 +343,42 @@ global_alloc (FILE *file)
 #ifdef ELIMINABLE_REGS
   for (i = 0; i < ARRAY_SIZE (eliminables); i++)
     {
-      SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
+      bool cannot_elim
+       = (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
+          || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
 
-      if (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
-         || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp))
-       SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from);
+      if (!regs_asm_clobbered[eliminables[i].from])
+       {
+         SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
+
+         if (cannot_elim)
+           SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from);
+       }
+      else if (cannot_elim)
+       error ("%s cannot be used in asm here",
+              reg_names[eliminables[i].from]);
     }
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-  SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
-  if (need_fp)
-    SET_HARD_REG_BIT (no_global_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+  if (!regs_asm_clobbered[HARD_FRAME_POINTER_REGNUM])
+    {
+      SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
+      if (need_fp)
+       SET_HARD_REG_BIT (no_global_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+    }
+  else if (need_fp)
+    error ("%s cannot be used in asm here",
+          reg_names[HARD_FRAME_POINTER_REGNUM]);
 #endif
 
 #else
-  SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
-  if (need_fp)
-    SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM);
+  if (!regs_asm_clobbered[FRAME_POINTER_REGNUM])
+    {
+      SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
+      if (need_fp)
+       SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM);
+    }
+  else if (need_fp)
+    error ("%s cannot be used in asm here", reg_names[FRAME_POINTER_REGNUM]);
 #endif
 
   /* Track which registers have already been used.  Start with registers
index b2aeb5fb02c1970b2339975152e79dbd0f5b404e..9c9edccb26b8c7acc41c815ec643344307252b8a 100644 (file)
@@ -153,11 +153,14 @@ extern bitmap_head subregs_of_mode;
 
 extern short *reg_renumber;
 
-/* Vector indexed by hardware reg
-   saying whether that reg is ever used.  */
+/* Vector indexed by hardware reg saying whether that reg is ever used.  */
 
 extern char regs_ever_live[FIRST_PSEUDO_REGISTER];
 
+/* Like regs_ever_live, but saying whether reg is set by asm statements.  */
+
+extern char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
+
 /* For each hard register, the widest mode object that it can contain.
    This will be a MODE_INT mode if the register can hold integers.  Otherwise
    it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the