OSDN Git Service

* array.c: Don't include assert.h.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index b114dc2..950d6fd 100644 (file)
@@ -2485,9 +2485,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
      a register.  */
   enum reg_class preferred_class[MAX_RECOG_OPERANDS];
   char pref_or_nothing[MAX_RECOG_OPERANDS];
-  /* Nonzero for a MEM operand whose entire address needs a reload.  */
+  /* Nonzero for a MEM operand whose entire address needs a reload. 
+     May be -1 to indicate the entire address may or may not need a reload.  */
   int address_reloaded[MAX_RECOG_OPERANDS];
-  /* Nonzero for an address operand that needs to be completely reloaded.  */
+  /* Nonzero for an address operand that needs to be completely reloaded.
+     May be -1 to indicate the entire operand may or may not need a reload.  */
   int address_operand_reloaded[MAX_RECOG_OPERANDS];
   /* Value of enum reload_type to use for operand.  */
   enum reload_type operand_type[MAX_RECOG_OPERANDS];
@@ -3077,6 +3079,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                  {
                    /* Operands don't match.  */
                    rtx value;
+                   int loc1, loc2;
                    /* Retroactively mark the operand we had to match
                       as a loser, if it wasn't already.  */
                    if (this_alternative_win[m])
@@ -3085,12 +3088,26 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                    if (this_alternative[m] == (int) NO_REGS)
                      bad = 1;
                    /* But count the pair only once in the total badness of
-                      this alternative, if the pair can be a dummy reload.  */
+                      this alternative, if the pair can be a dummy reload.
+                      The pointers in operand_loc are not swapped; swap
+                      them by hand if necessary.  */
+                   if (swapped && i == commutative)
+                     loc1 = commutative + 1;
+                   else if (swapped && i == commutative + 1)
+                     loc1 = commutative;
+                   else
+                     loc1 = i;
+                   if (swapped && m == commutative)
+                     loc2 = commutative + 1;
+                   else if (swapped && m == commutative + 1)
+                     loc2 = commutative;
+                   else
+                     loc2 = m;
                    value
                      = find_dummy_reload (recog_data.operand[i],
                                           recog_data.operand[m],
-                                          recog_data.operand_loc[i],
-                                          recog_data.operand_loc[m],
+                                          recog_data.operand_loc[loc1],
+                                          recog_data.operand_loc[loc2],
                                           operand_mode[i], operand_mode[m],
                                           this_alternative[m], -1,
                                           this_alternative_earlyclobber[m]);
@@ -3180,7 +3197,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                          : offsettable_nonstrict_memref_p (operand))
                         /* A reloaded address is offsettable because it is now
                            just a simple register indirect.  */
-                        || address_reloaded[i]))
+                        || address_reloaded[i] == 1))
                    || (REG_P (operand)
                        && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                        && reg_renumber[REGNO (operand)] < 0
@@ -3291,7 +3308,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
                        /* If the address was already reloaded,
                           we win as well.  */
                        else if (MEM_P (operand)
-                                && address_reloaded[i])
+                                && address_reloaded[i] == 1)
                          win = 1;
                        /* Likewise if the address will be reloaded because
                           reg_equiv_address is nonzero.  For reg_equiv_mem
@@ -3891,7 +3908,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
       }
     else if (goal_alternative_matched[i] < 0
             && goal_alternative_matches[i] < 0
-            && !address_operand_reloaded[i]
+            && address_operand_reloaded[i] != 1
             && optimize)
       {
        /* For each non-matching operand that's a MEM or a pseudo-register
@@ -4631,8 +4648,9 @@ maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
    to determine if we may generate output reloads, and where to put USEs
    for pseudos that we have to replace with stack slots.
 
-   Value is nonzero if this address is reloaded or replaced as a whole.
-   This is interesting to the caller if the address is an autoincrement.
+   Value is one if this address is reloaded or replaced as a whole; it is
+   zero if the top level of this address was not reloaded or replaced, and
+   it is -1 if it may or may not have been reloaded or replaced.
 
    Note that there is no verification that the address will be valid after
    this routine does its work.  Instead, we rely on the fact that the address
@@ -4647,6 +4665,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 {
   int regno;
   int removed_and = 0;
+  int op_index;
   rtx tem;
 
   /* If the address is a register, see if it is a legitimate address and
@@ -4770,7 +4789,7 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
       *memrefloc = copy_rtx (*memrefloc);
       XEXP (*memrefloc, 0) = ad;
       move_replacements (&ad, &XEXP (*memrefloc, 0));
-      return 1;
+      return -1;
     }
   while (0);
 #endif
@@ -4892,7 +4911,9 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
 
      Handle all base registers here, not just fp/ap/sp, because on some
      targets (namely SPARC) we can also get invalid addresses from preventive
-     subreg big-endian corrections made by find_reloads_toplev.
+     subreg big-endian corrections made by find_reloads_toplev.  We
+     can also get expressions involving LO_SUM (rather than PLUS) from
+     find_reloads_subreg_address.
 
      If we decide to do something, it must be that `double_reg_address_ok'
      is true.  We generate a reload of the base register + constant and
@@ -4900,62 +4921,62 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
      This is safe because we know the address isn't shared.
 
      We check for the base register as both the first and second operand of
-     the innermost PLUS.  */
-
-  else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && GET_CODE (XEXP (ad, 0)) == PLUS
-          && REG_P (XEXP (XEXP (ad, 0), 0))
-          && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
-          && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
-              || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
-              || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
-          && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
+     the innermost PLUS and/or LO_SUM.  */
+
+  for (op_index = 0; op_index < 2; ++op_index)
     {
-      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
-                               plus_constant (XEXP (XEXP (ad, 0), 0),
-                                              INTVAL (XEXP (ad, 1))),
-                               XEXP (XEXP (ad, 0), 1));
-      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
-                                MODE_BASE_REG_CLASS (mode),
-                                GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
-                             type, 0, insn);
+      rtx operand;
 
-      return 0;
-    }
+      if (!(GET_CODE (ad) == PLUS 
+           && GET_CODE (XEXP (ad, 1)) == CONST_INT
+           && (GET_CODE (XEXP (ad, 0)) == PLUS
+               || GET_CODE (XEXP (ad, 0)) == LO_SUM)))
+       continue;
 
-  else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
-          && GET_CODE (XEXP (ad, 0)) == PLUS
-          && REG_P (XEXP (XEXP (ad, 0), 1))
-          && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
-          && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
-              || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+      operand = XEXP (XEXP (ad, 0), op_index);
+      if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+       continue;
+
+      if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
+          || operand == frame_pointer_rtx
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+          || operand == hard_frame_pointer_rtx
 #endif
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-              || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+          || operand == arg_pointer_rtx
 #endif
-              || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
-          && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
-    {
-      *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
-                               XEXP (XEXP (ad, 0), 0),
-                               plus_constant (XEXP (XEXP (ad, 0), 1),
-                                              INTVAL (XEXP (ad, 1))));
-      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
-                                MODE_BASE_REG_CLASS (mode),
-                                GET_MODE (ad), opnum, type, ind_levels);
-      find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
-                             type, 0, insn);
+          || operand == stack_pointer_rtx)
+         && ! maybe_memory_address_p (mode, ad, 
+                                      &XEXP (XEXP (ad, 0), op_index)))
+       {
+         rtx offset_reg;
+         rtx addend;
+
+         offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
+         addend = XEXP (XEXP (ad, 0), 1 - op_index);
+         
+         /* Form the adjusted address.  */
+         if (GET_CODE (XEXP (ad, 0)) == PLUS)
+           ad = gen_rtx_PLUS (GET_MODE (ad), 
+                              op_index == 0 ? offset_reg : addend, 
+                              op_index == 0 ? addend : offset_reg);
+         else
+           ad = gen_rtx_LO_SUM (GET_MODE (ad), 
+                                op_index == 0 ? offset_reg : addend, 
+                                op_index == 0 ? addend : offset_reg);
+         *loc = ad;
+
+         find_reloads_address_part (XEXP (ad, op_index), 
+                                    &XEXP (ad, op_index),
+                                    MODE_BASE_REG_CLASS (mode),
+                                    GET_MODE (ad), opnum, type, ind_levels);
+         find_reloads_address_1 (mode, 
+                                 XEXP (ad, 1 - op_index), 1, 
+                                 &XEXP (ad, 1 - op_index), opnum,
+                                 type, 0, insn);
 
-      return 0;
+         return 0;
+       }
     }
 
   /* See if address becomes valid when an eliminable register