From 6dd53648e913ea6ad55131ed0c8cc2709e9a3316 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 25 Aug 2004 17:24:37 -0700 Subject: [PATCH] target-def.h (TARGET_SCALAR_MODE_SUPPORTED_P): New. * 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. From-SVN: r86593 --- gcc/ChangeLog | 15 ++++++++ gcc/c-common.c | 76 ++++++++++++++++++++++++---------------- gcc/config/alpha/alpha.c | 42 +++++++++++++++++++--- gcc/doc/tm.texi | 12 +++++++ gcc/expr.c | 2 +- gcc/target-def.h | 5 +++ gcc/target.h | 9 ++++- gcc/targhooks.c | 47 +++++++++++++++++++++++++ gcc/targhooks.h | 2 ++ 9 files changed, 174 insertions(+), 36 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 36363d1148e..43d00b5fd39 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2004-08-25 Richard Henderson + + * 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. + 2004-08-25 Richard Henderson * config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Don't diff --git a/gcc/c-common.c b/gcc/c-common.c index 62d2231587f..7e691660ac4 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4267,7 +4267,7 @@ handle_mode_attribute (tree *node, tree name, tree args, int len = strlen (p); enum machine_mode mode = VOIDmode; tree typefm; - tree ptr_type; + bool valid_mode; if (len > 4 && p[0] == '_' && p[1] == '_' && p[len - 1] == '_' && p[len - 2] == '_') @@ -4294,51 +4294,67 @@ handle_mode_attribute (tree *node, tree name, tree args, if (mode == VOIDmode) { - error ("unknown machine mode `%s'", p); + error ("unknown machine mode %<%s%>", p); return NULL_TREE; } - if (VECTOR_MODE_P (mode)) + 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; - typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); - if (typefm == NULL_TREE) - error ("no data type for mode `%s'", p); + default: + break; + } + if (!valid_mode) + { + error ("unable to emulate %<%s%>", p); + return NULL_TREE; + } - 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 (POINTER_TYPE_P (type)) { - /* 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)) + tree (*fn)(tree, enum machine_mode, bool); + + if (!targetm.valid_pointer_mode (mode)) { - error ("unable to emulate '%s'", GET_MODE_NAME (mode)); + error ("invalid pointer mode %<%s%>", p); 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; - } + if (TREE_CODE (type) == POINTER_TYPE) + fn = build_pointer_type_for_mode; else - *node = typefm; - /* No need to layout the type here. The caller should do this. */ + 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; diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index c623e009fb1..c6d93446a84 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -670,14 +670,45 @@ alpha_extra_constraint (rtx value, int c) } } -/* Implements target hook vector_mode_supported_p. */ +/* 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))) + && (mode == V8QImode + || mode == V4HImode + || mode == V2SImode)) return true; return false; @@ -9362,6 +9393,9 @@ alpha_init_libfuncs (void) #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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 7240d19e837..b15cb53dec6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3878,6 +3878,18 @@ arguments to @code{va_arg}; the latter two are as in @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 diff --git a/gcc/expr.c b/gcc/expr.c index b98986447f4..6811abedd80 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8799,7 +8799,7 @@ vector_mode_valid_p (enum machine_mode mode) /* 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 targetm.scalar_mode_supported_p (innermode); } /* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */ diff --git a/gcc/target-def.h b/gcc/target-def.h index 4d8fea0c8dd..156ebef7c7b 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -305,6 +305,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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 @@ -475,6 +479,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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, \ diff --git a/gcc/target.h b/gcc/target.h index 2c3798eaa5d..27e4086129e 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -381,7 +381,14 @@ struct gcc_target /* 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. */ + /* 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. */ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 00d7e8444d7..6aa2e07117b 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -62,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm_p.h" #include "target-def.h" + void default_external_libcall (rtx fun ATTRIBUTE_UNUSED) { @@ -207,3 +208,49 @@ default_unwind_emit (FILE * stream ATTRIBUTE_UNUSED, /* 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 (); + } +} diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 077175eda9d..b91e51dec84 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -43,3 +43,5 @@ extern bool hook_pass_by_reference_must_pass_in_stack (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); -- 2.30.2