diff mbox

Setting precision for a PSImode type

Message ID 4F85C8FC.5060902@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt April 11, 2012, 6:10 p.m. UTC
On 04/11/2012 07:31 PM, Peter Bigot wrote:
> The biggest one is that widening from 20-bit to 32-bit is an extremely
> expensive operation: it was a 16-bit ISA, but some newer MCUs support
> an extension with 20 bits in each register and a set of new
> instructions that must be used to preserve the upper 4 bits.  Getting
> bits 19..16 of a 20-bit register down into the low bits of a 16 bit
> register requires a five-position rotate-through-carry.  The 20-bit
> enhancement to the ISA was really intended only to support a larger
> address space; to simplify validation of the machine description I've
> chosen to allow it to be used for any integer operation, but I have no
> reason to think that'll be common.

Ok. So these are pointer modes, essentially? For the target I'm working
on, I'm using the following patch, see if that helps you any. It seems
to apply to trunk, so I might as well ask for an OK if it bootstraps and
tests ok (but it has little use while these ports remain out-of-tree).


Bernd
* mode-classes.def (MODE_POINTER): New.
	* machmode.h (POINTER_MODE_P): New macro.
	* genopinit.c (gen_insn): Allow MODE_POINTER for some modifiers.
	* expr.c (convert_move): Handle MODE_POINTER like MODE_PARTIAL_INT.
	* recog.c (general_operand, immediate_operand): Allow MODE_POINTER.
	* stor-layout.c (int_mode_for_mode): Likwise.
	* genmodes.c (complete_mode): Likewise.
	(POINTER_MODE): New macro.
	(make_pointer_mode): New static function.
	* emit-rtl.c (immed_double_const): Allow MODE_POINTER.
	* simplify-rtx.c (simplify_immed_subreg): Likewise.
	* explow.c (trunc_int_for_mode): Likewise.

Comments

Richard Sandiford April 11, 2012, 7:15 p.m. UTC | #1
Bernd Schmidt <bernds@codesourcery.com> writes:
> On 04/11/2012 07:31 PM, Peter Bigot wrote:
>> The biggest one is that widening from 20-bit to 32-bit is an extremely
>> expensive operation: it was a 16-bit ISA, but some newer MCUs support
>> an extension with 20 bits in each register and a set of new
>> instructions that must be used to preserve the upper 4 bits.  Getting
>> bits 19..16 of a 20-bit register down into the low bits of a 16 bit
>> register requires a five-position rotate-through-carry.  The 20-bit
>> enhancement to the ISA was really intended only to support a larger
>> address space; to simplify validation of the machine description I've
>> chosen to allow it to be used for any integer operation, but I have no
>> reason to think that'll be common.
>
> Ok. So these are pointer modes, essentially? For the target I'm working
> on, I'm using the following patch, see if that helps you any. It seems
> to apply to trunk, so I might as well ask for an OK if it bootstraps and
> tests ok (but it has little use while these ports remain out-of-tree).

Not that I can approve this anyway, but: what are the properties of
MODE_POINTER vs. MODE_PARTIAL_INT?

It seems odd on the face of it for POINTER_MODE_P (Pmode) to be false
on the majority of targets.  But that's probably just a naming thing.

Richard
Bernd Schmidt April 11, 2012, 7:22 p.m. UTC | #2
On 04/11/2012 09:15 PM, Richard Sandiford wrote:
> Bernd Schmidt <bernds@codesourcery.com> writes:
>> On 04/11/2012 07:31 PM, Peter Bigot wrote:
>>> The biggest one is that widening from 20-bit to 32-bit is an extremely
>>> expensive operation: it was a 16-bit ISA, but some newer MCUs support
>>> an extension with 20 bits in each register and a set of new
>>> instructions that must be used to preserve the upper 4 bits.  Getting
>>> bits 19..16 of a 20-bit register down into the low bits of a 16 bit
>>> register requires a five-position rotate-through-carry.  The 20-bit
>>> enhancement to the ISA was really intended only to support a larger
>>> address space; to simplify validation of the machine description I've
>>> chosen to allow it to be used for any integer operation, but I have no
>>> reason to think that'll be common.
>>
>> Ok. So these are pointer modes, essentially? For the target I'm working
>> on, I'm using the following patch, see if that helps you any. It seems
>> to apply to trunk, so I might as well ask for an OK if it bootstraps and
>> tests ok (but it has little use while these ports remain out-of-tree).
> 
> Not that I can approve this anyway, but: what are the properties of
> MODE_POINTER vs. MODE_PARTIAL_INT?

MODE_POINTER is intended to avoid problems where you have modes that
cannot be used as integer modes (because the arithmetic operations
doesn't exist on the machine), and which have odd conversions. It's a
way of keeping them out of the way of int_mode_for_size. I'm also
thinking of overloading the meaning so that MODE_POINTER occupies
exactly one register, even if it is bigger than BITS_PER_WORD (yes, ugh).

> It seems odd on the face of it for POINTER_MODE_P (Pmode) to be false
> on the majority of targets.  But that's probably just a naming thing.

On the majority of targets the distinction is meaningless since pointers
don't behave any differently than integers.


Bernd
diff mbox

Patch

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	(revision 365245)
+++ gcc/machmode.h	(working copy)
@@ -76,6 +76,9 @@  extern const unsigned char mode_class[NU
   (GET_MODE_CLASS (MODE) == MODE_INT		\
    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT)
 
+/* True if MODE is a pointer mode.  */
+#define POINTER_MODE_P(MODE) (GET_MODE_CLASS (MODE) == MODE_POINTER)
+
 /* Nonzero if MODE is a scalar floating point mode.  */
 #define SCALAR_FLOAT_MODE_P(MODE)		\
   (GET_MODE_CLASS (MODE) == MODE_FLOAT		\
Index: gcc/genopinit.c
===================================================================
--- gcc/genopinit.c	(revision 365109)
+++ gcc/genopinit.c	(working copy)
@@ -368,11 +368,13 @@  gen_insn (rtx insn)
 
 		    if (*p == 0
 			&& (! force_int || mode_class[i] == MODE_INT
-			    || mode_class[i] == MODE_VECTOR_INT)
+			    || mode_class[i] == MODE_VECTOR_INT
+			    || mode_class[i] == MODE_POINTER)
 		        && (! force_partial_int
                             || mode_class[i] == MODE_INT
                             || mode_class[i] == MODE_PARTIAL_INT
-			    || mode_class[i] == MODE_VECTOR_INT)
+			    || mode_class[i] == MODE_VECTOR_INT
+			    || mode_class[i] == MODE_POINTER)
 			&& (! force_float
 			    || mode_class[i] == MODE_FLOAT
 			    || mode_class[i] == MODE_DECIMAL_FLOAT
Index: gcc/mode-classes.def
===================================================================
--- gcc/mode-classes.def	(revision 365109)
+++ gcc/mode-classes.def	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.
   DEF_MODE_CLASS (MODE_CC),		/* condition code in a register */ \
   DEF_MODE_CLASS (MODE_INT),		/* integer */			   \
   DEF_MODE_CLASS (MODE_PARTIAL_INT),	/* integer with padding bits */    \
+  DEF_MODE_CLASS (MODE_POINTER),	/* pointer */			   \
   DEF_MODE_CLASS (MODE_FRACT),		/* signed fractional number */	   \
   DEF_MODE_CLASS (MODE_UFRACT),		/* unsigned fractional number */   \
   DEF_MODE_CLASS (MODE_ACCUM),		/* signed accumulator */	   \
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 365245)
+++ gcc/expr.c	(working copy)
@@ -481,7 +481,8 @@  convert_move (rtx to, rtx from, int unsi
   /* Handle pointer conversion.  */			/* SPEE 900220.  */
   /* Targets are expected to provide conversion insns between PxImode and
      xImode for all MODE_PARTIAL_INT modes they use, but no others.  */
-  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT)
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT
+      || GET_MODE_CLASS (to_mode) == MODE_POINTER)
     {
       enum machine_mode full_mode
 	= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
@@ -495,7 +496,8 @@  convert_move (rtx to, rtx from, int unsi
 		      to, from, UNKNOWN);
       return;
     }
-  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT)
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT
+      || GET_MODE_CLASS (from_mode) == MODE_POINTER)
     {
       rtx new_from;
       enum machine_mode full_mode
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	(revision 365109)
+++ gcc/recog.c	(working copy)
@@ -920,7 +920,8 @@  general_operand (rtx op, enum machine_mo
      if the caller wants something floating.  */
   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
       && GET_MODE_CLASS (mode) != MODE_INT
-      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
+      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT
+      && GET_MODE_CLASS (mode) != MODE_POINTER)
     return 0;
 
   if (CONST_INT_P (op)
@@ -1097,7 +1098,8 @@  immediate_operand (rtx op, enum machine_
      if the caller wants something floating.  */
   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
       && GET_MODE_CLASS (mode) != MODE_INT
-      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
+      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT
+      && GET_MODE_CLASS (mode) != MODE_POINTER)
     return 0;
 
   if (CONST_INT_P (op)
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 365246)
+++ gcc/stor-layout.c	(working copy)
@@ -484,6 +484,7 @@  int_mode_for_mode (enum machine_mode mod
     case MODE_VECTOR_ACCUM:
     case MODE_VECTOR_UFRACT:
     case MODE_VECTOR_UACCUM:
+    case MODE_POINTER:
       mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
       break;
 
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(revision 365109)
+++ gcc/genmodes.c	(working copy)
@@ -353,6 +353,7 @@  complete_mode (struct mode_data *m)
       break;
 
     case MODE_INT:
+    case MODE_POINTER:
     case MODE_FLOAT:
     case MODE_DECIMAL_FLOAT:
     case MODE_FRACT:
@@ -569,6 +570,19 @@  make_int_mode (const char *name,
   m->bytesize = bytesize;
   m->precision = precision;
 }
+
+#define POINTER_MODE(N, B, Y) \
+  make_pointer_mode (#N, B, Y, __FILE__, __LINE__)
+
+static void
+make_pointer_mode (const char *name,
+		   unsigned int precision, unsigned int bytesize,
+		   const char *file, unsigned int line)
+{
+  struct mode_data *m = new_mode (MODE_POINTER, name, file, line);
+  m->bytesize = bytesize;
+  m->precision = precision;
+}
 
 #define FRACT_MODE(N, Y, F) \
 	make_fixed_point_mode (MODE_FRACT, #N, Y, 0, F, __FILE__, __LINE__)
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	(revision 365245)
+++ gcc/emit-rtl.c	(working copy)
@@ -542,6 +542,7 @@  immed_double_const (HOST_WIDE_INT i0, HO
     {
       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
 		  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+		  || GET_MODE_CLASS (mode) == MODE_POINTER
 		  /* We can get a 0 for an error mark.  */
 		  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
 		  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 365109)
+++ gcc/simplify-rtx.c	(working copy)
@@ -5070,6 +5070,7 @@  simplify_immed_subreg (enum machine_mode
 	{
 	case MODE_INT:
 	case MODE_PARTIAL_INT:
+	case MODE_POINTER:
 	  {
 	    unsigned HOST_WIDE_INT hi = 0, lo = 0;
 
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(revision 365245)
+++ gcc/explow.c	(working copy)
@@ -53,7 +53,7 @@  trunc_int_for_mode (HOST_WIDE_INT c, enu
   int width = GET_MODE_BITSIZE (mode);
 
   /* You want to truncate to a _what_?  */
-  gcc_assert (SCALAR_INT_MODE_P (mode));
+  gcc_assert (SCALAR_INT_MODE_P (mode) || POINTER_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
   if (mode == BImode)