diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7ffdb8ffe55b103756db78982b7e395f21ae19a6..b133ccefe78a3b12baf6012104a63a85661c40c1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2001-05-10  David Edelsohn  <edelsohn@gnu.org>
+
+	* expr.c (emit_group_load): extract_bit_field requires a REG or
+	MEM as an argument.
+
 Thu May 10 14:45:44 2001  Jeffrey A Law  (law@cygnus.com)
 
 	* jump.c (jump_optimize_1): Do not wrap the new jump target
diff --git a/gcc/expr.c b/gcc/expr.c
index 7edfea63c09f0e7381568e17b081457eb44805e3..cdabeddece74cc7a4f1190f970251c6157efddc0 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1959,18 +1959,6 @@ emit_group_load (dst, orig_src, ssize, align)
 
   tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
 
-  /* If we won't be loading directly from memory, protect the real source
-     from strange tricks we might play.  */
-  src = orig_src;
-  if (GET_CODE (src) != MEM && ! CONSTANT_P (src))
-    {
-      if (GET_MODE (src) == VOIDmode)
-	src = gen_reg_rtx (GET_MODE (dst));
-      else
-	src = gen_reg_rtx (GET_MODE (orig_src));
-      emit_move_insn (src, orig_src);
-    }
-
   /* Process the pieces.  */
   for (i = start; i < XVECLEN (dst, 0); i++)
     {
@@ -1988,6 +1976,22 @@ emit_group_load (dst, orig_src, ssize, align)
 	    abort ();
 	}
 
+      /* If we won't be loading directly from memory, protect the real source
+	 from strange tricks we might play; but make sure that the source can
+	 be loaded directly into the destination.  */
+      src = orig_src;
+      if (GET_CODE (orig_src) != MEM
+	  && (!CONSTANT_P (orig_src)
+	      || (GET_MODE (orig_src) != mode
+		  && GET_MODE (orig_src) != VOIDmode)))
+	{
+	  if (GET_MODE (orig_src) == VOIDmode)
+	    src = gen_reg_rtx (mode);
+	  else
+	    src = gen_reg_rtx (GET_MODE (orig_src));
+	  emit_move_insn (src, orig_src);
+	}
+
       /* Optimize the access just a bit.  */
       if (GET_CODE (src) == MEM
 	  && align >= GET_MODE_ALIGNMENT (mode)
@@ -2011,8 +2015,7 @@ emit_group_load (dst, orig_src, ssize, align)
 	  else
 	    abort ();
 	}
-      else if ((CONSTANT_P (src)
-		&& (GET_MODE (src) == VOIDmode || GET_MODE (src) == mode))
+      else if (CONSTANT_P (src)
 	       || (GET_CODE (src) == REG && GET_MODE (src) == mode))
 	tmps[i] = src;
       else