Add scalar_mode_supported_p target hook

Richard Henderson rth@redhat.com
Thu Aug 26 01:15:00 GMT 2004


I plan on using this new hook in the Fortran front end in deciding which
types the front end should make available to the programmer.


r~


        * target-def.h (TARGET_SCALAR_MODE_SUPPORTED_P): New.
        * target.h (struct gcc_target): Add scalar_mode_supported_p.
        * targhooks.c (default_scalar_mode_supported_p): New.
        * targhooks.h (default_scalar_mode_supported_p): Declare.
        * doc/tm.texi (TARGET_SCALAR_MODE_SUPPORTED_P): Document.
                                                                                
        * c-common.c (handle_mode_attribute): Query scalar_mode_supported_p
        before attempting to create types.  Tidy.
        * expr.c (vector_mode_valid_p): Use scalar_mode_supported_p.
                                                                                
        * config/alpha/alpha.c (alpha_scalar_mode_supported_p): New.
        (TARGET_SCALAR_MODE_SUPPORTED_P): New.

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.558
diff -c -p -d -r1.558 c-common.c
*** gcc/c-common.c	25 Aug 2004 09:51:18 -0000	1.558
--- gcc/c-common.c	26 Aug 2004 00:10:55 -0000
*************** handle_mode_attribute (tree *node, tree 
*** 4267,4273 ****
        int len = strlen (p);
        enum machine_mode mode = VOIDmode;
        tree typefm;
!       tree ptr_type;
  
        if (len > 4 && p[0] == '_' && p[1] == '_'
  	  && p[len - 1] == '_' && p[len - 2] == '_')
--- 4267,4273 ----
        int len = strlen (p);
        enum machine_mode mode = VOIDmode;
        tree typefm;
!       bool valid_mode;
  
        if (len > 4 && p[0] == '_' && p[1] == '_'
  	  && p[len - 1] == '_' && p[len - 2] == '_')
*************** handle_mode_attribute (tree *node, tree 
*** 4294,4344 ****
  
        if (mode == VOIDmode)
  	{
! 	  error ("unknown machine mode `%s'", p);
  	  return NULL_TREE;
  	}
  
!       if (VECTOR_MODE_P (mode))
  	{
  	  warning ("specifying vector types with __attribute__ ((mode)) "
  		   "is deprecated");
  	  warning ("use __attribute__ ((vector_size)) instead");
! 	}
  
!       typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
!       if (typefm == NULL_TREE)
! 	error ("no data type for mode `%s'", p);
  
!       else if ((TREE_CODE (type) == POINTER_TYPE
! 		|| TREE_CODE (type) == REFERENCE_TYPE)
! 	       && !targetm.valid_pointer_mode (mode))
! 	error ("invalid pointer mode `%s'", p);
!       else
  	{
! 	  /* If this is a vector, make sure we either have hardware
! 	     support, or we can emulate it.  */
! 	  if (VECTOR_MODE_P (mode) && !vector_mode_valid_p (mode))
  	    {
! 	      error ("unable to emulate '%s'", GET_MODE_NAME (mode));
  	      return NULL_TREE;
  	    }
  
! 	  if (TREE_CODE (type) == POINTER_TYPE)
! 	    {
! 	      ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
! 						      mode, false);
! 	      *node = ptr_type;
! 	    }
! 	  else if (TREE_CODE (type) == REFERENCE_TYPE)
! 	    {
! 	      ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
! 							mode, false);
! 	      *node = ptr_type;
! 	    }
  	  else
! 	    *node = typefm;
! 	  /* No need to layout the type here.  The caller should do this.  */
  	}
      }
  
    return NULL_TREE;
--- 4294,4360 ----
  
        if (mode == VOIDmode)
  	{
! 	  error ("unknown machine mode %<%s%>", p);
  	  return NULL_TREE;
  	}
  
!       valid_mode = false;
!       switch (GET_MODE_CLASS (mode))
  	{
+ 	case MODE_INT:
+ 	case MODE_PARTIAL_INT:
+ 	case MODE_FLOAT:
+ 	  valid_mode = targetm.scalar_mode_supported_p (mode);
+ 	  break;
+ 
+ 	case MODE_COMPLEX_INT:
+ 	case MODE_COMPLEX_FLOAT:
+ 	  valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
+ 	  break;
+ 
+ 	case MODE_VECTOR_INT:
+ 	case MODE_VECTOR_FLOAT:
  	  warning ("specifying vector types with __attribute__ ((mode)) "
  		   "is deprecated");
  	  warning ("use __attribute__ ((vector_size)) instead");
! 	  valid_mode = vector_mode_valid_p (mode);
! 	  break;
  
! 	default:
! 	  break;
! 	}
!       if (!valid_mode)
! 	{
! 	  error ("unable to emulate %<%s%>", p);
! 	  return NULL_TREE;
! 	}
  
!       if (POINTER_TYPE_P (type))
  	{
! 	  tree (*fn)(tree, enum machine_mode, bool);
! 
! 	  if (!targetm.valid_pointer_mode (mode))
  	    {
! 	      error ("invalid pointer mode %<%s%>", p);
  	      return NULL_TREE;
  	    }
  
!           if (TREE_CODE (type) == POINTER_TYPE)
! 	    fn = build_pointer_type_for_mode;
  	  else
! 	    fn = build_reference_type_for_mode;
! 	  typefm = fn (TREE_TYPE (type), mode, false);
  	}
+       else
+         typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+       if (typefm == NULL_TREE)
+ 	{
+ 	  error ("no data type for mode %<%s%>", p);
+ 	  return NULL_TREE;
+ 	}
+       *node = typefm;
+ 
+       /* No need to layout the type here.  The caller should do this.  */
      }
  
    return NULL_TREE;
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.710
diff -c -p -d -r1.710 expr.c
*** gcc/expr.c	25 Aug 2004 09:51:24 -0000	1.710
--- gcc/expr.c	26 Aug 2004 00:10:56 -0000
*************** vector_mode_valid_p (enum machine_mode m
*** 8799,8805 ****
  
    /* If we have support for the inner mode, we can safely emulate it.
       We may not have V2DI, but me can emulate with a pair of DIs.  */
!   return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
  }
  
  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
--- 8799,8805 ----
  
    /* If we have support for the inner mode, we can safely emulate it.
       We may not have V2DI, but me can emulate with a pair of DIs.  */
!   return targetm.scalar_mode_supported_p (innermode);
  }
  
  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
Index: gcc/target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.97
diff -c -p -d -r1.97 target-def.h
*** gcc/target-def.h	24 Aug 2004 00:30:46 -0000	1.97
--- gcc/target-def.h	26 Aug 2004 00:10:56 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 305,310 ****
--- 305,314 ----
  #define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
  #endif
  
+ #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
+ #define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
+ #endif
+ 
  #ifndef TARGET_VECTOR_MODE_SUPPORTED_P
  #define TARGET_VECTOR_MODE_SUPPORTED_P hook_bool_mode_false
  #endif
*************** Foundation, 59 Temple Place - Suite 330,
*** 475,480 ****
--- 479,485 ----
    TARGET_ENCODE_SECTION_INFO,			\
    TARGET_STRIP_NAME_ENCODING,			\
    TARGET_VALID_POINTER_MODE,                    \
+   TARGET_SCALAR_MODE_SUPPORTED_P,		\
    TARGET_VECTOR_MODE_SUPPORTED_P,               \
    TARGET_VECTOR_OPAQUE_P,			\
    TARGET_RTX_COSTS,				\
Index: gcc/target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.108
diff -c -p -d -r1.108 target.h
*** gcc/target.h	24 Aug 2004 00:30:46 -0000	1.108
--- gcc/target.h	26 Aug 2004 00:10:56 -0000
*************** struct gcc_target
*** 381,387 ****
    /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
    bool (* valid_pointer_mode) (enum machine_mode mode);
  
!   /* True if MODE is valid for a vector.  */
    bool (* vector_mode_supported_p) (enum machine_mode mode);
  
    /* True if a vector is opaque.  */
--- 381,394 ----
    /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
    bool (* valid_pointer_mode) (enum machine_mode mode);
  
!   /* True if MODE is valid for the target.  By "valid", we mean able to
!      be manipulated in non-trivial ways.  In particular, this means all
!      the arithmetic is supported.  */
!   bool (* scalar_mode_supported_p) (enum machine_mode mode);
! 
!   /* Similarly for vector modes.  "Supported" here is less strict.  At
!      least some operations are supported; need to check optabs or builtins
!      for further details.  */
    bool (* vector_mode_supported_p) (enum machine_mode mode);
  
    /* True if a vector is opaque.  */
Index: gcc/targhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.c,v
retrieving revision 2.26
diff -c -p -d -r2.26 targhooks.c
*** gcc/targhooks.c	16 Aug 2004 20:08:31 -0000	2.26
--- gcc/targhooks.c	26 Aug 2004 00:10:56 -0000
*************** Software Foundation, 59 Temple Place - S
*** 62,67 ****
--- 62,68 ----
  #include "tm_p.h"
  #include "target-def.h"
  
+ 
  void
  default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
  {
*************** default_unwind_emit (FILE * stream ATTRI
*** 207,209 ****
--- 208,256 ----
    /* Should never happen.  */
    abort ();
  }
+ 
+ /* True if MODE is valid for the target.  By "valid", we mean able to
+    be manipulated in non-trivial ways.  In particular, this means all
+    the arithmetic is supported.
+ 
+    By default we guess this means that any C type is supported.  If
+    we can't map the mode back to a type that would be available in C,
+    then reject it.  Special case, here, is the double-word arithmetic
+    supported by optabs.c.  */
+ 
+ bool
+ default_scalar_mode_supported_p (enum machine_mode mode)
+ {
+   int precision = GET_MODE_PRECISION (mode);
+ 
+   switch (GET_MODE_CLASS (mode))
+     {
+     case MODE_PARTIAL_INT:
+     case MODE_INT:
+       if (precision == CHAR_TYPE_SIZE)
+ 	return true;
+       if (precision == SHORT_TYPE_SIZE)
+ 	return true;
+       if (precision == INT_TYPE_SIZE)
+ 	return true;
+       if (precision == LONG_TYPE_SIZE)
+ 	return true;
+       if (precision == LONG_LONG_TYPE_SIZE)
+ 	return true;
+       if (precision == 2 * BITS_PER_WORD)
+ 	return true;
+       return false;
+ 
+     case MODE_FLOAT:
+       if (precision == FLOAT_TYPE_SIZE)
+ 	return true;
+       if (precision == DOUBLE_TYPE_SIZE)
+ 	return true;
+       if (precision == LONG_DOUBLE_TYPE_SIZE)
+ 	return true;
+       return false;
+ 
+     default:
+       abort ();
+     }
+ }
Index: gcc/targhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.h,v
retrieving revision 2.17
diff -c -p -d -r2.17 targhooks.h
*** gcc/targhooks.h	16 Aug 2004 20:08:31 -0000	2.17
--- gcc/targhooks.h	26 Aug 2004 00:10:56 -0000
*************** extern bool hook_pass_by_reference_must_
*** 43,45 ****
--- 43,47 ----
    (CUMULATIVE_ARGS *, enum machine_mode mode, tree, bool);
  
  extern void default_unwind_emit (FILE *, rtx);
+ 
+ extern bool default_scalar_mode_supported_p (enum machine_mode);
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.389
diff -c -p -d -r1.389 alpha.c
*** gcc/config/alpha/alpha.c	25 Aug 2004 09:52:08 -0000	1.389
--- gcc/config/alpha/alpha.c	26 Aug 2004 00:10:56 -0000
*************** alpha_extra_constraint (rtx value, int c
*** 670,683 ****
      }
  }
  
! /* Implements target hook vector_mode_supported_p.  */
  static bool
  alpha_vector_mode_supported_p (enum machine_mode mode)
  {
    if (TARGET_MAX
!       && ((mode == V8QImode)
! 	  || (mode == V4HImode)
! 	  || (mode == V2SImode)))
      return true;
  
    return false;
--- 670,714 ----
      }
  }
  
! /* The scalar modes supported differs from the default check-what-c-supports
!    version in that sometimes TFmode is available even when long double
!    indicates only DFmode.  On unicosmk, we have the situation that HImode
!    doesn't map to any C type, but of course we still support that.  */
! 
! static bool
! alpha_scalar_mode_supported_p (enum machine_mode mode)
! {
!   switch (mode)
!     {
!     case QImode:
!     case HImode:
!     case SImode:
!     case DImode:
!     case TImode: /* via optabs.c */
!       return true;
! 
!     case SFmode:
!     case DFmode:
!       return true;
! 
!     case TFmode:
!       return TARGET_HAS_XFLOATING_LIBS;
! 
!     default:
!       return false;
!     }
! }
! 
! /* Alpha implements a couple of integer vector mode operations when
!    TARGET_MAX is enabled.  */
! 
  static bool
  alpha_vector_mode_supported_p (enum machine_mode mode)
  {
    if (TARGET_MAX
!       && (mode == V8QImode
! 	  || mode == V4HImode
! 	  || mode == V2SImode))
      return true;
  
    return false;
*************** alpha_init_libfuncs (void)
*** 9362,9367 ****
--- 9393,9401 ----
  #define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg
  #undef TARGET_GIMPLIFY_VA_ARG_EXPR
  #define TARGET_GIMPLIFY_VA_ARG_EXPR alpha_gimplify_va_arg
+ 
+ #undef TARGET_SCALAR_MODE_SUPPORTED_P
+ #define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
  #undef TARGET_VECTOR_MODE_SUPPORTED_P
  #define TARGET_VECTOR_MODE_SUPPORTED_P alpha_vector_mode_supported_p
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.358
diff -c -p -d -r1.358 tm.texi
*** doc/tm.texi	24 Aug 2004 00:30:52 -0000	1.358
--- doc/tm.texi	26 Aug 2004 00:21:35 -0000
*************** arguments to @code{va_arg}; the latter t
*** 3878,3883 ****
--- 3878,3895 ----
  @code{gimplify.c:gimplify_expr}.
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
+ Define this to return nonzero if the port is prepared to handle
+ insns involving scalar mode @var{mode}.  For a scalar mode to be
+ considered supported, all the basic arithmetic and comparisons
+ must work.
+ 
+ The default version of this hook returns true for any mode
+ required to handle the basic C types (as defined by the port).
+ Included here are the double-word arithmetic supported by the
+ code in @file{optabs.c}.
+ @end deftypefn
+ 
  @deftypefn {Target Hook} bool TARGET_VECTOR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
  Define this to return nonzero if the port is prepared to handle
  insns involving vector mode @var{mode}.  At the very least, it



More information about the Gcc-patches mailing list