diff --git a/gcc/function.c b/gcc/function.c
index e673f21..bb09df8 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -1675,22 +1675,55 @@ instantiate_virtual_regs_in_insn (rtx insn)
 	  break;
 
 	case SUBREG:
-	  new_rtx = instantiate_new_reg (SUBREG_REG (x), &offset);
-	  if (new_rtx == NULL)
-	    continue;
-	  if (offset != 0)
-	    {
-	      start_sequence ();
-	      new_rtx = expand_simple_binop (GET_MODE (new_rtx), PLUS, new_rtx,
-					 GEN_INT (offset), NULL_RTX,
-					 1, OPTAB_LIB_WIDEN);
-	      seq = get_insns ();
-	      end_sequence ();
-	      emit_insn_before (seq, insn);
-	    }
-	  x = simplify_gen_subreg (recog_data.operand_mode[i], new_rtx,
-				   GET_MODE (new_rtx), SUBREG_BYTE (x));
-	  gcc_assert (x);
+	  {
+	    if (MEM_P (SUBREG_REG (x)))
+	      {
+		rtx addr, mem_rtx, tmp_rtx;
+		bool changed = false;
+
+		mem_rtx = SUBREG_REG (x);
+		addr = XEXP (mem_rtx, 0);
+
+		for_each_rtx (&addr, instantiate_virtual_regs_in_rtx, &changed);
+		if (!changed)
+		  continue;
+
+		start_sequence ();
+		mem_rtx = replace_equiv_address (mem_rtx, addr);
+		tmp_rtx = simplify_gen_subreg (recog_data.operand_mode[i], mem_rtx,
+					       GET_MODE (mem_rtx), SUBREG_BYTE (x));
+		if (!safe_insn_predicate (insn_code, i, tmp_rtx))
+		  {
+		    addr = force_reg (GET_MODE (addr), addr);
+		    mem_rtx = replace_equiv_address (mem_rtx, addr);
+		  }
+		seq = get_insns ();
+		end_sequence ();
+		if (seq)
+		  emit_insn_before (seq, insn);
+		x = simplify_gen_subreg (recog_data.operand_mode[i], mem_rtx,
+					 GET_MODE (mem_rtx), SUBREG_BYTE (x));
+	      }
+	    else
+	      {
+		new_rtx = instantiate_new_reg (SUBREG_REG (x), &offset);
+		if (new_rtx == NULL)
+		  continue;
+		if (offset != 0)
+		  {
+		    start_sequence ();
+		    new_rtx = expand_simple_binop (GET_MODE (new_rtx), PLUS, new_rtx,
+						   GEN_INT (offset), NULL_RTX,
+						   1, OPTAB_LIB_WIDEN);
+		    seq = get_insns ();
+		    end_sequence ();
+		    emit_insn_before (seq, insn);
+		  }
+		x = simplify_gen_subreg (recog_data.operand_mode[i], new_rtx,
+					 GET_MODE (new_rtx), SUBREG_BYTE (x));
+	      }
+	    gcc_assert (x);
+	  }
 	  break;
 
 	default:
