OSDN Git Service

* config/i386/winnt.c (ix86_handle_dll_attribute): Set
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 1ce3199..c188aec 100644 (file)
@@ -280,9 +280,6 @@ char *reload_firstobj;
    Used to quickly free all memory after processing one insn.  */
 static char *reload_insn_firstobj;
 
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
 /* List of insn_chain instructions, one for every insn that reload needs to
    examine.  */
 struct insn_chain *reload_insn_chain;
@@ -443,7 +440,7 @@ static rtx inc_for_reload           PARAMS ((rtx, rtx, rtx, int));
 static void reload_cse_regs_1          PARAMS ((rtx));
 static int reload_cse_noop_set_p       PARAMS ((rtx));
 static int reload_cse_simplify_set     PARAMS ((rtx, rtx));
-static int reload_cse_simplify_operands        PARAMS ((rtx));
+static int reload_cse_simplify_operands        PARAMS ((rtx, rtx));
 static void reload_combine             PARAMS ((void));
 static void reload_combine_note_use    PARAMS ((rtx *, rtx));
 static void reload_combine_note_store  PARAMS ((rtx, rtx, void *));
@@ -457,7 +454,7 @@ static HOST_WIDE_INT sext_for_mode  PARAMS ((enum machine_mode,
                                                 HOST_WIDE_INT));
 static void failed_reload              PARAMS ((rtx, int));
 static int set_reload_reg              PARAMS ((int, int));
-static void reload_cse_simplify                PARAMS ((rtx));
+static void reload_cse_simplify                PARAMS ((rtx, rtx));
 void fixup_abnormal_edges              PARAMS ((void));
 extern void dump_needs                 PARAMS ((struct insn_chain *));
 \f
@@ -1183,10 +1180,12 @@ reload (first, global)
 
   /* Make a pass over all the insns and delete all USEs which we inserted
      only to tag a REG_EQUAL note on them.  Remove all REG_DEAD and REG_UNUSED
-     notes.  Delete all CLOBBER insns that don't refer to the return value
-     and simplify (subreg (reg)) operands.  Also remove all REG_RETVAL and
-     REG_LIBCALL notes since they are no longer useful or accurate.  Strip
-     and regenerate REG_INC notes that may have been moved around.  */
+     notes.  Delete all CLOBBER insns, except those that refer to the return
+     value and the special mem:BLK CLOBBERs added to prevent the scheduler
+     from misarranging variable-array code, and simplify (subreg (reg))
+     operands.  Also remove all REG_RETVAL and REG_LIBCALL notes since they
+     are no longer useful or accurate.  Strip and regenerate REG_INC notes
+     that may have been moved around.  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn))
@@ -1203,6 +1202,11 @@ reload (first, global)
             && (GET_MODE (insn) == QImode
                 || find_reg_note (insn, REG_EQUAL, NULL_RTX)))
            || (GET_CODE (PATTERN (insn)) == CLOBBER
+               && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM
+                   || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode
+                   || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH
+                       && XEXP (XEXP (PATTERN (insn), 0), 0) 
+                               != stack_pointer_rtx))
                && (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
                    || ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
          {
@@ -1383,8 +1387,12 @@ maybe_fix_stack_asms ()
                  break;
 
                default:
-                 cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
-
+                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                   cls = (int) reg_class_subunion[cls]
+                     [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                 else
+                   cls = (int) reg_class_subunion[cls]
+                     [(int) REG_CLASS_FROM_LETTER (c)];
                }
            }
        }
@@ -3403,7 +3411,7 @@ set_offsets_for_label (insn)
 }
 
 /* See if anything that happened changes which eliminations are valid.
-   For example, on the Sparc, whether or not the frame pointer can
+   For example, on the SPARC, whether or not the frame pointer can
    be eliminated can depend on what registers have been used.  We need
    not check some conditions again (such as flag_omit_frame_pointer)
    since they can't have changed.  */
@@ -3842,7 +3850,7 @@ reload_as_needed (live_known)
 
       else if (INSN_P (insn))
        {
-         rtx oldpat = PATTERN (insn);
+         rtx oldpat = copy_rtx (PATTERN (insn));
 
          /* If this is a USE and CLOBBER of a MEM, ensure that any
             references to eliminable registers have been removed.  */
@@ -4324,7 +4332,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
       abort ();
     }
   /* We resolve conflicts with remaining reloads of the same type by
-     excluding the intervals of of reload registers by them from the
+     excluding the intervals of reload registers by them from the
      interval of freed reload registers.  Since we only keep track of
      one set of interval bounds, we might have to exclude somewhat
      more than what would be necessary if we used a HARD_REG_SET here.
@@ -6096,11 +6104,19 @@ merge_assigned_reloads (insn)
             if they were for inputs, RELOAD_OTHER for outputs.  Note that
             this test is equivalent to looking for reloads for this operand
             number.  */
+         /* We must take special care when there are two or more reloads to
+            be merged and a RELOAD_FOR_OUTPUT_ADDRESS reload that loads the
+            same value or a part of it; we must not change its type if there
+            is a conflicting input.  */
 
          if (rld[i].when_needed == RELOAD_OTHER)
            for (j = 0; j < n_reloads; j++)
              if (rld[j].in != 0
                  && rld[j].when_needed != RELOAD_OTHER
+                 && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
+                 && (! conflicting_input
+                     || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+                     || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
                  && reg_overlap_mentioned_for_reload_p (rld[j].in,
                                                         rld[i].in))
                rld[j].when_needed
@@ -6822,7 +6838,7 @@ emit_output_reload_insns (chain, rl, j)
 
   if (rl->when_needed == RELOAD_OTHER)
     {
-      emit_insns (other_output_reload_insns[rl->opnum]);
+      emit_insn (other_output_reload_insns[rl->opnum]);
       other_output_reload_insns[rl->opnum] = get_insns ();
     }
   else
@@ -7038,25 +7054,25 @@ emit_reload_insns (chain)
      reloads for the operand.  The RELOAD_OTHER output reloads are
      output in descending order by reload number.  */
 
-  emit_insns_before (other_input_address_reload_insns, insn);
-  emit_insns_before (other_input_reload_insns, insn);
+  emit_insn_before (other_input_address_reload_insns, insn);
+  emit_insn_before (other_input_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      emit_insns_before (inpaddr_address_reload_insns[j], insn);
-      emit_insns_before (input_address_reload_insns[j], insn);
-      emit_insns_before (input_reload_insns[j], insn);
+      emit_insn_before (inpaddr_address_reload_insns[j], insn);
+      emit_insn_before (input_address_reload_insns[j], insn);
+      emit_insn_before (input_reload_insns[j], insn);
     }
 
-  emit_insns_before (other_operand_reload_insns, insn);
-  emit_insns_before (operand_reload_insns, insn);
+  emit_insn_before (other_operand_reload_insns, insn);
+  emit_insn_before (operand_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      rtx x = emit_insns_after (outaddr_address_reload_insns[j], insn);
-      x = emit_insns_after (output_address_reload_insns[j], x);
-      x = emit_insns_after (output_reload_insns[j], x);
-      emit_insns_after (other_output_reload_insns[j], x);
+      rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
+      x = emit_insn_after (output_address_reload_insns[j], x);
+      x = emit_insn_after (output_reload_insns[j], x);
+      emit_insn_after (other_output_reload_insns[j], x);
     }
 
   /* For all the spill regs newly reloaded in this instruction,
@@ -7163,8 +7179,7 @@ emit_reload_insns (chain)
                    for (k = 1; k < nnr; k++)
                      reg_last_reload_reg[nregno + k]
                        = (nr == nnr
-                          ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
-                                         REGNO (rld[r].reg_rtx) + k)
+                          ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
                           : 0);
 
                  /* Now do the inverse operation.  */
@@ -7213,8 +7228,7 @@ emit_reload_insns (chain)
                    for (k = 1; k < nnr; k++)
                      reg_last_reload_reg[nregno + k]
                        = (nr == nnr
-                          ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
-                                         REGNO (rld[r].reg_rtx) + k)
+                          ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
                           : 0);
 
                  /* Unless we inherited this reload, show we haven't
@@ -7994,8 +8008,9 @@ reload_cse_noop_set_p (set)
 
 /* Try to simplify INSN.  */
 static void
-reload_cse_simplify (insn)
+reload_cse_simplify (insn, testreg)
      rtx insn;
+     rtx testreg;
 {
   rtx body = PATTERN (insn);
 
@@ -8023,7 +8038,7 @@ reload_cse_simplify (insn)
       if (count > 0)
        apply_change_group ();
       else
-       reload_cse_simplify_operands (insn);
+       reload_cse_simplify_operands (insn, testreg);
     }
   else if (GET_CODE (body) == PARALLEL)
     {
@@ -8040,7 +8055,8 @@ reload_cse_simplify (insn)
            {
              if (! reload_cse_noop_set_p (part))
                break;
-             if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
+             if (REG_P (SET_DEST (part))
+                 && REG_FUNCTION_VALUE_P (SET_DEST (part)))
                {
                  if (value)
                    break;
@@ -8066,7 +8082,7 @@ reload_cse_simplify (insn)
       if (count > 0)
        apply_change_group ();
       else
-       reload_cse_simplify_operands (insn);
+       reload_cse_simplify_operands (insn, testreg);
     }
 }
 
@@ -8092,6 +8108,7 @@ reload_cse_regs_1 (first)
      rtx first;
 {
   rtx insn;
+  rtx testreg = gen_rtx_REG (VOIDmode, -1);
 
   cselib_init ();
   init_alias_analysis ();
@@ -8099,7 +8116,7 @@ reload_cse_regs_1 (first)
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
       if (INSN_P (insn))
-       reload_cse_simplify (insn);
+       reload_cse_simplify (insn, testreg);
 
       cselib_process_insn (insn);
     }
@@ -8270,8 +8287,9 @@ reload_cse_simplify_set (set, insn)
    hard registers.  */
 
 static int
-reload_cse_simplify_operands (insn)
+reload_cse_simplify_operands (insn, testreg)
      rtx insn;
+     rtx testreg;
 {
   int i, j;
 
@@ -8291,7 +8309,6 @@ reload_cse_simplify_operands (insn)
   int *op_alt_regno[MAX_RECOG_OPERANDS];
   /* Array of alternatives, sorted in order of decreasing desirability.  */
   int *alternative_order;
-  rtx reg = gen_rtx_REG (VOIDmode, -1);
 
   extract_insn (insn);
 
@@ -8375,8 +8392,8 @@ reload_cse_simplify_operands (insn)
          if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
            continue;
 
-         REGNO (reg) = regno;
-         PUT_MODE (reg, mode);
+         REGNO (testreg) = regno;
+         PUT_MODE (testreg, mode);
 
          /* We found a register equal to this operand.  Now look for all
             alternatives that can accept this register and have not been
@@ -8418,10 +8435,10 @@ reload_cse_simplify_operands (insn)
                     alternative yet and the operand being replaced is not
                     a cheap CONST_INT.  */
                  if (op_alt_regno[i][j] == -1
-                     && reg_fits_class_p (reg, class, 0, mode)
+                     && reg_fits_class_p (testreg, class, 0, mode)
                      && (GET_CODE (recog_data.operand[i]) != CONST_INT
                          || (rtx_cost (recog_data.operand[i], SET)
-                             > rtx_cost (reg, SET))))
+                             > rtx_cost (testreg, SET))))
                    {
                      alternative_nregs[j]++;
                      op_alt_regno[i][j] = regno;
@@ -9465,19 +9482,22 @@ fixup_abnormal_edges ()
              next = NEXT_INSN (insn);
              if (INSN_P (insn))
                {
-                 rtx seq;
-
                  delete_insn (insn);
 
-                 /* We're not deleting it, we're moving it.  */
-                 INSN_DELETED_P (insn) = 0;
+                 /* Sometimes there's still the return value USE.
+                    If it's placed after a trapping call (i.e. that
+                    call is the last insn anyway), we have no fallthru
+                    edge.  Simply delete this use and don't try to insert
+                    on the non-existant edge.  */
+                 if (GET_CODE (PATTERN (insn)) != USE)
+                   {
+                     /* We're not deleting it, we're moving it.  */
+                     INSN_DELETED_P (insn) = 0;
+                     PREV_INSN (insn) = NULL_RTX;
+                     NEXT_INSN (insn) = NULL_RTX;
 
-                 /* Emit a sequence, rather than scarfing the pattern, so
-                    that we don't lose REG_NOTES etc.  */
-                 /* ??? Could copy the test from gen_sequence, but don't
-                    think it's worth the bother.  */
-                 seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
-                 insert_insn_on_edge (seq, e);
+                     insert_insn_on_edge (insn, e);
+                   }
                }
              insn = next;
            }