OSDN Git Service

(OBJC_ERR_BAD_STATE): New error code.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index 1e5d265..0689d60 100644 (file)
@@ -123,6 +123,13 @@ Boston, MA 02111-1307, USA.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
+/* The contents of the current function definition are allocated
+   in this obstack, and all are freed at the end of the function.
+   For top-level functions, this is temporary_obstack.
+   Separate obstacks are made for nested functions.  */
+
+extern struct obstack *function_obstack;
+
 /* List of labels that must never be deleted.  */
 extern rtx forced_labels;
 
@@ -164,56 +171,9 @@ int max_scratch;
 
 static int num_scratch;
 
-/* Indexed by n, gives number of basic block that  (REG n) is used in.
-   If the value is REG_BLOCK_GLOBAL (-2),
-   it means (REG n) is used in more than one basic block.
-   REG_BLOCK_UNKNOWN (-1) means it hasn't been seen yet so we don't know.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.  */
-
-int *reg_basic_block;
-
-/* Indexed by n, gives number of times (REG n) is used or set, each
-   weighted by its loop-depth.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.  */
-
-int *reg_n_refs;
-
-/* Indexed by N; says whether a pseudo register N was ever used
-   within a SUBREG that changes the size of the reg.  Some machines prohibit
-   such objects to be in certain (usually floating-point) registers.  */
-
-char *reg_changes_size;
-
-/* Indexed by N, gives number of places register N dies.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.  */
-
-short *reg_n_deaths;
-
-/* Indexed by N, gives 1 if that reg is live across any CALL_INSNs.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.  */
+/* Indexed by n, giving various register information */
 
-int *reg_n_calls_crossed;
-
-/* Total number of instructions at which (REG n) is live.
-   The larger this is, the less priority (REG n) gets for
-   allocation in a real register.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.
-
-   local-alloc.c may alter this number to change the priority.
-
-   Negative values are special.
-   -1 is used to mark a pseudo reg which has a constant or memory equivalent
-   and is used infrequently enough that it should not get a hard register.
-   -2 is used to mark a pseudo reg for a parameter, when a frame pointer
-   is not required.  global.c makes an allocno for this but does
-   not try to assign a hard register to it.  */
-
-int *reg_live_length;
+reg_info *reg_n_info;
 
 /* Element N is the next insn that uses (hard or pseudo) register number N
    within the current basic block; or zero, if there is no such insn.
@@ -293,7 +253,7 @@ 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));
-static void init_regset_vector         PROTO((regset *, regset, int, int));
+static void init_regset_vector         PROTO((regset *, int, int, struct obstack *));
 static void propagate_block            PROTO((regset, rtx, rtx, int, 
                                               regset, int));
 static rtx flow_delete_insn            PROTO((rtx));
@@ -416,6 +376,7 @@ find_basic_blocks (f, nonlocal_label_list)
   /* List of label_refs to all labels whose addresses are taken
      and used as data.  */
   rtx label_value_list;
+  int label_value_list_marked_live;
   rtx x, note;
   enum rtx_code prev_code, code;
   int depth, pass;
@@ -424,6 +385,7 @@ find_basic_blocks (f, nonlocal_label_list)
  restart:
 
   label_value_list = 0;
+  label_value_list_marked_live = 0;
   block_live_static = block_live;
   bzero (block_live, n_basic_blocks);
   bzero (block_marked, n_basic_blocks);
@@ -500,13 +462,6 @@ find_basic_blocks (f, nonlocal_label_list)
     abort ();
   n_basic_blocks = i + 1;
 
-  /* Don't delete the labels (in this function)
-     that are referenced by non-jump instructions.  */
-
-  for (x = label_value_list; x; x = XEXP (x, 1))
-    if (! LABEL_REF_NONLOCAL_P (x))
-      block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
-
   for (x = forced_labels; x; x = XEXP (x, 1))
     if (! LABEL_REF_NONLOCAL_P (x))
       block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
@@ -573,6 +528,21 @@ find_basic_blocks (f, nonlocal_label_list)
                    
            if (computed_jump)
              {
+               if (label_value_list_marked_live == 0)
+                 {
+                   label_value_list_marked_live = 1;
+
+                   /* This could be made smarter by only considering
+                      these live, if the computed goto is live.  */
+
+                   /* Don't delete the labels (in this function) that
+                      are referenced by non-jump instructions.  */
+
+                   for (x = label_value_list; x; x = XEXP (x, 1))
+                     if (! LABEL_REF_NONLOCAL_P (x))
+                       block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
+                 }
+
                for (x = label_value_list; x; x = XEXP (x, 1))
                  mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
                                  insn, 0);
@@ -605,6 +575,13 @@ find_basic_blocks (f, nonlocal_label_list)
               gotos.  */
          }
 
+      /* All blocks associated with labels in label_value_list are
+        trivially considered as marked live, if the list is empty.
+        We do this to speed up the below code.  */
+
+      if (label_value_list == 0)
+       label_value_list_marked_live = 1;
+
       /* Pass over all blocks, marking each block that is reachable
         and has not yet been marked.
         Keep doing this until, in one pass, no blocks have been marked.
@@ -624,6 +601,28 @@ find_basic_blocks (f, nonlocal_label_list)
                insn = basic_block_end[i];
                if (GET_CODE (insn) == JUMP_INSN)
                  mark_label_ref (PATTERN (insn), insn, 0);
+
+               if (label_value_list_marked_live == 0)
+                 /* Now that we know that this block is live, mark as
+                    live, all the blocks that we might be able to get
+                    to as live.  */
+
+                 for (insn = basic_block_head[i];
+                      insn != NEXT_INSN (basic_block_end[i]);
+                      insn = NEXT_INSN (insn))
+                   {
+                     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+                       {
+                         for (note = REG_NOTES (insn);
+                              note;
+                              note = XEXP (note, 1))
+                           if (REG_NOTE_KIND (note) == REG_LABEL)
+                             {
+                               x = XEXP (note, 0);
+                               block_live[BLOCK_NUM (x)] = 1;
+                             }
+                       }
+                   }
              }
        }
 
@@ -907,7 +906,6 @@ life_analysis (f, nregs)
      rtx f;
      int nregs;
 {
-  register regset tem;
   int first_pass;
   int changed;
   /* For each basic block, a bitmask of regs
@@ -953,24 +951,18 @@ life_analysis (f, nregs)
      if there isn't enough space.
      Don't use oballoc since we may need to allocate other things during
      this function on the temporary obstack.  */
-  tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
-  bzero ((char *) tem, n_basic_blocks * regset_bytes);
-  init_regset_vector (basic_block_live_at_end, tem,
-                     n_basic_blocks, regset_bytes);
+  init_regset_vector (basic_block_live_at_end, n_basic_blocks, regset_bytes,
+                     &flow_obstack);
 
   basic_block_new_live_at_end
     = (regset *) alloca (n_basic_blocks * sizeof (regset));
-  tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
-  bzero ((char *) tem, n_basic_blocks * regset_bytes);
-  init_regset_vector (basic_block_new_live_at_end, tem,
-                     n_basic_blocks, regset_bytes);
+  init_regset_vector (basic_block_new_live_at_end, n_basic_blocks, regset_bytes,
+                     &flow_obstack);
 
   basic_block_significant
     = (regset *) alloca (n_basic_blocks * sizeof (regset));
-  tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
-  bzero ((char *) tem, n_basic_blocks * regset_bytes);
-  init_regset_vector (basic_block_significant, tem,
-                     n_basic_blocks, regset_bytes);
+  init_regset_vector (basic_block_significant, n_basic_blocks, regset_bytes,
+                     &flow_obstack);
 
   /* Record which insns refer to any volatile memory
      or for any reason can't be deleted just because they are dead stores.
@@ -1071,12 +1063,10 @@ life_analysis (f, nregs)
       {
        /* If exiting needs the right stack value,
           consider the stack pointer live at the end of the function.  */
-       basic_block_live_at_end[n_basic_blocks - 1]
-         [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
-           |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
-       basic_block_new_live_at_end[n_basic_blocks - 1]
-         [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
-           |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+       SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+                          STACK_POINTER_REGNUM);
+       SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+                          STACK_POINTER_REGNUM);
       }
 
   /* Mark the frame pointer is needed at the end of the function.  If
@@ -1085,22 +1075,16 @@ life_analysis (f, nregs)
 
   if (n_basic_blocks > 0)
     {
-      basic_block_live_at_end[n_basic_blocks - 1]
-       [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
-         |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
-      basic_block_new_live_at_end[n_basic_blocks - 1]
-       [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
-         |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
+      SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+                        FRAME_POINTER_REGNUM);
+      SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+                        FRAME_POINTER_REGNUM);
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
       /* If they are different, also mark the hard frame pointer as live */
-      basic_block_live_at_end[n_basic_blocks - 1]
-       [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
-         |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
-                                    % REGSET_ELT_BITS);
-      basic_block_new_live_at_end[n_basic_blocks - 1]
-       [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
-         |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
-                                    % REGSET_ELT_BITS);
+      SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+                        HARD_FRAME_POINTER_REGNUM);
+      SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+                        HARD_FRAME_POINTER_REGNUM);
 #endif      
       }
 
@@ -1116,12 +1100,8 @@ life_analysis (f, nregs)
 #endif
          )
        {
-         basic_block_live_at_end[n_basic_blocks - 1]
-           [i / REGSET_ELT_BITS]
-             |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
-         basic_block_new_live_at_end[n_basic_blocks - 1]
-           [i / REGSET_ELT_BITS]
-             |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+         SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1], i);
+         SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1], i);
        }
 
   /* Propagate life info through the basic blocks
@@ -1156,21 +1136,18 @@ life_analysis (f, nregs)
                 reg that is live at the end now but was not live there before
                 is one of the significant regs of this basic block).  */
 
-             for (j = 0; j < regset_size; j++)
-               {
-                 register REGSET_ELT_TYPE x
-                   = (basic_block_new_live_at_end[i][j]
-                      & ~basic_block_live_at_end[i][j]);
-                 if (x)
-                   consider = 1;
-                 if (x & basic_block_significant[i][j])
-                   {
-                     must_rescan = 1;
-                     consider = 1;
-                     break;
-                   }
-               }
-
+             EXECUTE_IF_AND_COMPL_IN_REG_SET (basic_block_new_live_at_end[i],
+                                              basic_block_live_at_end[i],
+                                              0, j,
+                                              {
+                                                consider = 1;
+                                                if (REGNO_REG_SET_P (basic_block_significant[i], j))
+                                                  {
+                                                    must_rescan = 1;
+                                                    goto done;
+                                                  }
+                                              });
+           done:
              if (! consider)
                continue;
            }
@@ -1184,23 +1161,22 @@ life_analysis (f, nregs)
              /* No complete rescan needed;
                 just record those variables newly known live at end
                 as live at start as well.  */
-             for (j = 0; j < regset_size; j++)
-               {
-                 register REGSET_ELT_TYPE x
-                   = (basic_block_new_live_at_end[i][j]
-                      & ~basic_block_live_at_end[i][j]);
-                 basic_block_live_at_start[i][j] |= x;
-                 basic_block_live_at_end[i][j] |= x;
-               }
+             IOR_AND_COMPL_REG_SET (basic_block_live_at_start[i],
+                                    basic_block_new_live_at_end[i],
+                                    basic_block_live_at_end[i]);
+
+             IOR_AND_COMPL_REG_SET (basic_block_live_at_end[i],
+                                    basic_block_new_live_at_end[i],
+                                    basic_block_live_at_end[i]);
            }
          else
            {
              /* Update the basic_block_live_at_start
                 by propagation backwards through the block.  */
-             bcopy ((char *) basic_block_new_live_at_end[i],
-                    (char *) basic_block_live_at_end[i], regset_bytes);
-             bcopy ((char *) basic_block_live_at_end[i],
-                    (char *) basic_block_live_at_start[i], regset_bytes);
+             COPY_REG_SET (basic_block_live_at_end[i],
+                           basic_block_new_live_at_end[i]);
+             COPY_REG_SET (basic_block_live_at_start[i],
+                           basic_block_live_at_end[i]);
              propagate_block (basic_block_live_at_start[i],
                               basic_block_head[i], basic_block_end[i], 0,
                               first_pass ? basic_block_significant[i]
@@ -1215,12 +1191,8 @@ life_analysis (f, nregs)
               that falls through into this one (if any).  */
            head = basic_block_head[i];
            if (basic_block_drops_in[i])
-             {
-               register int j;
-               for (j = 0; j < regset_size; j++)
-                 basic_block_new_live_at_end[i-1][j]
-                   |= basic_block_live_at_start[i][j];
-             }
+             IOR_REG_SET (basic_block_new_live_at_end[i-1],
+                          basic_block_live_at_start[i]);
 
            /* Update the basic_block_new_live_at_end's of
               all the blocks that jump to this one.  */
@@ -1230,10 +1202,8 @@ life_analysis (f, nregs)
                   jump = LABEL_NEXTREF (jump))
                {
                  register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
-                 register int j;
-                 for (j = 0; j < regset_size; j++)
-                   basic_block_new_live_at_end[from_block][j]
-                     |= basic_block_live_at_start[i][j];
+                 IOR_REG_SET (basic_block_new_live_at_end[from_block],
+                              basic_block_live_at_start[i]);
                }
          }
 #ifdef USE_C_ALLOCA
@@ -1249,10 +1219,11 @@ life_analysis (f, nregs)
      one basic block.  */
 
   if (n_basic_blocks > 0)
-    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-      if (basic_block_live_at_start[0][i / REGSET_ELT_BITS]
-         & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
-       reg_basic_block[i] = REG_BLOCK_GLOBAL;
+    EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[0],
+                              FIRST_PSEUDO_REGISTER, i,
+                              {
+                                REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+                              });
 
   /* Now the life information is accurate.
      Make one more pass over each basic block
@@ -1283,14 +1254,16 @@ life_analysis (f, nregs)
      But we don't need to do this for the user's variables, since
      ANSI says only volatile variables need this.  */
 #ifdef LONGJMP_RESTORE_FROM_STACK
-  for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
-    if (regs_live_at_setjmp[i / REGSET_ELT_BITS]
-       & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))
-       && regno_reg_rtx[i] != 0 && ! REG_USERVAR_P (regno_reg_rtx[i]))
-      {
-       reg_live_length[i] = -1;
-       reg_basic_block[i] = -1;
-      }
+  EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+                            FIRST_PSEUDO_REGISTER, i,
+                            {
+                              if (regno_reg_rtx[i] != 0
+                                  && ! REG_USERVAR_P (regno_reg_rtx[i]))
+                                {
+                                  REG_LIVE_LENGTH (i) = -1;
+                                  REG_BASIC_BLOCK (i) = -1;
+                                }
+                            });
 #endif
 #endif
 
@@ -1303,14 +1276,15 @@ life_analysis (f, nregs)
      If the pseudo goes in a hard reg, some other value may occupy
      that hard reg where this pseudo is dead, thus clobbering the pseudo.
      Conclusion: such a pseudo must not go in a hard reg.  */
-  for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
-    if ((regs_live_at_setjmp[i / REGSET_ELT_BITS]
-        & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
-       && regno_reg_rtx[i] != 0)
-      {
-       reg_live_length[i] = -1;
-       reg_basic_block[i] = -1;
-      }
+  EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+                            FIRST_PSEUDO_REGISTER, i,
+                            {
+                              if (regno_reg_rtx[i] != 0)
+                                {
+                                  REG_LIVE_LENGTH (i) = -1;
+                                  REG_BASIC_BLOCK (i) = -1;
+                                }
+                            });
 
   obstack_free (&flow_obstack, NULL_PTR);
 }
@@ -1324,42 +1298,26 @@ void
 allocate_for_life_analysis ()
 {
   register int i;
-  register regset tem;
 
   regset_size = ((max_regno + REGSET_ELT_BITS - 1) / REGSET_ELT_BITS);
   regset_bytes = regset_size * sizeof (*(regset) 0);
 
-  reg_n_refs = (int *) oballoc (max_regno * sizeof (int));
-  bzero ((char *) reg_n_refs, max_regno * sizeof (int));
-
-  reg_n_sets = (short *) oballoc (max_regno * sizeof (short));
-  bzero ((char *) reg_n_sets, max_regno * sizeof (short));
-
-  reg_n_deaths = (short *) oballoc (max_regno * sizeof (short));
-  bzero ((char *) reg_n_deaths, max_regno * sizeof (short));
+  /* Because both reg_scan and flow_analysis want to set up the REG_N_SETS
+     information, explicitly reset it here.  The allocation should have
+     already happened on the previous reg_scan pass.  Make sure in case
+     some more registers were allocated.  */
+  allocate_reg_info (max_regno, FALSE, FALSE);
 
-  reg_changes_size = (char *) oballoc (max_regno * sizeof (char));
-  bzero (reg_changes_size, max_regno * sizeof (char));;
-
-  reg_live_length = (int *) oballoc (max_regno * sizeof (int));
-  bzero ((char *) reg_live_length, max_regno * sizeof (int));
-
-  reg_n_calls_crossed = (int *) oballoc (max_regno * sizeof (int));
-  bzero ((char *) reg_n_calls_crossed, max_regno * sizeof (int));
-
-  reg_basic_block = (int *) oballoc (max_regno * sizeof (int));
   for (i = 0; i < max_regno; i++)
-    reg_basic_block[i] = REG_BLOCK_UNKNOWN;
+    REG_N_SETS (i) = 0;
 
   basic_block_live_at_start
     = (regset *) oballoc (n_basic_blocks * sizeof (regset));
-  tem = (regset) oballoc (n_basic_blocks * regset_bytes);
-  bzero ((char *) tem, n_basic_blocks * regset_bytes);
-  init_regset_vector (basic_block_live_at_start, tem,
-                     n_basic_blocks, regset_bytes);
+  init_regset_vector (basic_block_live_at_start, n_basic_blocks, regset_bytes,
+                     function_obstack);
 
-  regs_live_at_setjmp = (regset) oballoc (regset_bytes);
-  bzero ((char *) regs_live_at_setjmp, regset_bytes);
+  regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
+  CLEAR_REG_SET (regs_live_at_setjmp);
 }
 
 /* Make each element of VECTOR point at a regset,
@@ -1368,19 +1326,18 @@ allocate_for_life_analysis ()
    BYTES_PER_ELT is the number of bytes in one regset.  */
 
 static void
-init_regset_vector (vector, space, nelts, bytes_per_elt)
+init_regset_vector (vector, nelts, bytes_per_elt, alloc_obstack)
      regset *vector;
-     regset space;
      int nelts;
      int bytes_per_elt;
+     struct obstack *alloc_obstack;
 {
   register int i;
-  register regset p = space;
 
   for (i = 0; i < nelts; i++)
     {
-      vector[i] = p;
-      p += bytes_per_elt / sizeof (*p);
+      vector[i] = OBSTACK_ALLOC_REG_SET (alloc_obstack);
+      CLEAR_REG_SET (vector[i]);
     }
 }
 
@@ -1420,11 +1377,8 @@ propagate_block (old, first, last, final, significant, bnum)
   /* The following variables are used only if FINAL is nonzero.  */
   /* This vector gets one element for each reg that has been live
      at any point in the basic block that has been scanned so far.
-     SOMETIMES_MAX says how many elements are in use so far.
-     In each element, OFFSET is the byte-number within a regset
-     for the register described by the element, and BIT is a mask
-     for that register's bit within the byte.  */
-  register struct sometimes { short offset; short bit; } *regs_sometimes_live;
+     SOMETIMES_MAX says how many elements are in use so far.  */
+  register int *regs_sometimes_live;
   int sometimes_max = 0;
   /* This regset has 1 for each reg that we have seen live so far.
      It and REGS_SOMETIMES_LIVE are updated together.  */
@@ -1435,8 +1389,8 @@ propagate_block (old, first, last, final, significant, bnum)
      current basic block, and adjust as we pass ends and starts of loops.  */
   loop_depth = basic_block_loop_depth[bnum];
 
-  dead = (regset) alloca (regset_bytes);
-  live = (regset) alloca (regset_bytes);
+  dead = ALLOCA_REG_SET ();
+  live = ALLOCA_REG_SET ();
 
   cc0_live = 0;
   last_mem_set = 0;
@@ -1456,32 +1410,22 @@ propagate_block (old, first, last, final, significant, bnum)
 
   if (final)
     {
-      register int i, offset;
-      REGSET_ELT_TYPE bit;
+      register int i;
 
       num_scratch = 0;
-      maxlive = (regset) alloca (regset_bytes);
-      bcopy ((char *) old, (char *) maxlive, regset_bytes);
-      regs_sometimes_live
-       = (struct sometimes *) alloca (max_regno * sizeof (struct sometimes));
+      maxlive = ALLOCA_REG_SET ();
+      COPY_REG_SET (maxlive, old);
+      regs_sometimes_live = (int *) alloca (max_regno * sizeof (int));
 
       /* Process the regs live at the end of the block.
         Enter them in MAXLIVE and REGS_SOMETIMES_LIVE.
-        Also mark them as not local to any one basic block.  */
-
-      for (offset = 0, i = 0; offset < regset_size; offset++)
-       for (bit = 1; bit; bit <<= 1, i++)
-         {
-           if (i == max_regno)
-             break;
-           if (old[offset] & bit)
-             {
-               reg_basic_block[i] = REG_BLOCK_GLOBAL;
-               regs_sometimes_live[sometimes_max].offset = offset;
-               regs_sometimes_live[sometimes_max].bit = i % REGSET_ELT_BITS;
-               sometimes_max++;
-             }
-         }
+        Also mark them as not local to any one basic block. */
+      EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
+                                {
+                                  REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+                                  regs_sometimes_live[sometimes_max] = i;
+                                  sometimes_max++;
+                                });
     }
 
   /* Scan the block an insn at a time from end to beginning.  */
@@ -1508,11 +1452,7 @@ propagate_block (old, first, last, final, significant, bnum)
             warn if any non-volatile datum is live.  */
 
          if (final && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
-           {
-             int i;
-             for (i = 0; i < regset_size; i++)
-               regs_live_at_setjmp[i] |= old[i];
-           }
+           IOR_REG_SET (regs_live_at_setjmp, old);
        }
 
       /* Update the life-status of regs for this insn.
@@ -1568,11 +1508,8 @@ propagate_block (old, first, last, final, significant, bnum)
              goto flushed;
            }
 
-         for (i = 0; i < regset_size; i++)
-           {
-             dead[i] = 0;      /* Faster than bzero here */
-             live[i] = 0;      /* since regset_size is usually small */
-           }
+         CLEAR_REG_SET (dead);
+         CLEAR_REG_SET (live);
 
          /* See if this is an increment or decrement that can be
             merged into a following memory address.  */
@@ -1662,13 +1599,10 @@ propagate_block (old, first, last, final, significant, bnum)
                  for (i = 0; i < FIRST_PSEUDO_REGISTER; 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));
+                     SET_REGNO_REG_SET (dead, i);
 
                  /* The stack ptr is used (honorarily) by a CALL insn.  */
-                 live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
-                   |= ((REGSET_ELT_TYPE) 1
-                       << (STACK_POINTER_REGNUM % REGSET_ELT_BITS));
+                 SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
 
                  /* Calls may also reference any of the global registers,
                     so they are made live.  */
@@ -1683,11 +1617,8 @@ propagate_block (old, first, last, final, significant, bnum)
                }
 
              /* Update OLD for the registers used or set.  */
-             for (i = 0; i < regset_size; i++)
-               {
-                 old[i] &= ~dead[i];
-                 old[i] |= live[i];
-               }
+             AND_COMPL_REG_SET (old, dead);
+             IOR_REG_SET (old, live);
 
              if (GET_CODE (insn) == CALL_INSN && final)
                {
@@ -1695,11 +1626,11 @@ propagate_block (old, first, last, final, significant, bnum)
                     must not go in a register clobbered by calls.
                     Find all regs now live and record this for them.  */
 
-                 register struct sometimes *p = regs_sometimes_live;
+                 register int *p = regs_sometimes_live;
 
                  for (i = 0; i < sometimes_max; i++, p++)
-                   if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
-                     reg_n_calls_crossed[p->offset * REGSET_ELT_BITS + p->bit]+= 1;
+                   if (REGNO_REG_SET_P (old, *p))
+                     REG_N_CALLS_CROSSED (*p)++;
                }
            }
 
@@ -1709,33 +1640,22 @@ propagate_block (old, first, last, final, significant, bnum)
 
          if (final)
            {
-             for (i = 0; i < regset_size; i++)
-               {
-                 register REGSET_ELT_TYPE diff = live[i] & ~maxlive[i];
+             register int regno;
+             register int *p;
 
-                 if (diff)
-                   {
-                     register int regno;
-                     maxlive[i] |= diff;
-                     for (regno = 0; diff && regno < REGSET_ELT_BITS; regno++)
-                       if (diff & ((REGSET_ELT_TYPE) 1 << regno))
-                         {
-                           regs_sometimes_live[sometimes_max].offset = i;
-                           regs_sometimes_live[sometimes_max].bit = regno;
-                           diff &= ~ ((REGSET_ELT_TYPE) 1 << regno);
-                           sometimes_max++;
-                         }
-                   }
-               }
+             EXECUTE_IF_AND_COMPL_IN_REG_SET (live, maxlive, 0, regno,
+                                              {
+                                                regs_sometimes_live[sometimes_max++] = regno;
+                                                SET_REGNO_REG_SET (maxlive, regno);
+                                              });
 
-             {
-               register struct sometimes *p = regs_sometimes_live;
-               for (i = 0; i < sometimes_max; i++, p++)
-                 {
-                   if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
-                     reg_live_length[p->offset * REGSET_ELT_BITS + p->bit]++;
-                 }
-             }
+             p = regs_sometimes_live;
+             for (i = 0; i < sometimes_max; i++)
+               {
+                 regno = *p++;
+                 if (REGNO_REG_SET_P (old, regno))
+                   REG_LIVE_LENGTH (regno)++;
+               }
            }
        }
     flushed: ;
@@ -1788,9 +1708,6 @@ insn_dead_p (x, needed, call_ok)
       if (GET_CODE (r) == REG)
        {
          register int regno = REGNO (r);
-         register int offset = regno / REGSET_ELT_BITS;
-         register REGSET_ELT_TYPE bit
-           = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
 
          /* Don't delete insns to set global regs.  */
          if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
@@ -1805,7 +1722,7 @@ insn_dead_p (x, needed, call_ok)
                 it, so we can treat it normally).  */
              || (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
 #endif
-             || (needed[offset] & bit) != 0)
+             || REGNO_REG_SET_P (needed, regno))
            return 0;
 
          /* If this is a hard register, verify that subsequent words are
@@ -1815,9 +1732,7 @@ insn_dead_p (x, needed, call_ok)
              int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
 
              while (--n > 0)
-               if ((needed[(regno + n) / REGSET_ELT_BITS]
-                    & ((REGSET_ELT_TYPE) 1
-                       << ((regno + n) % REGSET_ELT_BITS))) != 0)
+               if (REGNO_REG_SET_P (needed, regno+n))
                  return 0;
            }
 
@@ -1926,8 +1841,7 @@ regno_uninitialized (regno)
          && (global_regs[regno] || FUNCTION_ARG_REGNO_P (regno))))
     return 0;
 
-  return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
-         & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)));
+  return REGNO_REG_SET_P (basic_block_live_at_start[0], regno);
 }
 
 /* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -1941,11 +1855,9 @@ regno_clobbered_at_setjmp (regno)
   if (n_basic_blocks == 0)
     return 0;
 
-  return ((reg_n_sets[regno] > 1
-          || (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
-              & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))))
-         && (regs_live_at_setjmp[regno / REGSET_ELT_BITS]
-             & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))));
+  return ((REG_N_SETS (regno) > 1
+          || REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+         && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
 }
 \f
 /* Process the registers that are set within X.
@@ -2038,18 +1950,15 @@ mark_set_1 (needed, dead, x, insn, significant)
       && ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
     /* && regno != STACK_POINTER_REGNUM) -- let's try without this.  */
     {
-      register int offset = regno / REGSET_ELT_BITS;
-      register REGSET_ELT_TYPE bit
-       = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
-      REGSET_ELT_TYPE some_needed = (needed[offset] & bit);
-      REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
+      int some_needed = REGNO_REG_SET_P (needed, regno);
+      int some_not_needed = ! some_needed;
 
       /* Mark it as a significant register for this basic block.  */
       if (significant)
-       significant[offset] |= bit;
+       SET_REGNO_REG_SET (significant, regno);
 
       /* Mark it as as dead before this insn.  */
-      dead[offset] |= bit;
+      SET_REGNO_REG_SET (dead, regno);
 
       /* A hard reg in a wide mode may really be multiple registers.
         If so, mark all of them just like the first.  */
@@ -2065,17 +1974,14 @@ 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);
-
+             int regno_n = regno + n;
+             int needed_regno = REGNO_REG_SET_P (needed, regno_n);
              if (significant)
-               significant[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+               SET_REGNO_REG_SET (significant, regno_n);
 
-             dead[(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);
+             SET_REGNO_REG_SET (dead, regno_n);
+             some_needed |= needed_regno;
+             some_not_needed |= ! needed_regno;
            }
        }
       /* Additional data to record if this is the final pass.  */
@@ -2098,7 +2004,7 @@ mark_set_1 (needed, dead, x, insn, significant)
                  reg_next_use[i] = 0;
 
                  regs_ever_live[i] = 1;
-                 reg_n_sets[i]++;
+                 REG_N_SETS (i)++;
                }
            }
          else
@@ -2109,22 +2015,22 @@ mark_set_1 (needed, dead, x, insn, significant)
 
              /* Keep track of which basic blocks each reg appears in.  */
 
-             if (reg_basic_block[regno] == REG_BLOCK_UNKNOWN)
-               reg_basic_block[regno] = blocknum;
-             else if (reg_basic_block[regno] != blocknum)
-               reg_basic_block[regno] = REG_BLOCK_GLOBAL;
+             if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN)
+               REG_BASIC_BLOCK (regno) = blocknum;
+             else if (REG_BASIC_BLOCK (regno) != blocknum)
+               REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
 
              /* Count (weighted) references, stores, etc.  This counts a
                 register twice if it is modified, but that is correct.  */
-             reg_n_sets[regno]++;
+             REG_N_SETS (regno)++;
 
-             reg_n_refs[regno] += loop_depth;
+             REG_N_REFS (regno) += loop_depth;
                  
              /* The insns where a reg is live are normally counted
                 elsewhere, but we want the count to include the insn
                 where the reg is set, and the normal counting mechanism
                 would not count it.  */
-             reg_live_length[regno]++;
+             REG_LIVE_LENGTH (regno)++;
            }
 
          if (! some_not_needed)
@@ -2152,7 +2058,7 @@ mark_set_1 (needed, dead, x, insn, significant)
                 Indicate this by marking the reg being set as dying here.  */
              REG_NOTES (insn)
                = gen_rtx (EXPR_LIST, REG_UNUSED, reg, REG_NOTES (insn));
-             reg_n_deaths[REGNO (reg)]++;
+             REG_N_DEATHS (REGNO (reg))++;
            }
          else
            {
@@ -2166,9 +2072,7 @@ mark_set_1 (needed, dead, x, insn, significant)
 
              for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
                   i >= 0; i--)
-               if ((needed[(regno + i) / REGSET_ELT_BITS]
-                    & ((REGSET_ELT_TYPE) 1
-                       << ((regno + i) % REGSET_ELT_BITS))) == 0)
+               if (!REGNO_REG_SET_P (needed, regno + i))
                  REG_NOTES (insn)
                    = gen_rtx (EXPR_LIST, REG_UNUSED,
                               gen_rtx (REG, reg_raw_mode[regno + i],
@@ -2331,14 +2235,13 @@ find_auto_inc (needed, x, insn)
                 it previously wasn't live here.  If we don't mark
                 it as needed, we'll put a REG_DEAD note for it
                 on this insn, which is incorrect.  */
-             needed[regno / REGSET_ELT_BITS]
-               |= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
+             SET_REGNO_REG_SET (needed, regno);
 
              /* If there are any calls between INSN and INCR, show
                 that REGNO now crosses them.  */
              for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
                if (GET_CODE (temp) == CALL_INSN)
-                 reg_n_calls_crossed[regno]++;
+                 REG_N_CALLS_CROSSED (regno)++;
            }
          else
            return;
@@ -2370,11 +2273,11 @@ find_auto_inc (needed, x, insn)
              /* Count an extra reference to the reg.  When a reg is
                 incremented, spilling it is worse, so we want to make
                 that less likely.  */
-             reg_n_refs[regno] += loop_depth;
+             REG_N_REFS (regno) += loop_depth;
 
              /* Count the increment as a setting of the register,
                 even though it isn't a SET in rtl.  */
-             reg_n_sets[regno]++;
+             REG_N_SETS (regno)++;
            }
        }
     }
@@ -2432,9 +2335,15 @@ mark_used_regs (needed, live, x, final, insn)
       return;
 
     case MEM:
-      /* Invalidate the data for the last MEM stored.  We could do this only
-        if the addresses conflict, but this doesn't seem worthwhile.  */
-      last_mem_set = 0;
+      /* CYGNUS LOCAL dje/8176 */
+      /* Invalidate the data for the last MEM stored, but only if MEM is
+        something that can be stored into.  */
+      if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+         && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+       ; /* needn't clear last_mem_set */
+      else
+       last_mem_set = 0;
+      /* END CYGNUS LOCAL */
 
 #ifdef AUTO_INC_DEC
       if (final)
@@ -2447,7 +2356,7 @@ mark_used_regs (needed, live, x, final, insn)
          && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
          && (GET_MODE_SIZE (GET_MODE (x))
              != GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
-       reg_changes_size[REGNO (SUBREG_REG (x))] = 1;
+       REG_CHANGES_SIZE (REGNO (SUBREG_REG (x))) = 1;
 
       /* While we're here, optimize this case.  */
       x = SUBREG_REG (x);
@@ -2467,13 +2376,10 @@ mark_used_regs (needed, live, x, final, insn)
 
       regno = REGNO (x);
       {
-       register int offset = regno / REGSET_ELT_BITS;
-       register REGSET_ELT_TYPE bit
-         = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
-       REGSET_ELT_TYPE some_needed = needed[offset] & bit;
-       REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
+       REGSET_ELT_TYPE some_needed = REGNO_REG_SET_P (needed, regno);
+       REGSET_ELT_TYPE some_not_needed = ! some_needed;
 
-       live[offset] |= bit;
+       SET_REGNO_REG_SET (live, regno);
 
        /* A hard reg in a wide mode may really be multiple registers.
           If so, mark all of them just like the first.  */
@@ -2515,13 +2421,12 @@ mark_used_regs (needed, live, x, final, insn)
            n = HARD_REGNO_NREGS (regno, GET_MODE (x));
            while (--n > 0)
              {
-               REGSET_ELT_TYPE n_bit
-                 = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+               int regno_n = regno + n;
+               int needed_regno = REGNO_REG_SET_P (needed, regno_n);
 
-               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);
+               SET_REGNO_REG_SET (live, regno_n);
+               some_needed |= needed_regno;
+               some_not_needed |= ! needed_regno;
              }
          }
        if (final)
@@ -2549,14 +2454,14 @@ mark_used_regs (needed, live, x, final, insn)
 
                register int blocknum = BLOCK_NUM (insn);
 
-               if (reg_basic_block[regno] == REG_BLOCK_UNKNOWN)
-                 reg_basic_block[regno] = blocknum;
-               else if (reg_basic_block[regno] != blocknum)
-                 reg_basic_block[regno] = REG_BLOCK_GLOBAL;
+               if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN)
+                 REG_BASIC_BLOCK (regno) = blocknum;
+               else if (REG_BASIC_BLOCK (regno) != blocknum)
+                 REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
 
                /* Count (weighted) number of uses of each reg.  */
 
-               reg_n_refs[regno] += loop_depth;
+               REG_N_REFS (regno) += loop_depth;
              }
 
            /* Record and count the insns in which a reg dies.
@@ -2588,7 +2493,7 @@ mark_used_regs (needed, live, x, final, insn)
                  {
                    REG_NOTES (insn)
                      = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (insn));
-                   reg_n_deaths[regno]++;
+                   REG_N_DEATHS (regno)++;
                  }
                else
                  {
@@ -2599,9 +2504,7 @@ mark_used_regs (needed, live, x, final, insn)
 
                    for (i = HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1;
                         i >= 0; i--)
-                     if ((needed[(regno + i) / REGSET_ELT_BITS]
-                          & ((REGSET_ELT_TYPE) 1
-                             << ((regno + i) % REGSET_ELT_BITS))) == 0
+                     if (!REGNO_REG_SET_P (needed, regno + i)
                          && ! dead_or_set_regno_p (insn, regno + i))
                        REG_NOTES (insn)
                          = gen_rtx (EXPR_LIST, REG_DEAD,
@@ -2649,7 +2552,7 @@ mark_used_regs (needed, live, x, final, insn)
                && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
                && (GET_MODE_SIZE (GET_MODE (testreg))
                    != GET_MODE_SIZE (GET_MODE (SUBREG_REG (testreg)))))
-             reg_changes_size[REGNO (SUBREG_REG (testreg))] = 1;
+             REG_CHANGES_SIZE (REGNO (SUBREG_REG (testreg))) = 1;
 
            /* Modifying a single register in an alternate mode
               does not use any of the old value.  But these other
@@ -2695,8 +2598,7 @@ mark_used_regs (needed, live, x, final, insn)
       if (! EXIT_IGNORE_STACK
          || (! FRAME_POINTER_REQUIRED && flag_omit_frame_pointer))
 #endif
-       live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
-         |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+       SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (global_regs[i]
@@ -2704,8 +2606,7 @@ mark_used_regs (needed, live, x, final, insn)
            || EPILOGUE_USES (i)
 #endif
            )
-         live[i / REGSET_ELT_BITS]
-           |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+         SET_REGNO_REG_SET (live, i);
       break;
     }
 
@@ -2770,8 +2671,8 @@ try_pre_increment_1 (insn)
         less likely.  */
       if (regno >= FIRST_PSEUDO_REGISTER)
        {
-         reg_n_refs[regno] += loop_depth;
-         reg_n_sets[regno]++;
+         REG_N_REFS (regno) += loop_depth;
+         REG_N_SETS (regno)++;
        }
       return 1;
     }
@@ -2944,19 +2845,19 @@ dump_flow_info (file)
   fprintf (file, "%d registers.\n", max_regno);
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    if (reg_n_refs[i])
+    if (REG_N_REFS (i))
       {
        enum reg_class class, altclass;
        fprintf (file, "\nRegister %d used %d times across %d insns",
-                i, reg_n_refs[i], reg_live_length[i]);
-       if (reg_basic_block[i] >= 0)
-         fprintf (file, " in block %d", reg_basic_block[i]);
-       if (reg_n_deaths[i] != 1)
-         fprintf (file, "; dies in %d places", reg_n_deaths[i]);
-       if (reg_n_calls_crossed[i] == 1)
+                i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
+       if (REG_BASIC_BLOCK (i) >= 0)
+         fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
+       if (REG_N_DEATHS (i) != 1)
+         fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
+       if (REG_N_CALLS_CROSSED (i) == 1)
          fprintf (file, "; crosses 1 call");
-       else if (reg_n_calls_crossed[i])
-         fprintf (file, "; crosses %d calls", reg_n_calls_crossed[i]);
+       else if (REG_N_CALLS_CROSSED (i))
+         fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
        if (PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
          fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
        class = reg_preferred_class (i);
@@ -3005,13 +2906,8 @@ dump_flow_info (file)
        }
       fprintf (file, "\nRegisters live at start:");
       for (regno = 0; regno < max_regno; regno++)
-       {
-         register int offset = regno / REGSET_ELT_BITS;
-         register REGSET_ELT_TYPE bit
-           = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
-         if (basic_block_live_at_start[i][offset] & bit)
-             fprintf (file, " %d", regno);
-       }
+       if (REGNO_REG_SET_P (basic_block_live_at_start[i], regno))
+         fprintf (file, " %d", regno);
       fprintf (file, "\n");
     }
   fprintf (file, "\n");