Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2012-11-18 17:33:42.000000000 +0000
+++ gcc/optabs.c	2012-11-20 20:46:16.893286686 +0000
@@ -8258,11 +8258,12 @@ #define CODE_FOR_extzv	CODE_FOR_nothing
 enum extraction_type { ET_unaligned_mem, ET_reg };
 
 /* Check whether insv, extv or extzv pattern ICODE can be used for an
-   insertion or extraction of type TYPE on a structure of mode MODE.
-   Return true if so and fill in *INSN accordingly.  STRUCT_OP is the
-   operand number of the structure (the first sign_extract or zero_extract
-   operand) and FIELD_OP is the operand number of the field (the other
-   side of the set from the sign_extract or zero_extract).  */
+   insertion or extraction of type TYPE on a structure and field of
+   mode MODE.  Return true if so and fill in *INSN accordingly.
+   STRUCT_OP is the operand number of the structure (the first
+   sign_extract or zero_extract operand) and FIELD_OP is the operand
+   number of the field (the other side of the set from the sign_extract
+   or zero_extract).  */
 
 static bool
 get_traditional_extraction_insn (extraction_insn *insn,
@@ -8273,15 +8274,23 @@ get_traditional_extraction_insn (extract
 {
   const struct insn_data_d *data = &insn_data[icode];
 
-  enum machine_mode struct_mode = data->operand[struct_op].mode;
-  if (struct_mode == VOIDmode)
-    struct_mode = word_mode;
-  if (mode != struct_mode)
-    return false;
-
   enum machine_mode field_mode = data->operand[field_op].mode;
   if (field_mode == VOIDmode)
     field_mode = word_mode;
+  if (mode != field_mode)
+    return false;
+
+  enum machine_mode struct_mode;
+  if (type == ET_unaligned_mem)
+    struct_mode = byte_mode;
+  else
+    {
+      struct_mode = data->operand[struct_op].mode;
+      if (struct_mode == VOIDmode)
+	struct_mode = word_mode;
+      if (mode != struct_mode)
+	return false;
+    }
 
   enum machine_mode pos_mode = data->operand[struct_op + 2].mode;
   if (pos_mode == VOIDmode)
@@ -8289,7 +8298,7 @@ get_traditional_extraction_insn (extract
 
   insn->icode = icode;
   insn->field_mode = field_mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
+  insn->struct_mode = struct_mode;
   insn->pos_mode = pos_mode;
   return true;
 }
