diff mbox

[40/67] Use scalar_int_mode for extraction_insn fields

Message ID 87oa0li6jt.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Dec. 9, 2016, 1:19 p.m. UTC
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.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* 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.
diff mbox

Patch

diff --git a/gcc/combine.c b/gcc/combine.c
index 0f25782..449f371 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7608,7 +7608,7 @@  make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   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;
     }
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 0b2e61a..71e1fa8 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -409,31 +409,32 @@  flip_storage_order (machine_mode mode, rtx x)
   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);
     }
 }
 
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index e664587..6541f07 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -100,9 +100,14 @@  get_traditional_extraction_insn (extraction_insn *insn,
     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 extraction_insn *insn,
 
   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;
 }
 
diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
index 840dc79..58fbf13 100644
--- a/gcc/optabs-query.h
+++ b/gcc/optabs-query.h
@@ -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 *,
diff --git a/gcc/recog.c b/gcc/recog.c
index 317ec29..906a5b0 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -663,25 +663,18 @@  simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
 					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;