insv, extv and eztzv modify or read a field in a register or
memory.  The field always has a scalar integer mode, while the
register or memory either has a scalar integer mode or BLKmode.
The mode of the bit position is also a scalar integer.

This patch uses the type system to make that explicit.

2017-07-13  Richard Sandiford  <richard.sandif...@linaro.org>
            Alan Hayward  <alan.hayw...@arm.com>
            David Sherwood  <david.sherw...@arm.com>

gcc/
        * optabs-query.h (extraction_insn::struct_mode): Change type to
        opt_scalar_int_mode and update comment.
        (extraction_insn::field_mode): Change type to scalar_int_mode.
        (extraction_insn::pos_mode): Likewise.
        * combine.c (make_extraction): Update accordingly.
        * optabs-query.c (get_traditional_extraction_insn): Likewise.
        (get_optab_extraction_insn): Likewise.
        * recog.c (simplify_while_replacing): Likewise.
        * expmed.c (narrow_bit_field_mem): Chane the type of the mode
        parameter to opt_scalar_int_mode.

Index: gcc/optabs-query.h
===================================================================
--- gcc/optabs-query.h  2017-02-23 19:54:15.000000000 +0000
+++ gcc/optabs-query.h  2017-07-13 09:18:42.162518990 +0100
@@ -141,16 +141,17 @@ struct extraction_insn
   enum insn_code icode;
 
   /* The mode that the structure operand should have.  This is byte_mode
-     when using the legacy insv, extv and extzv patterns to access memory.  */
-  machine_mode struct_mode;
+     when using the legacy insv, extv and extzv patterns to access memory.
+     If no mode is given, the structure is a BLKmode memory.  */
+  opt_scalar_int_mode struct_mode;
 
   /* The mode of the field to be inserted or extracted, and by extension
      the mode of the insertion or extraction itself.  */
-  machine_mode field_mode;
+  scalar_int_mode field_mode;
 
   /* The mode of the field's bit position.  This is only important
      when the position is variable rather than constant.  */
-  machine_mode pos_mode;
+  scalar_int_mode pos_mode;
 };
 
 bool get_best_reg_extraction_insn (extraction_insn *,
Index: gcc/combine.c
===================================================================
--- gcc/combine.c       2017-07-13 09:18:39.584734236 +0100
+++ gcc/combine.c       2017-07-13 09:18:42.160519154 +0100
@@ -7632,7 +7632,7 @@ make_extraction (machine_mode mode, rtx
   if (get_best_reg_extraction_insn (&insn, pattern,
                                    GET_MODE_BITSIZE (inner_mode), mode))
     {
-      wanted_inner_reg_mode = insn.struct_mode;
+      wanted_inner_reg_mode = *insn.struct_mode;
       pos_mode = insn.pos_mode;
       extraction_mode = insn.field_mode;
     }
Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c  2017-07-13 09:18:30.902501597 +0100
+++ gcc/optabs-query.c  2017-07-13 09:18:42.161519072 +0100
@@ -100,9 +100,14 @@ get_traditional_extraction_insn (extract
     pos_mode = word_mode;
 
   insn->icode = icode;
-  insn->field_mode = field_mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
-  insn->pos_mode = pos_mode;
+  insn->field_mode = as_a <scalar_int_mode> (field_mode);
+  if (type == ET_unaligned_mem)
+    insn->struct_mode = byte_mode;
+  else if (struct_mode == BLKmode)
+    insn->struct_mode = opt_scalar_int_mode ();
+  else
+    insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
+  insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
   return true;
 }
 
@@ -126,12 +131,17 @@ get_optab_extraction_insn (struct extrac
 
   const struct insn_data_d *data = &insn_data[icode];
 
+  machine_mode pos_mode = data->operand[pos_op].mode;
+  if (pos_mode == VOIDmode)
+    pos_mode = word_mode;
+
   insn->icode = icode;
-  insn->field_mode = mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
-  insn->pos_mode = data->operand[pos_op].mode;
-  if (insn->pos_mode == VOIDmode)
-    insn->pos_mode = word_mode;
+  insn->field_mode = as_a <scalar_int_mode> (mode);
+  if (type == ET_unaligned_mem)
+    insn->struct_mode = opt_scalar_int_mode ();
+  else
+    insn->struct_mode = insn->field_mode;
+  insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
   return true;
 }
 
Index: gcc/recog.c
===================================================================
--- gcc/recog.c 2017-07-13 09:18:39.591733644 +0100
+++ gcc/recog.c 2017-07-13 09:18:42.162518990 +0100
@@ -663,25 +663,18 @@ simplify_while_replacing (rtx *loc, rtx
                                        MEM_ADDR_SPACE (XEXP (x, 0)))
          && !MEM_VOLATILE_P (XEXP (x, 0)))
        {
-         machine_mode wanted_mode = VOIDmode;
          int pos = INTVAL (XEXP (x, 2));
-
+         machine_mode new_mode = is_mode;
          if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ())
-           {
-             wanted_mode = insn_data[targetm.code_for_extzv].operand[1].mode;
-             if (wanted_mode == VOIDmode)
-               wanted_mode = word_mode;
-           }
+           new_mode = insn_data[targetm.code_for_extzv].operand[1].mode;
          else if (GET_CODE (x) == SIGN_EXTRACT && targetm.have_extv ())
-           {
-             wanted_mode = insn_data[targetm.code_for_extv].operand[1].mode;
-             if (wanted_mode == VOIDmode)
-               wanted_mode = word_mode;
-           }
+           new_mode = insn_data[targetm.code_for_extv].operand[1].mode;
+         scalar_int_mode wanted_mode = (new_mode == VOIDmode
+                                        ? word_mode
+                                        : as_a <scalar_int_mode> (new_mode));
 
          /* If we have a narrower mode, we can do something.  */
-         if (wanted_mode != VOIDmode
-             && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
+         if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
            {
              int offset = pos / BITS_PER_UNIT;
              rtx newmem;
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c        2017-07-13 09:18:41.678559010 +0100
+++ gcc/expmed.c        2017-07-13 09:18:42.161519072 +0100
@@ -409,31 +409,32 @@ flip_storage_order (machine_mode mode, r
   return result;
 }
 
-/* Adjust bitfield memory MEM so that it points to the first unit of mode
-   MODE that contains a bitfield of size BITSIZE at bit position BITNUM.
-   If MODE is BLKmode, return a reference to every byte in the bitfield.
-   Set *NEW_BITNUM to the bit position of the field within the new memory.  */
+/* If MODE is set, adjust bitfield memory MEM so that it points to the
+   first unit of mode MODE that contains a bitfield of size BITSIZE at
+   bit position BITNUM.  If MODE is not set, return a BLKmode reference
+   to every byte in the bitfield.  Set *NEW_BITNUM to the bit position
+   of the field within the new memory.  */
 
 static rtx
-narrow_bit_field_mem (rtx mem, machine_mode mode,
+narrow_bit_field_mem (rtx mem, opt_scalar_int_mode mode,
                      unsigned HOST_WIDE_INT bitsize,
                      unsigned HOST_WIDE_INT bitnum,
                      unsigned HOST_WIDE_INT *new_bitnum)
 {
-  if (mode == BLKmode)
+  if (mode.exists ())
+    {
+      unsigned int unit = GET_MODE_BITSIZE (*mode);
+      *new_bitnum = bitnum % unit;
+      HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT;
+      return adjust_bitfield_address (mem, *mode, offset);
+    }
+  else
     {
       *new_bitnum = bitnum % BITS_PER_UNIT;
       HOST_WIDE_INT offset = bitnum / BITS_PER_UNIT;
       HOST_WIDE_INT size = ((*new_bitnum + bitsize + BITS_PER_UNIT - 1)
                            / BITS_PER_UNIT);
-      return adjust_bitfield_address_size (mem, mode, offset, size);
-    }
-  else
-    {
-      unsigned int unit = GET_MODE_BITSIZE (mode);
-      *new_bitnum = bitnum % unit;
-      HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT;
-      return adjust_bitfield_address (mem, mode, offset);
+      return adjust_bitfield_address_size (mem, BLKmode, offset, size);
     }
 }
 

Reply via email to