diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1b1beacc56ff00d41782550c876d279da38010d4..aef412e73c42322f7044f586e1ed097dbba959c9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+Mon Aug 18 21:49:02 1997  Jim Wilson  <wilson@cygnus.com>
+
+	* reload.c (find_reloads): Add code to convert RELOAD_FOR_OPADDR_ADDR
+	reloads to RELOAD_FOR_OPERAND_ADDRESS reloads.
+	* reload1.c: Undo bugfix from Aug 11.
+
 Tue Aug 19 09:34:57 1997  Jeffrey A Law  (law@cygnus.com)
 
 	* Makefile.in (EXPECT, RUNTEST, RUNTESTFLAGS): Define.
diff --git a/gcc/reload.c b/gcc/reload.c
index a8bd5de579ac0f7d15dc2b1bde2fcf906cb465b1..efd4aca2e94be3f3d51e3ac01adc545ef7f9554c 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -3871,6 +3871,35 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 	reload_opnum[i] = goal_alternative_matches[reload_opnum[i]];
     }
 
+  /* Scan all the reloads, and check for RELOAD_FOR_OPERAND_ADDRESS reloads.
+     If we have more than one, then convert all RELOAD_FOR_OPADDR_ADDR
+     reloads to RELOAD_FOR_OPERAND_ADDRESS reloads.
+
+     choose_reload_regs assumes that RELOAD_FOR_OPADDR_ADDR reloads never
+     conflict with RELOAD_FOR_OPERAND_ADDRESS reloads.  This is true for a
+     single pair of RELOAD_FOR_OPADDR_ADDR/RELOAD_FOR_OPERAND_ADDRESS reloads.
+     However, if there is more than one RELOAD_FOR_OPERAND_ADDRESS reload,
+     then a RELOAD_FOR_OPADDR_ADDR reload conflicts with all
+     RELOAD_FOR_OPERAND_ADDRESS reloads other than the one that uses it.
+     This is complicated by the fact that a single operand can have more
+     than one RELOAD_FOR_OPERAND_ADDRESS reload.  It is very difficult to fix
+     choose_reload_regs without affecting code quality, and cases that
+     actually fail are extremely rare, so it turns out to be better to fix
+     the problem here by not generating cases that choose_reload_regs will
+     fail for.  */
+   
+  {
+    int op_addr_reloads = 0;
+    for (i = 0; i < n_reloads; i++)
+      if (reload_when_needed[i] == RELOAD_FOR_OPERAND_ADDRESS)
+	op_addr_reloads++;
+
+    if (op_addr_reloads > 1)
+      for (i = 0; i < n_reloads; i++)
+	if (reload_when_needed[i] == RELOAD_FOR_OPADDR_ADDR)
+	  reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+  }
+
   /* See if we have any reloads that are now allowed to be merged
      because we've changed when the reload is needed to
      RELOAD_FOR_OPERAND_ADDRESS or RELOAD_FOR_OTHER_ADDRESS.  Only
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 8067787478322be0b2d6148120418546ec553cf1..a3361abbfadfabb55e8f9ee1c43e714ea4a46674 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1341,8 +1341,8 @@ reload (first, global, dumpfile)
 			 don't conflict with things needed to reload inputs or
 			 outputs.  */
 
-		      in_max = MAX ((insn_needs.op_addr.regs[j][i]
-				     + insn_needs.op_addr_reload.regs[j][i]),
+		      in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
+					 insn_needs.op_addr_reload.regs[j][i]),
 				    in_max);
 
 		      out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
@@ -1374,8 +1374,8 @@ reload (first, global, dumpfile)
 			= MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
 		    }
 
-		  in_max = MAX ((insn_needs.op_addr.groups[i]
-				 + insn_needs.op_addr_reload.groups[i]),
+		  in_max = MAX (MAX (insn_needs.op_addr.groups[i],
+				     insn_needs.op_addr_reload.groups[i]),
 				in_max);
 		  out_max = MAX (out_max, insn_needs.insn.groups[i]);
 
@@ -4605,13 +4605,7 @@ reload_reg_free_p (regno, opnum, type)
 	if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
 	  return 0;
 
-      /* ??? A OPADDR_ADDR reload does not conflict with the OPERAND_ADDRESS
-	 reload that uses it.  However, the same operand can have multiple
-	 OPERAND_ADDRESS reloads, and a OPADDR_ADDR reload does conflict with
-	 other OPERAND_ADDRESS reloads for the same operand, hence we must
-	 say that OPADDR_ADDR and OPERAND_ADDRESS reloads always conflict.  */
       return (! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)
-	      && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
 	      && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno));
 
     case RELOAD_FOR_OPADDR_ADDR:
@@ -4619,8 +4613,7 @@ reload_reg_free_p (regno, opnum, type)
         if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
           return 0;
 
-      return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
-	      && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno));
+      return (!TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno));
 
     case RELOAD_FOR_OUTPUT:
       /* This cannot share a register with RELOAD_FOR_INSN reloads, other
@@ -4737,6 +4730,12 @@ reload_reg_free_before_p (regno, opnum, type)
       return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
 
     case RELOAD_FOR_OPERAND_ADDRESS:
+      /* Earlier reloads include RELOAD_FOR_OPADDR_ADDR reloads.  */
+      if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
+	return 0;
+
+      /* ... fall through ...  */
+
     case RELOAD_FOR_OPADDR_ADDR:
     case RELOAD_FOR_INSN:
       /* These can't conflict with inputs, or each other, so all we have to
@@ -4880,7 +4879,8 @@ reload_reg_reaches_end_p (regno, opnum, type)
 	    || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
 	  return 0;
 
-      return (! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno));
+      return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
+	      && !TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno));
 
     case RELOAD_FOR_INSN:
       /* These conflict with other outputs with RELOAD_OTHER.  So
@@ -4955,13 +4955,11 @@ reloads_conflict (r1, r2)
 
     case RELOAD_FOR_OPERAND_ADDRESS:
       return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
-	      || r2_type == RELOAD_FOR_OPERAND_ADDRESS
-	      || r2_type == RELOAD_FOR_OPADDR_ADDR);
+	      || r2_type == RELOAD_FOR_OPERAND_ADDRESS);
 
     case RELOAD_FOR_OPADDR_ADDR:
       return (r2_type == RELOAD_FOR_INPUT 
-	      || r2_type == RELOAD_FOR_OPADDR_ADDR
-	      || r2_type == RELOAD_FOR_OPERAND_ADDRESS);
+	      || r2_type == RELOAD_FOR_OPADDR_ADDR);
 
     case RELOAD_FOR_OUTPUT:
       return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT