public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] change specific int128 -> generic intN
@ 2014-04-14 23:03 DJ Delorie
  2014-04-15  5:54 ` Marc Glisse
                   ` (2 more replies)
  0 siblings, 3 replies; 49+ messages in thread
From: DJ Delorie @ 2014-04-14 23:03 UTC (permalink / raw)
  To: gcc-patches


[this time with patch]

This patch replaces the current int128 support with a generic intN
support, which happens to provide int128 as well as up to three
additional intN types per target.  I will post a separate patch for
the msp430 backend demonstrating the use of this new feature for
__int20, as well as a third to fix some problems with PSImode in
general.

The general idea is that genmodes has a new macro INT_N() for
<tm>-modes.def, which gives the mode and precision to use for
target-specific intN types.  These types are always created, but the
parser will error with "unsupported" if the target does not support
that mode for that compile (i.e. because of command line switches,
etc).  There's an INT_N(TI,128) in the common sources.

If the target defines any types larger than "long long", those types
(like int128 before) will be used for type promotion, but types
smaller than "long long" will not, to avoid confusing the C type
promotion rules.  Otherwise, it's up to the source being compiled to
specific __intN types as desired.

The only non-automatic part of this is the table of pre-computed
constants in builtin_define_type_minmax() (c-family/c-cppbuiltin.c).
I've added the entries for int20 and int24 but each target will need
to expand the table as needed.

gcc/

	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __intN for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.

gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Remove __int128-specific entries.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.

gcc/lto/
	* lto-lang.c (lto_build_c_type_nodes): Check intN types for
	size-type as well.
	(lto_init): Initialize all intN types, not just int128.


Index: machmode.h
===================================================================
--- machmode.h	(revision 209391)
+++ machmode.h	(working copy)
@@ -322,7 +322,19 @@ extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  unsigned int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+/* This is also in tree.h.  genmodes.c guarantees the're sorted from
+   smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: c-family/c-pretty-print.c
===================================================================
--- c-family/c-pretty-print.c	(revision 209391)
+++ c-family/c-pretty-print.c	(working copy)
@@ -907,12 +907,14 @@ pp_c_string_literal (c_pretty_printer *p
 
 /* Pretty-print an INTEGER literal.  */
 
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
+  int idx;
+
   /* We are going to compare the type of I to other types using
      pointer comparison so we need to use its canonical type.  */
   tree type =
     TYPE_CANONICAL (TREE_TYPE (i))
     ? TYPE_CANONICAL (TREE_TYPE (i))
     : TREE_TYPE (i);
@@ -939,15 +941,23 @@ pp_c_integer_constant (c_pretty_printer 
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
-  else if (type == int128_integer_type_node
-           || type == int128_unsigned_type_node)
-    pp_string (pp, "I128");
+  else for (idx = 0; idx < NUM_INT_N_ENTS; idx ++)
+    if (int_n_enabled_p[idx])
+      {
+	char buf[2+20];
+	if (type == int_n_trees[idx].signed_type
+	    || type == int_n_trees[idx].unsigned_type)
+	  {
+	    sprintf (buf, "I%d", int_n_data[idx].bitsize);
+	    pp_string (pp, buf);
+	  }
+      }
 }
 
 /* Print out a CHARACTER literal.  */
 
 static void
 pp_c_character_constant (c_pretty_printer *pp, tree c)
Index: c-family/c-cppbuiltin.c
===================================================================
--- c-family/c-cppbuiltin.c	(revision 209391)
+++ c-family/c-cppbuiltin.c	(working copy)
@@ -775,12 +775,14 @@ cpp_iec_559_complex_value (void)
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
 {
+  int i;
+
   /* -undef turns off target-specific built-ins.  */
   if (flag_undef)
     return;
 
   define_language_independent_builtin_macros (pfile);
 
@@ -993,15 +995,20 @@ c_cpp_builtins (cpp_reader *pfile)
   else if (flag_stack_protect == 1)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201307");
 
-  if (int128_integer_type_node != NULL_TREE)
-    builtin_define_type_sizeof ("__SIZEOF_INT128__",
-			        int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[15+20];
+	sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+	builtin_define_type_sizeof (buf,
+				    int_n_trees[i].signed_type);
+      }
   builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
   builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
   builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
 			      unsigned_ptrdiff_type_node);
 
   /* A straightforward target hook doesn't work, because of problems
@@ -1227,18 +1234,21 @@ builtin_define_with_hex_fp_value (const 
 static const char *
 type_suffix (tree type)
 {
   static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
   int unsigned_suffix;
   int is_long;
+  int tp = TYPE_PRECISION (type);
 
   if (type == long_long_integer_type_node
-      || type == long_long_unsigned_type_node)
+      || type == long_long_unsigned_type_node
+      || tp > TYPE_PRECISION (long_integer_type_node))
     is_long = 2;
   else if (type == long_integer_type_node
-	   || type == long_unsigned_type_node)
+	   || type == long_unsigned_type_node
+	   || tp > TYPE_PRECISION (integer_type_node))
     is_long = 1;
   else if (type == integer_type_node
 	   || type == unsigned_type_node
 	   || type == short_integer_type_node
 	   || type == short_unsigned_type_node
 	   || type == signed_char_type_node
@@ -1298,29 +1308,32 @@ builtin_define_type_minmax (const char *
   static const char *const values[]
     = { "127", "255",
 	"32767", "65535",
 	"2147483647", "4294967295",
 	"9223372036854775807", "18446744073709551615",
 	"170141183460469231731687303715884105727",
-	"340282366920938463463374607431768211455" };
+	"340282366920938463463374607431768211455",
+	"524287", "1048575",
+	"8388607", "16777215",
+  };
 
   const char *value, *suffix;
   char *buf;
   size_t idx;
 
   /* Pre-rendering the values mean we don't have to futz with printing a
-     multi-word decimal value.  There are also a very limited number of
-     precisions that we support, so it's really a waste of time.  */
+     multi-word decimal value.  */
   switch (TYPE_PRECISION (type))
     {
     case 8:	idx = 0; break;
     case 16:	idx = 2; break;
     case 32:	idx = 4; break;
     case 64:	idx = 6; break;
     case 128:	idx = 8; break;
-    default:    gcc_unreachable ();
+    case 20:    idx = 10; break;
+    default:	gcc_unreachable ();
     }
 
   value = values[idx + TYPE_UNSIGNED (type)];
   suffix = type_suffix (type);
 
   buf = (char *) alloca (strlen (max_macro) + 1 + strlen (value)
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 209391)
+++ c-family/c-common.c	(working copy)
@@ -57,18 +57,16 @@ cpp_reader *parse_in;		/* Declared in c-
 
    INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
 
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
-	tree int128_integer_type_node;
 
 	tree short_unsigned_type_node;
 	tree long_unsigned_type_node;
 	tree long_long_unsigned_type_node;
-	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
 	tree truthvalue_false_node;
 	tree truthvalue_true_node;
 
 	tree ptrdiff_type_node;
@@ -460,13 +458,12 @@ const struct c_common_resword c_common_r
   { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
   { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
-  { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
   { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
@@ -3395,12 +3392,14 @@ check_case_bounds (tree type, tree orig_
 /* Return an integer type with BITS bits of precision,
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 tree
 c_common_type_for_size (unsigned int bits, int unsignedp)
 {
+  int i;
+
   if (bits == TYPE_PRECISION (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (bits == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 
@@ -3411,16 +3410,17 @@ c_common_type_for_size (unsigned int bit
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (bits == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
-  if (int128_integer_type_node
-      && bits == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& bits == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
   if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -3478,12 +3478,13 @@ static GTY(()) tree registered_builtin_t
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
+  int i;
 
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -3494,15 +3495,17 @@ c_common_type_for_mode (enum machine_mod
   if (mode == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
-  if (int128_integer_type_node
-      && mode == TYPE_MODE (int128_integer_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& mode == int_n_data[i].m)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
 		     : widest_integer_literal_type_node;
 
   if (mode == QImode)
@@ -3694,12 +3697,13 @@ c_common_signed_type (tree type)
    signed according to UNSIGNEDP.  */
 
 tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   /* This block of code emulates the behavior of the old
      c_common_unsigned_type. In particular, it returns
      long_unsigned_type_node if passed a long, even when a int would
      have the same size. This is necessary for warnings to work
      correctly in archs where sizeof(int) == sizeof(long) */
@@ -3712,16 +3716,20 @@ c_common_signed_or_unsigned_type (int un
   if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
-  if (int128_integer_type_node
-      && (type1 == int128_integer_type_node
-	  || type1 == int128_unsigned_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
     return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3830,15 +3838,20 @@ c_common_signed_or_unsigned_type (int un
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -3859,12 +3872,14 @@ c_common_signed_or_unsigned_type (int un
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 
 tree
 c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
 {
+  int i;
+
   /* Extended integer types of the same width as a standard type have
      lesser rank, so those of the same width as int promote to int or
      unsigned int and are valid for printf formats expecting int or
      unsigned int.  To avoid such special cases, avoid creating
      extended integer types for bit-fields if a standard integer type
      is available.  */
@@ -3876,16 +3891,17 @@ c_build_bitfield_integer_type (unsigned 
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (width == TYPE_PRECISION (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node
-      && width == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& width == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -5292,12 +5308,13 @@ c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5308,19 +5325,25 @@ c_common_nodes_and_builtins (void)
   if (c_dialect_cxx ())
     record_builtin_type (RID_SIGNED, NULL, integer_type_node);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
-  if (int128_integer_type_node != NULL_TREE)
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
     {
-      record_builtin_type (RID_INT128, "__int128",
-			   int128_integer_type_node);
-      record_builtin_type (RID_MAX, "__int128 unsigned",
-			   int128_unsigned_type_node);
+      char name[25];
+
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), xstrdup (name),
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, xstrdup (name),
+			   int_n_trees[i].unsigned_type);
     }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -5350,12 +5373,14 @@ c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intSI_type_node));
   lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  /* Note that this is different than the __int128 type that's part of
+     the generic __intN support.  */
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
 					   get_identifier ("__int128_t"),
 					   intTI_type_node));
 #endif
@@ -11632,13 +11657,12 @@ keyword_begins_type_specifier (enum rid 
     case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-    case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
     case RID_SHORT:
     case RID_SIGNED:
     case RID_DFLOAT32:
     case RID_DFLOAT64:
@@ -11655,12 +11679,16 @@ keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 209391)
+++ c-family/c-common.h	(working copy)
@@ -88,13 +88,12 @@ enum rid
   /* C (reserved and imaginary types not implemented, so any use is a
      syntax error) */
   RID_IMAGINARY,
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
   RID_ENUM,    RID_STRUCT, RID_UNION,    RID_IF,     RID_ELSE,
   RID_WHILE,   RID_DO,     RID_FOR,      RID_SWITCH, RID_CASE,
   RID_DEFAULT, RID_BREAK,  RID_CONTINUE, RID_RETURN, RID_GOTO,
   RID_SIZEOF,
 
   /* C extensions */
@@ -185,12 +184,29 @@ enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN_t keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13_t.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: c/c-parser.c
===================================================================
--- c/c-parser.c	(revision 209391)
+++ c/c-parser.c	(working copy)
@@ -109,12 +109,22 @@ c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      /* We always create the symbols but they aren't always supported.  */
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (xstrdup (name));
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 \f
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -484,13 +494,12 @@ c_token_starts_typename (c_token *token)
 	}
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -512,12 +521,16 @@ c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -642,13 +655,12 @@ c_token_starts_declspecs (c_token *token
 	case RID_INLINE:
 	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -671,12 +683,16 @@ c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2136,13 +2152,13 @@ c_parser_static_assert_declaration_no_se
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
      __auto_type
-     __int128
+     __intN
      _Decimal32
      _Decimal64
      _Decimal128
      _Fract
      _Accum
      _Sat
@@ -2290,13 +2306,12 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_AUTO_TYPE:
 	  if (!auto_type_ok)
 	    goto out;
 	  /* Fall through.  */
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -2306,12 +2321,16 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3726,13 +3745,12 @@ c_parser_attribute_any_word (c_parser *p
       bool ok;
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_SHORT:
 	case RID_INLINE:
@@ -3756,12 +3774,16 @@ c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8897,13 +8919,12 @@ c_parser_objc_selector (c_parser *parser
     case RID_ASM:
     case RID_SIZEOF:
     case RID_TYPEOF:
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
-    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
     case RID_SIGNED:
     case RID_RESTRICT:
     case RID_COMPLEX:
@@ -8918,12 +8939,16 @@ c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: c/c-tree.h
===================================================================
--- c/c-tree.h	(revision 209391)
+++ c/c-tree.h	(working copy)
@@ -196,13 +196,13 @@ enum c_typespec_keyword {
   cts_none,
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
-  cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -263,12 +263,14 @@ struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 209391)
+++ c/c-decl.c	(working copy)
@@ -9147,16 +9147,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<long%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		  error_at (loc,
-			    ("both %<long%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<long%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<long%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9195,16 +9196,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<short%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		error_at (loc,
-			  ("both %<short%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<short%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<short%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9372,17 +9374,18 @@ declspecs_add_type (location_t loc, stru
 		}
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
 	      pedwarn (loc, OPT_Wpedantic,
 		       "ISO C does not support saturating types");
-	      if (specs->typespec_word == cts_int128)
+	      if (specs->typespec_word == cts_int_n)
 	        {
 		  error_at (loc,
-			    ("both %<_Sat%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<_Sat%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	        }
 	      else if (specs->typespec_word == cts_auto_type)
 		error_at (loc,
 			  ("both %<_Sat%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
@@ -9440,13 +9443,13 @@ declspecs_add_type (location_t loc, stru
 
 	  return specs;
 	}
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+	     "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
 	     "__auto_type".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
 			"two or more data types in declaration specifiers");
 	      return specs;
@@ -9481,37 +9484,44 @@ declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_auto_type;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
-	    case RID_INT128:
-	      if (int128_integer_type_node == NULL_TREE)
-		{
-		  error_at (loc, "%<__int128%> is not supported for this target");
-		  return specs;
-		}
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      specs->int_n_idx = i - RID_INT_N_0;
 	      if (!in_system_header_at (input_location))
 		pedwarn (loc, OPT_Wpedantic,
-			 "ISO C does not support %<__int128%> type");
+			 "ISO C does not support %<__int%d%> types",
+			 int_n_data[specs->int_n_idx].bitsize);
 
 	      if (specs->long_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<long%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<long%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->saturating_p)
 		error_at (loc,
-			  ("both %<_Sat%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<_Sat%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->short_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<short%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<short%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
+	      else if (! int_n_enabled_p [specs->int_n_idx])
+		error_at (loc,
+			  "%<__int%d%> is not supported on this target",
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else
 		{
-		  specs->typespec_word = cts_int128;
+		  specs->typespec_word = cts_int_n;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
@@ -10070,18 +10080,18 @@ finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
-    case cts_int128:
+    case cts_int_n:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       specs->type = (specs->unsigned_p
-		     ? int128_unsigned_type_node
-		     : int128_integer_type_node);
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
       if (specs->complex_p)
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
Index: tree.c
===================================================================
--- tree.c	(revision 209391)
+++ tree.c	(working copy)
@@ -236,12 +236,15 @@ static unsigned int type_hash_list (cons
 static unsigned int attribute_hash_list (const_tree, hashval_t);
 static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+bool int_n_enabled_p[NUM_INT_N_ENTS];
+int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9436,26 +9439,31 @@ make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (size == LONG_TYPE_SIZE)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
-  if (size == 128 && int128_integer_type_node)
-    return (unsignedp ? int128_unsigned_type_node
-            : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize
+	&& int_n_enabled_p[i])
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
@@ -9565,12 +9573,14 @@ build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9592,23 +9602,26 @@ build_common_tree_nodes (bool signed_cha
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-#if HOST_BITS_PER_WIDE_INT >= 64
-    /* TODO: This isn't correct, but as logic depends at the moment on
-       host's instead of target's wide-integer.
-       If there is a target not supporting TImode, but has an 128-bit
-       integer-scalar register, this target check needs to be adjusted. */
-    if (targetm.scalar_mode_supported_p (TImode))
-      {
-        int128_integer_type_node = make_signed_type (128);
-        int128_unsigned_type_node = make_unsigned_type (128);
-      }
-#endif
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+      int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+
+      if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE)
+	{
+	  integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
+	  integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
+	}
+    }
 
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.
      Front ends which want to override this size (i.e. Java) can redefine
      boolean_type_node before calling build_common_tree_nodes_2.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
@@ -9623,13 +9636,30 @@ build_common_tree_nodes (bool signed_cha
     size_type_node = long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
     size_type_node = long_long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
     size_type_node = short_unsigned_type_node;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		size_type_node = int_n_trees[i].signed_type;
+	      }
+	  }
+      if (size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
      when possible.  */
   intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
   intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
   intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
Index: tree.h
===================================================================
--- tree.h	(revision 209391)
+++ tree.h	(working copy)
@@ -3382,14 +3382,12 @@ tree_operand_check_code (const_tree __t,
 #define integer_type_node		integer_types[itk_int]
 #define unsigned_type_node		integer_types[itk_unsigned_int]
 #define long_integer_type_node		integer_types[itk_long]
 #define long_unsigned_type_node		integer_types[itk_unsigned_long]
 #define long_long_integer_type_node	integer_types[itk_long_long]
 #define long_long_unsigned_type_node	integer_types[itk_unsigned_long_long]
-#define int128_integer_type_node	integer_types[itk_int128]
-#define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
 #define NULL_TREE (tree) NULL
 
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\
@@ -4581,7 +4579,18 @@ extern unsigned int get_pointer_alignmen
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
 extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
 extern bool is_simple_builtin (tree);
 extern bool is_inexpensive_builtin (tree);
 
+
+typedef struct {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+} int_n_trees_t;
+
+/* This is also in machmode.h */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: toplev.c
===================================================================
--- toplev.c	(revision 209391)
+++ toplev.c	(working copy)
@@ -1867,12 +1867,24 @@ finalize (bool no_backend)
     dump_profile_report ();
 
   /* Language-specific end of compilation actions.  */
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || (bitsize == LONG_LONG_TYPE_SIZE && LONG_LONG_TYPE_SIZE < GET_MODE_BITSIZE (TImode)))
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
 do_compile (void)
 {
   /* Initialize timing first.  The C front ends read the main file in
      the post_options hook, and C++ does file timings.  */
@@ -1882,19 +1894,32 @@ do_compile (void)
 
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
 	 predefined macros, such as __LDBL_MAX__, for targets using non
 	 default FP formats.  */
       init_adjust_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize)
+	    && int_n_data[i].bitsize <= HOST_BITS_PER_WIDE_INT * 2)
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
 	backend_init ();
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 209391)
+++ cp/typeck.c	(working copy)
@@ -267,12 +267,13 @@ original_type (tree t)
 static tree
 cp_common_type (tree t1, tree t2)
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
   tree attributes;
+  int i;
 
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -361,22 +362,25 @@ cp_common_type (tree t1, tree t2)
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
-      if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
 	{
-	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-		    ? int128_unsigned_type_node
-		    : int128_integer_type_node);
-	  return build_type_attribute_variant (t, attributes);
+	  if (int_n_enabled_p [i]
+	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			       int_n_trees[i].signed_type)
+		  || same_type_p (TYPE_MAIN_VARIANT (t2),
+				  int_n_trees[i].signed_type)))
+	    {
+	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+			? int_n_trees[i].unsigned_type
+			: int_n_trees[i].signed_type);
+	      return build_type_attribute_variant (t, attributes);
+	    }
 	}
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
 	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 209391)
+++ cp/decl.c	(working copy)
@@ -8713,13 +8713,13 @@ grokdeclarator (const cp_declarator *dec
 		enum decl_context decl_context,
 		int initialized,
 		tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int explicit_int128 = 0;
+  int explicit_intN = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
 
   tree typedef_decl = NULL_TREE;
@@ -8784,13 +8784,13 @@ grokdeclarator (const cp_declarator *dec
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
   short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
-  explicit_int128 = declspecs->explicit_int128_p;
+  explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
     funcdef_flag = true, decl_context = FIELD;
@@ -9125,22 +9125,24 @@ grokdeclarator (const cp_declarator *dec
 
       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
 
-  if (explicit_int128)
+  if (explicit_intN)
     {
-      if (int128_integer_type_node == NULL_TREE)
-	{
-	  error ("%<__int128%> is not supported by this target");
-	  explicit_int128 = false;
-	}
+      if (! int_n_enabled_p[declspecs->int_n_idx])
+       {
+         error ("%<__int%d%> is not supported by this target",
+		int_n_data[declspecs->int_n_idx].bitsize);
+         explicit_intN = false;
+       }
       else if (pedantic && ! in_system_header_at (input_location))
-	pedwarn (input_location, OPT_Wpedantic,
-		 "ISO C++ does not support %<__int128%> for %qs", name);
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ does not support %<__int%d%> for %qs",
+		int_n_data[declspecs->int_n_idx].bitsize,  name);
     }
 
   /* Now process the modifiers that were specified
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
@@ -9166,13 +9168,13 @@ grokdeclarator (const cp_declarator *dec
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
       else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
-      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
       else if (long_p && short_p)
 	error ("%<long%> and %<short%> specified together for %qs", name);
       else if (type == char16_type_node || type == char32_type_node)
@@ -9182,13 +9184,13 @@ grokdeclarator (const cp_declarator *dec
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
 		       name);
 	      if (flag_pedantic_errors)
 		ok = 0;
@@ -9224,14 +9226,14 @@ grokdeclarator (const cp_declarator *dec
 	     `signed int' cannot be so controlled.  */
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
-	type = int128_unsigned_type_node;
+      if (explicit_intN)
+	type = int_n_trees[declspecs->int_n_idx].unsigned_type;
       else if (longlong)
 	type = long_long_unsigned_type_node;
       else if (long_p)
 	type = long_unsigned_type_node;
       else if (short_p)
 	type = short_unsigned_type_node;
@@ -9241,14 +9243,14 @@ grokdeclarator (const cp_declarator *dec
 	type = unsigned_type_for (type);
       else
 	type = unsigned_type_node;
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
-  else if (explicit_int128)
-    type = int128_integer_type_node;
+  else if (explicit_intN)
+    type = int_n_trees[declspecs->int_n_idx].signed_type;
   else if (longlong)
     type = long_long_integer_type_node;
   else if (long_p)
     type = long_integer_type_node;
   else if (short_p)
     type = short_integer_type_node;
@@ -9258,13 +9260,13 @@ grokdeclarator (const cp_declarator *dec
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
 	error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
 	 "complex double", but if any modifiers at all are specified it is
 	 the complex form of TYPE.  E.g, "complex short" is
 	 "complex short int".  */
-      else if (defaulted_int && ! longlong && ! explicit_int128
+      else if (defaulted_int && ! longlong && ! explicit_intN
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
 	type = complex_integer_type_node;
       else if (type == float_type_node)
 	type = complex_float_type_node;
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 209391)
+++ cp/rtti.c	(working copy)
@@ -1483,13 +1483,13 @@ emit_support_tinfos (void)
     &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
-    &int128_integer_type_node, &int128_unsigned_type_node,
+    //    &int128_integer_type_node, &int128_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
     &nullptr_type_node,
     0
   };
   int ix;
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 209391)
+++ cp/parser.c	(working copy)
@@ -936,13 +936,12 @@ cp_lexer_next_token_is_decl_specifier_ke
     case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
-    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
       /* GNU extensions.  */ 
@@ -951,12 +950,16 @@ cp_lexer_next_token_is_decl_specifier_ke
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
       return true;
 
     default:
+      if (token->keyword >= RID_FIRST_INT_N
+	  && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Returns TRUE iff the token T begins a decltype type.  */
 
@@ -14470,12 +14473,13 @@ static tree
 cp_parser_simple_type_specifier (cp_parser* parser,
 				 cp_decl_specifier_seq *decl_specs,
 				 cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
+  int idx;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* If we're looking at a keyword, things are easy.  */
   switch (token->keyword)
@@ -14503,18 +14507,25 @@ cp_parser_simple_type_specifier (cp_pars
       break;
     case RID_INT:
       if (decl_specs)
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
-    case RID_INT128:
-      if (!int128_integer_type_node)
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
+      idx = token->keyword - RID_INT_N_0;
+      if (! int_n_enabled_p [idx])
 	break;
       if (decl_specs)
-        decl_specs->explicit_int128_p = true;
-      type = int128_integer_type_node;
+	{
+	  decl_specs->explicit_intN_p = true;
+	  decl_specs->int_n_idx = idx;
+	}
+      type = int_n_trees [idx].signed_type;
       break;
     case RID_LONG:
       if (decl_specs)
 	set_and_check_decl_spec_loc (decl_specs, ds_long, token);
       type = long_integer_type_node;
       break;
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 209391)
+++ cp/mangle.c	(working copy)
@@ -149,14 +149,12 @@ integer_type_codes[itk_none] =
   'i',  /* itk_int */
   'j',  /* itk_unsigned_int */
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
-  'n',  /* itk_int128 */
-  'o',  /* itk_unsigned_int128  */
 };
 
 static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 209391)
+++ cp/cp-tree.h	(working copy)
@@ -4840,12 +4840,14 @@ typedef struct cp_decl_specifier_seq {
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
   /* True iff multiple storage classes were (erroneously) specified
@@ -4855,14 +4857,14 @@ typedef struct cp_decl_specifier_seq {
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
   /* True iff at least one type-specifier was found.  */
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
-  /* True iff "__int128" was explicitly provided.  */
-  BOOL_BITFIELD explicit_int128_p : 1;
+  /* True iff "__intN" was explicitly provided.  */
+  BOOL_BITFIELD explicit_intN_p : 1;
   /* True iff "char" was explicitly provided.  */
   BOOL_BITFIELD explicit_char_p : 1;
   /* True iff ds_thread is set for __thread, not thread_local.  */
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
 } cp_decl_specifier_seq;
 
Index: cp/lex.c
===================================================================
--- cp/lex.c	(revision 209391)
+++ cp/lex.c	(working copy)
@@ -190,12 +190,21 @@ init_reswords (void)
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
       if (! (c_common_reswords[i].disable & mask))
 	C_IS_RESERVED_WORD (id) = 1;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 static void
 init_cp_pragma (void)
 {
   c_register_pragma (0, "vtable", handle_pragma_vtable);
Index: builtin-types.def
===================================================================
--- builtin-types.def	(revision 209391)
+++ builtin-types.def	(working copy)
@@ -70,14 +70,12 @@ DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_typ
 DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
-DEF_PRIMITIVE_TYPE (BT_INT128, int128_integer_type_node)
-DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
 DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
Index: machmode.def
===================================================================
--- machmode.def	(revision 209391)
+++ machmode.def	(working copy)
@@ -189,12 +189,19 @@ INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
 
 /* No partial integer modes are defined by default.  */
 
+/* The target normally defines any target-specific __intN types and
+   their modes, but __int128 for TImode is fairly common so define it
+   here.  The type will not be created unless the target supports
+   TImode.  */
+
+INT_N (TI, 128);
+
 /* Basic floating point modes.  SF and DF are the only modes provided
    by default.  The names QF, HF, XF, and TF are reserved for targets
    that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
 
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE).  */
Index: stor-layout.c
===================================================================
--- stor-layout.c	(revision 209391)
+++ stor-layout.c	(working copy)
@@ -310,22 +310,30 @@ finalize_size_functions (void)
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   enum machine_mode mode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if ((mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+      && mode == BLKmode)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size
+	  && int_n_enabled_p[i])
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +354,33 @@ mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+	  && int_n_enabled_p[i])
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
@@ -1687,12 +1706,13 @@ finalize_type_size (tree type)
        sizetype, so we force a conversion.  */
     TYPE_SIZE_UNIT (type)
       = fold_convert (sizetype,
 		      size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
 				  bitsize_unit_node));
 
+  /* DJ - this may break partial-int types.  */
   if (TYPE_SIZE (type) != 0)
     {
       TYPE_SIZE (type) = round_up (TYPE_SIZE (type), TYPE_ALIGN (type));
       TYPE_SIZE_UNIT (type)
 	= round_up (TYPE_SIZE_UNIT (type), TYPE_ALIGN_UNIT (type));
     }
@@ -2056,13 +2076,13 @@ layout_type (tree type)
 
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       SET_TYPE_MODE (type,
 		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE (type)));
       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
       break;
 
     case REAL_TYPE:
       SET_TYPE_MODE (type,
 		     mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
@@ -2157,13 +2177,13 @@ layout_type (tree type)
 	    mode = targetm.addr_space.address_mode (as);
 	  }
 
 	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
-	TYPE_PRECISION (type) = GET_MODE_BITSIZE (mode);
+	TYPE_PRECISION (type) = GET_MODE_PRECISION (mode);
       }
       break;
 
     case ARRAY_TYPE:
       {
 	tree index = TYPE_DOMAIN (type);
@@ -2452,16 +2472,33 @@ initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      precision = -1;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZETYPE) == 0)
+	      {
+		precision = int_n_data[i].bitsize;
+	      }
+	  }
+      if (precision == -1)
+	gcc_unreachable ();
+    }
 
   bprecision
-    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+    = MIN (precision, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
   /* Create stubs for sizetype and bitsizetype so we can create constants.  */
Index: genmodes.c
===================================================================
--- genmodes.c	(revision 209391)
+++ genmodes.c	(working copy)
@@ -69,23 +69,25 @@ struct mode_data
 
   const char *file;		/* file and line of definition, */
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
+
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0
+  "<unknown>", 0, 0, 0, 0, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -627,12 +629,40 @@ reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(M,PREC)				\
+  make_int_n (#M, PREC, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (const char *m, int bitsize,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -906,12 +936,13 @@ emit_max_int (void)
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -966,12 +997,19 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\
 \n\
 #endif /* insn-modes.h */");
 }
 
 static void
@@ -1409,12 +1447,59 @@ emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+  struct mode_data **mode_sort;
+  int n_modes = 0;
+  int i, j;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_modes ++;
+  mode_sort = XALLOCAVEC (struct mode_data *, n_modes);
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      mode_sort[n_modes++] = m;
+
+  /* Yes, this is a bubblesort, but there are at most four (and
+     usually only 1-2) entries to sort.  */
+  for (i = 0; i<n_modes - 1; i++)
+    for (j = i + 1; j < n_modes; j++)
+      if (mode_sort[i]->int_n > mode_sort[j]->int_n)
+	{
+	  m = mode_sort[i];
+	  mode_sort[i] = mode_sort[j];
+	  mode_sort[j] = m;
+	}
+
+  for (i = 0; i < n_modes; i ++)
+    {
+      m = mode_sort[i];
+      printf(" {\n");
+      tagged_printf ("%u", m->int_n, m->name);
+      printf ("%smode,", m->name);
+      printf(" },\n");
+    }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1428,12 +1513,13 @@ emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: lto/lto-lang.c
===================================================================
--- lto/lto-lang.c	(revision 209391)
+++ lto/lto-lang.c	(working copy)
@@ -1140,23 +1140,44 @@ lto_build_c_type_nodes (void)
     {
       intmax_type_node = long_long_integer_type_node;
       uintmax_type_node = long_long_unsigned_type_node;
       signed_size_type_node = long_long_integer_type_node;
     }
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      signed_size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		intmax_type_node = int_n_trees[i].signed_type;
+		uintmax_type_node = int_n_trees[i].unsigned_type;
+		signed_size_type_node = int_n_trees[i].signed_type;
+	      }
+	  }
+      if (signed_size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   wint_type_node = unsigned_type_node;
   pid_type_node = integer_type_node;
 }
 
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
+  int i;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = (flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
@@ -1222,14 +1243,19 @@ lto_init (void)
   NAME_TYPE (long_double_type_node, "long double");
   NAME_TYPE (void_type_node, "void");
   NAME_TYPE (boolean_type_node, "bool");
   NAME_TYPE (complex_float_type_node, "complex float");
   NAME_TYPE (complex_double_type_node, "complex double");
   NAME_TYPE (complex_long_double_type_node, "complex long double");
-  if (int128_integer_type_node)
-    NAME_TYPE (int128_integer_type_node, "__int128");
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    if (int_n_enabled_p[i])
+      {
+	char name[50];
+	sprintf (name, "__int%d", int_n_data[i].bitsize);
+	NAME_TYPE (int_n_trees[i].signed_type, name);
+      }
 #undef NAME_TYPE
 
   /* Initialize LTO-specific data structures.  */
   in_lto_p = true;
 
   return true;
Index: gimple.c
===================================================================
--- gimple.c	(revision 209391)
+++ gimple.c	(working copy)
@@ -2096,12 +2096,13 @@ gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2113,16 +2114,21 @@ gimple_signed_or_unsigned_type (bool uns
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node
       || type1 == long_long_unsigned_type_node)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2229,16 +2235,20 @@ gimple_signed_or_unsigned_type (bool uns
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-	    ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
Index: tree-core.h
===================================================================
--- tree-core.h	(revision 209391)
+++ tree-core.h	(working copy)
@@ -560,14 +560,22 @@ enum integer_type_kind {
   itk_int,
   itk_unsigned_int,
   itk_long,
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
+
+  itk_intN_0,
+  itk_unsigned_intN_0,
+  itk_intN_1,
+  itk_unsigned_intN_1,
+  itk_intN_2,
+  itk_unsigned_intN_2,
+  itk_intN_3,
+  itk_unsigned_intN_3,
+
   itk_none
 };
 
 /* A pointer-to-function member type looks like:
 
      struct {

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-14 23:03 [patch] change specific int128 -> generic intN DJ Delorie
@ 2014-04-15  5:54 ` Marc Glisse
  2014-04-15  6:17   ` DJ Delorie
  2014-05-08 23:34 ` DJ Delorie
  2014-06-21 16:24 ` DJ Delorie
  2 siblings, 1 reply; 49+ messages in thread
From: Marc Glisse @ 2014-04-15  5:54 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

On Mon, 14 Apr 2014, DJ Delorie wrote:

> 	* rtti.c (emit_support_tinfos): Remove __int128-specific entries.

Hello,

I wanted to check the interaction with:
http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00618.html

but I don't see where you moved the __int128 typeinfo generation.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-15  5:54 ` Marc Glisse
@ 2014-04-15  6:17   ` DJ Delorie
  2014-04-17 20:17     ` Marc Glisse
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-04-15  6:17 UTC (permalink / raw)
  To: Marc Glisse; +Cc: gcc-patches


I wasn't sure what to do with that array, since it was static and
couldn't have "empty" slots in them like the arrays in tree.h.  Also,
do we need to have *every* type in that list?  What's the rule for
whether a type gets installed there or not?  The comment says
"guaranteed to be in the runtime support" but does that mean "for this
particular build" (wrt multilibs) as not all intN types are guaranteed
(even the int128 types were not guaranteed to be supported before my
patch).  In other parts of the patch, just taking out the special case
for __int128 was sufficient to "do the right thing" for all __intN
types.

I can certainly put the intN types in there, but note that it would
mean regenerating the fundamentals[] array at runtime to include those
types which are supported at the time.

Do the entries in the array need to be in a particular order?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-15  6:17   ` DJ Delorie
@ 2014-04-17 20:17     ` Marc Glisse
  0 siblings, 0 replies; 49+ messages in thread
From: Marc Glisse @ 2014-04-17 20:17 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

On Tue, 15 Apr 2014, DJ Delorie wrote:

> I wasn't sure what to do with that array, since it was static and
> couldn't have "empty" slots in them like the arrays in tree.h.  Also,
> do we need to have *every* type in that list?  What's the rule for
> whether a type gets installed there or not?  The comment says
> "guaranteed to be in the runtime support" but does that mean "for this
> particular build" (wrt multilibs) as not all intN types are guaranteed
> (even the int128 types were not guaranteed to be supported before my
> patch).  In other parts of the patch, just taking out the special case
> for __int128 was sufficient to "do the right thing" for all __intN
> types.

You need someone who understands this better than me (ask Jason). To be 
able to throw/catch a type, you need some typeinfo symbols. The front-end 
generates that for classes when they are defined. For fundamental types, 
it assumes libsupc++ will provide it, and the function you are modifying 
is the one generating libsupc++ (I am surprised your patch didn't cause 
any failure on x64_64, at least in abi_check). We need to generate the 
typeinfo for __intN, either in libsupc++, or in each TU, and since both 
cases will require code, I assume libsupc++ is preferable.

> I can certainly put the intN types in there, but note that it would
> mean regenerating the fundamentals[] array at runtime to include those
> types which are supported at the time.

After the patch I linked, it should just mean calling the helper function 
on your new types, no need to touch the array.

> Do the entries in the array need to be in a particular order?

No, any random order would do.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-14 23:03 [patch] change specific int128 -> generic intN DJ Delorie
  2014-04-15  5:54 ` Marc Glisse
@ 2014-05-08 23:34 ` DJ Delorie
  2014-05-09  0:26   ` Marc Glisse
  2014-06-21 16:24 ` DJ Delorie
  2 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-05-08 23:34 UTC (permalink / raw)
  To: gcc-patches


The libstdc++v3 headers have __int128 hard-coded all over the place.
Any suggestions on parameterizing those for the __intN types that are
actually supported by the target?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-08 23:34 ` DJ Delorie
@ 2014-05-09  0:26   ` Marc Glisse
  2014-05-09  2:21     ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Marc Glisse @ 2014-05-09  0:26 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches, libstdc++

On Thu, 8 May 2014, DJ Delorie wrote:

> The libstdc++v3 headers have __int128 hard-coded all over the place.
> Any suggestions on parameterizing those for the __intN types that are
> actually supported by the target?

(adding libstdc++@ in Cc:)

The first idea that comes to mind (so possibly not such a good one) is to 
provide predefined macros:
#define __EXTENDED_INTEGER_TYPE_1__ __int24
#define __EXTENDED_INTEGER_TYPE_2__ __int128
#undef __EXTENDED_INTEGER_TYPE_3__

Assuming that the formula sizeof(type)*char_bit==precision works for all 
types, it should be sufficient for the library (abs, type_traits and 
numeric_limits).

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-09  0:26   ` Marc Glisse
@ 2014-05-09  2:21     ` DJ Delorie
  2014-05-09  7:59       ` Marc Glisse
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-05-09  2:21 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches, libstdc++


> Assuming that the formula sizeof(type)*char_bit==precision works for all 

It doesn't.  THe MSP430 has __int20 for example.

Would it be acceptable for the compiler to always define a set of
macros for each of the intN types?  I would have thought that would be
discouraged, but it would be an easier way to handle it.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-09  2:21     ` DJ Delorie
@ 2014-05-09  7:59       ` Marc Glisse
  2014-05-09 18:29         ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Marc Glisse @ 2014-05-09  7:59 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libstdc++, gcc-patches

On Thu, 8 May 2014, DJ Delorie wrote:

>> Assuming that the formula sizeof(type)*char_bit==precision works for all
>
> It doesn't.  THe MSP430 has __int20 for example.

Well, it wasn't a hard requirement, it is just that the library has to 
use a more complicated way to get the precision (use (unsigned TYPE)(-1) 
to get the unsigned max and compute the precision from that, probably).

> Would it be acceptable for the compiler to always define a set of
> macros for each of the intN types?

What set of macros do you have in mind?

> I would have thought that would be discouraged,

If we can't think of another way...

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-09  7:59       ` Marc Glisse
@ 2014-05-09 18:29         ` DJ Delorie
  0 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-05-09 18:29 UTC (permalink / raw)
  To: libstdc++; +Cc: libstdc++, gcc-patches


> Well, it wasn't a hard requirement, it is just that the library has
> to use a more complicated way to get the precision (use (unsigned
> TYPE)(-1) to get the unsigned max and compute the precision from
> that, probably).

We could define macros for the precision too, and we already know max
and min values as macros, it's "just a matter of" exporting that info
to the C++ headers somehow.

> > Would it be acceptable for the compiler to always define a set of
> > macros for each of the intN types?
> 
> What set of macros do you have in mind?

In general, I meant.  They'd be predefined for pretty much every
compile, not just the C++ headers.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-14 23:03 [patch] change specific int128 -> generic intN DJ Delorie
  2014-04-15  5:54 ` Marc Glisse
  2014-05-08 23:34 ` DJ Delorie
@ 2014-06-21 16:24 ` DJ Delorie
  2014-06-21 17:35   ` Marc Glisse
  2014-06-21 20:17   ` Joseph S. Myers
  2 siblings, 2 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-21 16:24 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches


New version of https://gcc.gnu.org/ml/gcc-patches/2014-04/msg00723.html

This is a big patch, but it includes all the features/changes/support
requested since the initial patch.  Tested with identical results
before/after on x86-64 EXCEPT for g++.dg/ext/int128-1.C, which assumes
__int128 is not supported with -std= but as per previous discussion,
it now is (because __intN might be used for size_t, which is
required).  Tested on msp430 with significant improvements but a few
regressions (expected).

This patch replaces the current int128 support with a generic intN
support, which happens to provide int128 as well as up to three
additional intN types per target.  I will post a separate patch for
the msp430 backend demonstrating the use of this new feature for
__int20, as well as a third to fix some problems with PSImode in
general.

The general idea is that genmodes has a new macro INT_N() for
<tm>-modes.def, which gives the mode and precision to use for
target-specific intN types.  These types are always created, but the
parser will error with "unsupported" if the target does not support
that mode for that compile (i.e. because of command line switches,
etc).  There's an INT_N(TI,128) in the common sources.

If the target defines any types larger than "long long", those types
(like int128 before) will be used for type promotion, but types
smaller than "long long" will not, to avoid confusing the C type
promotion rules.  Otherwise, it's up to the source being compiled to
specific __intN types as desired.

gcc/

	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __int128 for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	(layout_type): Use precision, not size.
	(initialize_sizetypes): Support __intN types.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.
	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Round
	pointer size up to a power of two.
	* defaults.h (DWARF2_ADDR_SIZE): Round up.
	(POINTER_SIZE_UNITS): New, rounded up value.
	* dwarf2asm.c (size_of_encoded_value): Use it.
	(dw2_output_indirect_constant_1): Likewise.

	* expmed.c (init_expmed_one_conv): We now know the sizes of
	partial int modes.
	* expr.c (convert_move): If the target has an explicit converter,
	use it.
	* loop-iv.c (iv_number_of_iterations): Use precision, not size.
	* optabs.c (expand_float): Use precision, not size.
	(expand_fix): Likewise.
	* simplify-rtx (simplify_unary_operation_1): Likewise.
	* tree-dfa.c (get_ref_base_and_extent): Likewise.
	* varasm.c (assemble_addr_to_section): Round up pointer sizes.
	(default_assemble_integer) Likewise.
	(dump_tm_clone_pairs): Likewise.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	(cpp_atomic_builtins): Round pointer sizes up.
	(type_suffix): Use type precision, not specific types.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.

gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Check for all __intN types, not just
	__int128.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.

gcc/lto/
	* lto-lang.c (lto_build_c_type_nodes): Check intN types for
	size-type as well.
	(lto_init): Initialize all intN types, not just int128.
	* lto-object.c (lto_obj_begin_section): Do not assume pointers are
	powers-of-two in size.

gcc/config/msp430
	* config/msp430/msp430-protos.h (msp430_hard_regno_nregs_has_padding): New.
	(msp430_hard_regno_nregs_with_padding): New.
	* config/msp430/msp430.c (msp430_scalar_mode_supported_p): New.
	(msp430_hard_regno_nregs_has_padding): New.
	(msp430_hard_regno_nregs_with_padding): New.
	(msp430_unwind_word_mode): Use PSImode instead of SImode.
	(msp430_addr_space_legitimate_address_p): New.
	(msp430_asm_integer): New.
	(msp430_init_dwarf_reg_sizes_extra): New.
	(msp430_print_operand): Use X suffix for PSImode even in small model.
	* config/msp430/msp430.h (POINTER_SIZE): Use 20 bits, not 32.
	(PTR_SIZE): ...but 4 bytes for EH.
	(SIZE_TYPE): Use __int20.
	(PTRDIFF_TYPE): Likewise.
	(INCOMING_FRAME_SP_OFFSET): Adjust.
	* config/msp430/msp430.md (movqi_topbyte): New.
	(movpsi): Use fixed suffixes.
	(movsipsi2): Enable for 430X, not large model.
	(extendhipsi2): Likewise.
	(zero_extendhisi2): Likewise.
	(zero_extendhisipsi2): Likewise.
	(extend_and_shift1_hipsi2): Likewise.
	(extendpsisi2): Likewise.
	(*bitbranch<mode>4_z): Fix suffix logic.

* libstdc++-v3/
	* include/bits/cpp_type_traits.h: Add support for __intN types.
	* include/c_global/cstdlib: Likewise.
	* include/c_std/cstdlib: Likewise.
	* include/std/limits: Likewise.
	* include/std/type_traits: Likewise.
	* src/c++11/limits.cc: Likewise.

Index: libstdc++-v3/src/c++11/limits.cc
===================================================================
--- libstdc++-v3/src/c++11/limits.cc	(revision 211858)
+++ libstdc++-v3/src/c++11/limits.cc	(working copy)
@@ -385,60 +385,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   const bool numeric_limits<unsigned long long>::is_bounded;
   const bool numeric_limits<unsigned long long>::is_modulo;
   const bool numeric_limits<unsigned long long>::traps;
   const bool numeric_limits<unsigned long long>::tinyness_before;
   const float_round_style numeric_limits<unsigned long long>::round_style;
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  const bool numeric_limits<__int128>::is_specialized;
-  const int  numeric_limits<__int128>::digits;
-  const int  numeric_limits<__int128>::digits10;
-  const int  numeric_limits<__int128>::max_digits10;
-  const bool numeric_limits<__int128>::is_signed;
-  const bool numeric_limits<__int128>::is_integer;
-  const bool numeric_limits<__int128>::is_exact;
-  const int  numeric_limits<__int128>::radix;
-  const int  numeric_limits<__int128>::min_exponent;
-  const int  numeric_limits<__int128>::min_exponent10;
-  const int  numeric_limits<__int128>::max_exponent;
-  const int  numeric_limits<__int128>::max_exponent10;
-  const bool numeric_limits<__int128>::has_infinity;
-  const bool numeric_limits<__int128>::has_quiet_NaN;
-  const bool numeric_limits<__int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<__int128>::has_denorm;
-  const bool numeric_limits<__int128>::has_denorm_loss;
-  const bool numeric_limits<__int128>::is_iec559;
-  const bool numeric_limits<__int128>::is_bounded;
-  const bool numeric_limits<__int128>::is_modulo;
-  const bool numeric_limits<__int128>::traps;
-  const bool numeric_limits<__int128>::tinyness_before;
-  const float_round_style numeric_limits<__int128>::round_style;
-
-  const bool numeric_limits<unsigned __int128>::is_specialized;
-  const int  numeric_limits<unsigned __int128>::digits;
-  const int  numeric_limits<unsigned __int128>::digits10;
-  const int  numeric_limits<unsigned __int128>::max_digits10;
-  const bool numeric_limits<unsigned __int128>::is_signed;
-  const bool numeric_limits<unsigned __int128>::is_integer;
-  const bool numeric_limits<unsigned __int128>::is_exact;
-  const int  numeric_limits<unsigned __int128>::radix;
-  const int  numeric_limits<unsigned __int128>::min_exponent;
-  const int  numeric_limits<unsigned __int128>::min_exponent10;
-  const int  numeric_limits<unsigned __int128>::max_exponent;
-  const int  numeric_limits<unsigned __int128>::max_exponent10;
-  const bool numeric_limits<unsigned __int128>::has_infinity;
-  const bool numeric_limits<unsigned __int128>::has_quiet_NaN;
-  const bool numeric_limits<unsigned __int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<unsigned __int128>::has_denorm;
-  const bool numeric_limits<unsigned __int128>::has_denorm_loss;
-  const bool numeric_limits<unsigned __int128>::is_iec559;
-  const bool numeric_limits<unsigned __int128>::is_bounded;
-  const bool numeric_limits<unsigned __int128>::is_modulo;
-  const bool numeric_limits<unsigned __int128>::traps;
-  const bool numeric_limits<unsigned __int128>::tinyness_before;
-  const float_round_style numeric_limits<unsigned __int128>::round_style;
+#if !defined(__STRICT_ANSI__)
+#define INT_N(__INT_N_TYPE)							\
+  const bool numeric_limits<__INT_N_TYPE>::is_specialized;			\
+  const int  numeric_limits<__INT_N_TYPE>::digits;				\
+  const int  numeric_limits<__INT_N_TYPE>::digits10;				\
+  const int  numeric_limits<__INT_N_TYPE>::max_digits10;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_signed;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_integer;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_exact;				\
+  const int  numeric_limits<__INT_N_TYPE>::radix;				\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent10;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent10;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_infinity;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_quiet_NaN;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_signaling_NaN;			\
+  const float_denorm_style numeric_limits<__INT_N_TYPE>::has_denorm;		\
+  const bool numeric_limits<__INT_N_TYPE>::has_denorm_loss;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_iec559;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_bounded;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_modulo;				\
+  const bool numeric_limits<__INT_N_TYPE>::traps;				\
+  const bool numeric_limits<__INT_N_TYPE>::tinyness_before;			\
+  const float_round_style numeric_limits<__INT_N_TYPE>::round_style;		\
+  									\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_specialized;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits10;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_digits10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_signed;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_integer;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_exact;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::radix;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent10;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_infinity;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_quiet_NaN;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_signaling_NaN;		\
+  const float_denorm_style numeric_limits<unsigned __INT_N_TYPE>::has_denorm;	\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_denorm_loss;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_iec559;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_bounded;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_modulo;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::traps;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::tinyness_before;		\
+  const float_round_style numeric_limits<unsigned __INT_N_TYPE>::round_style;
+
+#ifdef __GLIBCXX_USE_INT_N_0
+  INT_N (__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+  INT_N (__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+  INT_N (__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+  INT_N (__GLIBCXX_TYPE_INT_N_3)
+#endif
 #endif
 
   // float
   const bool numeric_limits<float>::is_specialized;
   const int  numeric_limits<float>::digits;
   const int  numeric_limits<float>::digits10;
Index: libstdc++-v3/include/std/type_traits
===================================================================
--- libstdc++-v3/include/std/type_traits	(revision 211858)
+++ libstdc++-v3/include/std/type_traits	(working copy)
@@ -236,19 +236,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 
   template<>
     struct __is_integral_helper<unsigned long long>
     : public true_type { };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  // Conditionalizing on __STRICT_ANSI__ here will break any port that
+  // uses one of these types for size_t.
+#if defined(__GLIBCXX_USE_INT_N_0)
   template<>
-    struct __is_integral_helper<__int128>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
     : public true_type { };
 
   template<>
-    struct __is_integral_helper<unsigned __int128>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
     : public true_type { };
 #endif
 
   /// is_integral
   template<typename _Tp>
     struct is_integral
@@ -1598,16 +1627,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
   template<>
     struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_USE_INT_N_0)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
   template<>
-    struct __make_unsigned<__int128>
-    { typedef unsigned __int128 __type; };
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
@@ -1695,16 +1739,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
   template<>
     struct __make_signed<char32_t> : __make_signed<uint_least32_t>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_USE_INT_N_0)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
+    { typedef __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_1>
+    { typedef __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_2>
+    { typedef __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
   template<>
-    struct __make_signed<unsigned __int128>
-    { typedef __int128 __type; };
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
+    { typedef __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
Index: libstdc++-v3/include/std/limits
===================================================================
--- libstdc++-v3/include/std/limits	(revision 211858)
+++ libstdc++-v3/include/std/limits	(working copy)
@@ -1396,159 +1396,191 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
       static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
       static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 
        = round_toward_zero;
     };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  /// numeric_limits<__int128> specialization.
-  template<>
-    struct numeric_limits<__int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (__int128); }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (__int128); }
-
-#if __cplusplus >= 201103L
-      static constexpr __int128
-      lowest() noexcept { return min(); }
-#endif
-
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (__int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (__int128);
-#if __cplusplus >= 201103L
-      static constexpr int max_digits10 = 0;
-#endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
+#if !defined(__STRICT_ANSI__)
 
-      static _GLIBCXX_USE_CONSTEXPR bool traps
-       = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
+#define __INT_N(TYPE, MIN, MAX, UMAX, BITSIZE, EXT, UEXT)			\
+  template<> 									\
+    struct numeric_limits<TYPE> 						\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      min() _GLIBCXX_USE_NOEXCEPT { return MIN; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      max() _GLIBCXX_USE_NOEXCEPT { return MAX; } 				\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE - 1; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = (BITSIZE - 1) * 643L / 2136; 						\
+      										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      EXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps 					\
+       = __glibcxx_integral_traps; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
+    }; 										\
+ 										\
+  template<> 									\
+    struct numeric_limits<unsigned TYPE> 					\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      min() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      max() _GLIBCXX_USE_NOEXCEPT { return UMAX; } 				\
+ 										\
+      UEXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = BITSIZE * 643L / 2136; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; 	\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
     };
 
-  /// numeric_limits<unsigned __int128> specialization.
-  template<>
-    struct numeric_limits<unsigned __int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (unsigned __int128); }
-
 #if __cplusplus >= 201103L
-      static constexpr unsigned __int128
-      lowest() noexcept { return min(); }
-#endif
 
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (unsigned __int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (unsigned __int128);
-#if __cplusplus >= 201103L
+#define __INT_N_201103(TYPE)							\
+      static constexpr TYPE 							\
+      lowest() noexcept { return min(); }					\
       static constexpr int max_digits10 = 0;
-#endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
 
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
+#define __INT_N_U201103(TYPE)							\
+      static constexpr unsigned TYPE 						\
+      lowest() noexcept { return min(); }					\
+      static constexpr int max_digits10 = 0;
 
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
+#else
+#define __INT_N_201103(TYPE)
+#define __INT_N_U201103(TYPE)
+#endif
+
+#ifdef __GLIBCXX_USE_INT_N_0
+  __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_MIN_INT_N_0, __GLIBCXX_MAX_INT_N_0,
+	  __GLIBCXX_UMAX_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+  __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_MIN_INT_N_1, __GLIBCXX_MAX_INT_N_1,
+	   __GLIBCXX_UMAX_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+  __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_MIN_INT_N_2, __GLIBCXX_MAX_INT_N_2,
+	   __GLIBCXX_UMAX_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+  __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_MIN_INT_N_3, __GLIBCXX_MAX_INT_N_3,
+	   __GLIBCXX_UMAX_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3))
+#endif
+
+#undef __INT_N
+#undef __INT_N_201103
+#undef __INT_N_U201103
 
-      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
-    };
 #endif
 
   /// numeric_limits<float> specialization.
   template<>
     struct numeric_limits<float>
     {
Index: libstdc++-v3/include/c_std/cstdlib
===================================================================
--- libstdc++-v3/include/c_std/cstdlib	(revision 211858)
+++ libstdc++-v3/include/c_std/cstdlib	(working copy)
@@ -166,15 +166,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_USE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
   inline ldiv_t
   div(long __i, long __j) { return ldiv(__i, __j); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
Index: libstdc++-v3/include/bits/cpp_type_traits.h
===================================================================
--- libstdc++-v3/include/bits/cpp_type_traits.h	(revision 211858)
+++ libstdc++-v3/include/bits/cpp_type_traits.h	(working copy)
@@ -138,13 +138,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       enum { __value = 0 };
       typedef __false_type __type;
     };
 
   // Thirteen specializations (yes there are eleven standard integer
   // types; <em>long long</em> and <em>unsigned long long</em> are
-  // supported as extensions)
+  // supported as extensions).  Up to four target-specific __int<N>
+  // types are supported as well.
   template<>
     struct __is_integer<bool>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
@@ -248,12 +249,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_integer<unsigned long long>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
 
+#define __INT_N(TYPE) 			\
+  template<>				\
+    struct __is_integer<TYPE>		\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };					\
+  template<>				\
+    struct __is_integer<unsigned TYPE>	\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };
+
+#ifdef __GLIBCXX_USE_INT_N_0
+__INT_N(__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+__INT_N(__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+__INT_N(__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+__INT_N(__GLIBCXX_TYPE_INT_N_3)
+#endif
+
+#undef __INT_N
+
   //
   // Floating point types
   //
   template<typename _Tp>
     struct __is_floating
     {
Index: libstdc++-v3/include/c_global/cstdlib
===================================================================
--- libstdc++-v3/include/c_global/cstdlib	(revision 211858)
+++ libstdc++-v3/include/c_global/cstdlib	(working copy)
@@ -171,17 +171,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_USE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #if _GLIBCXX_USE_C99
 
 #undef _Exit
Index: gcc/dwarf2asm.c
===================================================================
--- gcc/dwarf2asm.c	(revision 211858)
+++ gcc/dwarf2asm.c	(working copy)
@@ -387,13 +387,13 @@ size_of_encoded_value (int encoding)
   if (encoding == DW_EH_PE_omit)
     return 0;
 
   switch (encoding & 0x07)
     {
     case DW_EH_PE_absptr:
-      return POINTER_SIZE / BITS_PER_UNIT;
+      return POINTER_SIZE_UNITS;
     case DW_EH_PE_udata2:
       return 2;
     case DW_EH_PE_udata4:
       return 4;
     case DW_EH_PE_udata8:
       return 8;
@@ -917,13 +917,13 @@ dw2_output_indirect_constant_1 (splay_tr
       if (USE_LINKONCE_INDIRECT)
 	DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
     }
 
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
   assemble_variable (decl, 1, 1, 1);
-  assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
 
   return 0;
 }
 
 /* Emit the constants queued through dw2_force_const_mem.  */
 
Index: gcc/cppbuiltin.c
===================================================================
--- gcc/cppbuiltin.c	(revision 211858)
+++ gcc/cppbuiltin.c	(working copy)
@@ -172,13 +172,13 @@ define_builtin_macros_for_type_sizes (cp
                          ? "__ORDER_BIG_ENDIAN__"
                          : "__ORDER_LITTLE_ENDIAN__"));
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E switch.  */
   cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
-			POINTER_SIZE / BITS_PER_UNIT);
+			1 << ceil_log2 ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT));
 }
 
 
 /* Define macros builtins common to all language performing CPP
    preprocessing.  */
 void
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	(revision 211858)
+++ gcc/machmode.h	(working copy)
@@ -342,7 +342,19 @@ extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  unsigned int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+/* This is also in tree.h.  genmodes.c guarantees the're sorted from
+   smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(revision 211858)
+++ gcc/c-family/c-pretty-print.c	(working copy)
@@ -917,12 +917,14 @@ pp_c_void_constant (c_pretty_printer *pp
 
 /* Pretty-print an INTEGER literal.  */
 
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
+  int idx;
+
   /* We are going to compare the type of I to other types using
      pointer comparison so we need to use its canonical type.  */
   tree type =
     TYPE_CANONICAL (TREE_TYPE (i))
     ? TYPE_CANONICAL (TREE_TYPE (i))
     : TREE_TYPE (i);
@@ -947,15 +949,23 @@ pp_c_integer_constant (c_pretty_printer 
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
-  else if (type == int128_integer_type_node
-           || type == int128_unsigned_type_node)
-    pp_string (pp, "I128");
+  else for (idx = 0; idx < NUM_INT_N_ENTS; idx ++)
+    if (int_n_enabled_p[idx])
+      {
+	char buf[2+20];
+	if (type == int_n_trees[idx].signed_type
+	    || type == int_n_trees[idx].unsigned_type)
+	  {
+	    sprintf (buf, "I%d", int_n_data[idx].bitsize);
+	    pp_string (pp, buf);
+	  }
+      }
 }
 
 /* Print out a CHARACTER literal.  */
 
 static void
 pp_c_character_constant (c_pretty_printer *pp, tree c)
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 211858)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -675,13 +675,13 @@ cpp_atomic_builtins (cpp_reader *pfile)
      to a boolean truth value, let the library work around that.  */
   builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
 				 targetm.atomic_test_and_set_trueval);
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E  or pch.  */
-  psize = POINTER_SIZE / BITS_PER_UNIT;
+  psize = POINTER_SIZE_UNITS;
   if (psize >= SWAP_LIMIT)
     psize = 0;
   builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE", 
 			(have_swap[psize]? 2 : 1));
 }
 
@@ -775,12 +775,14 @@ cpp_iec_559_complex_value (void)
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
 {
+  int i;
+
   /* -undef turns off target-specific built-ins.  */
   if (flag_undef)
     return;
 
   define_language_independent_builtin_macros (pfile);
 
@@ -844,12 +846,47 @@ c_cpp_builtins (cpp_reader *pfile)
   builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node);
   builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__",
 			      underlying_wchar_type_node);
   builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", wint_type_node);
   builtin_define_type_max ("__PTRDIFF_MAX__", ptrdiff_type_node);
   builtin_define_type_max ("__SIZE_MAX__", size_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[35+20+20];
+	char buf_min[15+20];
+	char buf_max[15+20];
+
+	sprintf(buf_min, "__INT%d_MIN__", int_n_data[i].bitsize);
+	sprintf(buf_max, "__INT%d_MAX__", int_n_data[i].bitsize);
+	builtin_define_type_minmax (buf_min, buf_max,
+				    int_n_trees[i].signed_type);
+	sprintf(buf_max, "__UINT%d_MAX__", int_n_data[i].bitsize);
+	builtin_define_type_max (buf_max,
+				 int_n_trees[i].unsigned_type);
+
+	/* These are used to configure the C++ library.  */
+
+	sprintf (buf, "__GLIBCXX_USE_INT_N_%d", i);
+	if (!flag_iso || int_n_data[i].bitsize == POINTER_SIZE)
+	  builtin_define_with_int_value (buf, 1);
+
+	sprintf (buf, "__GLIBCXX_TYPE_INT_N_%d=__int%d", i, int_n_data[i].bitsize);
+	cpp_define (parse_in, buf);
+
+	sprintf (buf, "__GLIBCXX_BITSIZE_INT_N_%d=%d", i, int_n_data[i].bitsize);
+	cpp_define (parse_in, buf);
+
+	sprintf(buf_min, "__GLIBCXX_MIN_INT_N_%d", i);
+	sprintf(buf_max, "__GLIBCXX_MAX_INT_N_%d", i);
+	builtin_define_type_minmax (buf_min, buf_max,
+				    int_n_trees[i].signed_type);
+	sprintf(buf_max, "__GLIBCXX_UMAX_INT_N_%d", i);
+	builtin_define_type_max (buf_max,
+				 int_n_trees[i].unsigned_type);
+      }
 
   /* stdint.h and the testsuite need to know these.  */
   builtin_define_stdint_macros ();
 
   /* Provide information for library headers to determine whether to
      define macros such as __STDC_IEC_559__ and
@@ -993,15 +1030,20 @@ c_cpp_builtins (cpp_reader *pfile)
   else if (flag_stack_protect == 1)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201307");
 
-  if (int128_integer_type_node != NULL_TREE)
-    builtin_define_type_sizeof ("__SIZEOF_INT128__",
-			        int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[15+20];
+	sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+	builtin_define_type_sizeof (buf,
+				    int_n_trees[i].signed_type);
+      }
   builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
   builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
   builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
 			      unsigned_ptrdiff_type_node);
 
   /* A straightforward target hook doesn't work, because of problems
@@ -1227,18 +1269,21 @@ builtin_define_with_hex_fp_value (const 
 static const char *
 type_suffix (tree type)
 {
   static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
   int unsigned_suffix;
   int is_long;
+  int tp = TYPE_PRECISION (type);
 
   if (type == long_long_integer_type_node
-      || type == long_long_unsigned_type_node)
+      || type == long_long_unsigned_type_node
+      || tp > TYPE_PRECISION (long_integer_type_node))
     is_long = 2;
   else if (type == long_integer_type_node
-	   || type == long_unsigned_type_node)
+	   || type == long_unsigned_type_node
+	   || tp > TYPE_PRECISION (integer_type_node))
     is_long = 1;
   else if (type == integer_type_node
 	   || type == unsigned_type_node
 	   || type == short_integer_type_node
 	   || type == short_unsigned_type_node
 	   || type == signed_char_type_node
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 211858)
+++ gcc/c-family/c-common.c	(working copy)
@@ -58,18 +58,16 @@ cpp_reader *parse_in;		/* Declared in c-
 
    INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
 
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
-	tree int128_integer_type_node;
 
 	tree short_unsigned_type_node;
 	tree long_unsigned_type_node;
 	tree long_long_unsigned_type_node;
-	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
 	tree truthvalue_false_node;
 	tree truthvalue_true_node;
 
 	tree ptrdiff_type_node;
@@ -461,13 +459,12 @@ const struct c_common_resword c_common_r
   { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
   { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
-  { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
   { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
@@ -3438,12 +3435,14 @@ check_case_bounds (location_t loc, tree 
 /* Return an integer type with BITS bits of precision,
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 tree
 c_common_type_for_size (unsigned int bits, int unsignedp)
 {
+  int i;
+
   if (bits == TYPE_PRECISION (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (bits == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 
@@ -3454,16 +3453,17 @@ c_common_type_for_size (unsigned int bit
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (bits == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
-  if (int128_integer_type_node
-      && bits == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& bits == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
   if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -3521,12 +3521,13 @@ tree registered_builtin_types;
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
+  int i;
 
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -3537,15 +3538,17 @@ c_common_type_for_mode (enum machine_mod
   if (mode == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
-  if (int128_integer_type_node
-      && mode == TYPE_MODE (int128_integer_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& mode == int_n_data[i].m)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
 		     : widest_integer_literal_type_node;
 
   if (mode == QImode)
@@ -3737,12 +3740,13 @@ c_common_signed_type (tree type)
    signed according to UNSIGNEDP.  */
 
 tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   /* This block of code emulates the behavior of the old
      c_common_unsigned_type. In particular, it returns
      long_unsigned_type_node if passed a long, even when a int would
      have the same size. This is necessary for warnings to work
      correctly in archs where sizeof(int) == sizeof(long) */
@@ -3755,16 +3759,20 @@ c_common_signed_or_unsigned_type (int un
   if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
-  if (int128_integer_type_node
-      && (type1 == int128_integer_type_node
-	  || type1 == int128_unsigned_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
     return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3873,15 +3881,20 @@ c_common_signed_or_unsigned_type (int un
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -3902,12 +3915,14 @@ c_common_signed_or_unsigned_type (int un
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 
 tree
 c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
 {
+  int i;
+
   /* Extended integer types of the same width as a standard type have
      lesser rank, so those of the same width as int promote to int or
      unsigned int and are valid for printf formats expecting int or
      unsigned int.  To avoid such special cases, avoid creating
      extended integer types for bit-fields if a standard integer type
      is available.  */
@@ -3919,16 +3934,17 @@ c_build_bitfield_integer_type (unsigned 
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (width == TYPE_PRECISION (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node
-      && width == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& width == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -5339,12 +5355,13 @@ c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5355,19 +5372,25 @@ c_common_nodes_and_builtins (void)
   if (c_dialect_cxx ())
     record_builtin_type (RID_SIGNED, NULL, integer_type_node);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
-  if (int128_integer_type_node != NULL_TREE)
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
     {
-      record_builtin_type (RID_INT128, "__int128",
-			   int128_integer_type_node);
-      record_builtin_type (RID_MAX, "__int128 unsigned",
-			   int128_unsigned_type_node);
+      char name[25];
+
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), xstrdup (name),
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, xstrdup (name),
+			   int_n_trees[i].unsigned_type);
     }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -5397,12 +5420,14 @@ c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intSI_type_node));
   lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  /* Note that this is different than the __int128 type that's part of
+     the generic __intN support.  */
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
 					   get_identifier ("__int128_t"),
 					   intTI_type_node));
 #endif
@@ -11695,13 +11720,12 @@ keyword_begins_type_specifier (enum rid 
     case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-    case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
     case RID_SHORT:
     case RID_SIGNED:
     case RID_DFLOAT32:
     case RID_DFLOAT64:
@@ -11718,12 +11742,16 @@ keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 211858)
+++ gcc/c-family/c-common.h	(working copy)
@@ -88,13 +88,12 @@ enum rid
   /* C (reserved and imaginary types not implemented, so any use is a
      syntax error) */
   RID_IMAGINARY,
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
   RID_ENUM,    RID_STRUCT, RID_UNION,    RID_IF,     RID_ELSE,
   RID_WHILE,   RID_DO,     RID_FOR,      RID_SWITCH, RID_CASE,
   RID_DEFAULT, RID_BREAK,  RID_CONTINUE, RID_RETURN, RID_GOTO,
   RID_SIZEOF,
 
   /* C extensions */
@@ -185,12 +184,29 @@ enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN_t keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13_t.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 211858)
+++ gcc/c/c-parser.c	(working copy)
@@ -110,12 +110,22 @@ c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      /* We always create the symbols but they aren't always supported.  */
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (xstrdup (name));
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 \f
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -485,13 +495,12 @@ c_token_starts_typename (c_token *token)
 	}
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -513,12 +522,16 @@ c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -643,13 +656,12 @@ c_token_starts_declspecs (c_token *token
 	case RID_INLINE:
 	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -672,12 +684,16 @@ c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2149,13 +2165,13 @@ c_parser_static_assert_declaration_no_se
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
      __auto_type
-     __int128
+     __intN
      _Decimal32
      _Decimal64
      _Decimal128
      _Fract
      _Accum
      _Sat
@@ -2303,13 +2319,12 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_AUTO_TYPE:
 	  if (!auto_type_ok)
 	    goto out;
 	  /* Fall through.  */
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -2319,12 +2334,16 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3739,13 +3758,12 @@ c_parser_attribute_any_word (c_parser *p
       bool ok;
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_SHORT:
 	case RID_INLINE:
@@ -3769,12 +3787,16 @@ c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8926,13 +8948,12 @@ c_parser_objc_selector (c_parser *parser
     case RID_ASM:
     case RID_SIZEOF:
     case RID_TYPEOF:
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
-    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
     case RID_SIGNED:
     case RID_RESTRICT:
     case RID_COMPLEX:
@@ -8947,12 +8968,16 @@ c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	(revision 211858)
+++ gcc/c/c-tree.h	(working copy)
@@ -196,13 +196,13 @@ enum c_typespec_keyword {
   cts_none,
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
-  cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -263,12 +263,14 @@ struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 211858)
+++ gcc/c/c-decl.c	(working copy)
@@ -9195,16 +9195,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<long%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		  error_at (loc,
-			    ("both %<long%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<long%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<long%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9243,16 +9244,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<short%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		error_at (loc,
-			  ("both %<short%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<short%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<short%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9420,17 +9422,18 @@ declspecs_add_type (location_t loc, stru
 		}
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
 	      pedwarn (loc, OPT_Wpedantic,
 		       "ISO C does not support saturating types");
-	      if (specs->typespec_word == cts_int128)
+	      if (specs->typespec_word == cts_int_n)
 	        {
 		  error_at (loc,
-			    ("both %<_Sat%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<_Sat%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	        }
 	      else if (specs->typespec_word == cts_auto_type)
 		error_at (loc,
 			  ("both %<_Sat%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
@@ -9488,13 +9491,13 @@ declspecs_add_type (location_t loc, stru
 
 	  return specs;
 	}
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+	     "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
 	     "__auto_type".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
 			"two or more data types in declaration specifiers");
 	      return specs;
@@ -9529,37 +9532,44 @@ declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_auto_type;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
-	    case RID_INT128:
-	      if (int128_integer_type_node == NULL_TREE)
-		{
-		  error_at (loc, "%<__int128%> is not supported for this target");
-		  return specs;
-		}
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      specs->int_n_idx = i - RID_INT_N_0;
 	      if (!in_system_header_at (input_location))
 		pedwarn (loc, OPT_Wpedantic,
-			 "ISO C does not support %<__int128%> type");
+			 "ISO C does not support %<__int%d%> types",
+			 int_n_data[specs->int_n_idx].bitsize);
 
 	      if (specs->long_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<long%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<long%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->saturating_p)
 		error_at (loc,
-			  ("both %<_Sat%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<_Sat%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->short_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<short%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<short%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
+	      else if (! int_n_enabled_p [specs->int_n_idx])
+		error_at (loc,
+			  "%<__int%d%> is not supported on this target",
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else
 		{
-		  specs->typespec_word = cts_int128;
+		  specs->typespec_word = cts_int_n;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
@@ -10121,18 +10131,18 @@ finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
-    case cts_int128:
+    case cts_int_n:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       specs->type = (specs->unsigned_p
-		     ? int128_unsigned_type_node
-		     : int128_integer_type_node);
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
       if (specs->complex_p)
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 211858)
+++ gcc/optabs.c	(working copy)
@@ -5178,13 +5178,13 @@ expand_float (rtx to, rtx from, int unsi
     {
       rtx libfunc;
       rtx insns;
       rtx value;
       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
-      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
+      if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
 	from = convert_to_mode (SImode, from, unsignedp);
 
       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
       gcc_assert (libfunc);
 
       start_sequence ();
@@ -5354,13 +5354,13 @@ expand_fix (rtx to, rtx from, int unsign
 	}
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
      only library calls we know about.  */
 
-  if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
+  if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode))
     {
       target = gen_reg_rtx (SImode);
 
       expand_fix (target, from, unsignedp);
     }
   else
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(revision 211858)
+++ gcc/defaults.h	(working copy)
@@ -448,13 +448,13 @@ see the files COPYING3 and COPYING.RUNTI
 /* The size of addresses as they appear in the Dwarf 2 data.
    Some architectures use word addresses to refer to code locations,
    but Dwarf 2 info always uses byte addresses.  On such machines,
    Dwarf 2 addresses need to be larger than the architecture's
    pointers.  */
 #ifndef DWARF2_ADDR_SIZE
-#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#define DWARF2_ADDR_SIZE ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
 #endif
 
 /* The size in bytes of a DWARF field indicating an offset or length
    relative to a debug info section, specified to be 4 bytes in the
    DWARF-2 specification.  The SGI/MIPS ABI defines it to be the same
    as PTR_SIZE.  */
@@ -748,12 +748,16 @@ see the files COPYING3 and COPYING.RUNTI
 #endif
 
 /* Width in bits of a pointer.  Mind the value of the macro `Pmode'.  */
 #ifndef POINTER_SIZE
 #define POINTER_SIZE BITS_PER_WORD
 #endif
+#ifndef POINTER_SIZE_UNITS
+#define POINTER_SIZE_UNITS ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
+#endif
+
 
 #ifndef PIC_OFFSET_TABLE_REGNUM
 #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
 #endif
 
 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 211858)
+++ gcc/tree.c	(working copy)
@@ -234,12 +234,15 @@ static unsigned int type_hash_list (cons
 static unsigned int attribute_hash_list (const_tree, hashval_t);
 static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+bool int_n_enabled_p[NUM_INT_N_ENTS];
+struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9485,26 +9488,31 @@ make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (size == LONG_TYPE_SIZE)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
-  if (size == 128 && int128_integer_type_node)
-    return (unsignedp ? int128_unsigned_type_node
-            : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize
+	&& int_n_enabled_p[i])
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
@@ -9614,12 +9622,14 @@ build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9641,23 +9651,26 @@ build_common_tree_nodes (bool signed_cha
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-#if HOST_BITS_PER_WIDE_INT >= 64
-    /* TODO: This isn't correct, but as logic depends at the moment on
-       host's instead of target's wide-integer.
-       If there is a target not supporting TImode, but has an 128-bit
-       integer-scalar register, this target check needs to be adjusted. */
-    if (targetm.scalar_mode_supported_p (TImode))
-      {
-        int128_integer_type_node = make_signed_type (128);
-        int128_unsigned_type_node = make_unsigned_type (128);
-      }
-#endif
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+      int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+
+      if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE)
+	{
+	  integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
+	  integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
+	}
+    }
 
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
   TYPE_PRECISION (boolean_type_node) = 1;
@@ -9670,13 +9683,30 @@ build_common_tree_nodes (bool signed_cha
     size_type_node = long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
     size_type_node = long_long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
     size_type_node = short_unsigned_type_node;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		size_type_node = int_n_trees[i].unsigned_type;
+	      }
+	  }
+      if (size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
      when possible.  */
   intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
   intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
   intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 211858)
+++ gcc/tree.h	(working copy)
@@ -3417,14 +3417,12 @@ tree_operand_check_code (const_tree __t,
 #define integer_type_node		integer_types[itk_int]
 #define unsigned_type_node		integer_types[itk_unsigned_int]
 #define long_integer_type_node		integer_types[itk_long]
 #define long_unsigned_type_node		integer_types[itk_unsigned_long]
 #define long_long_integer_type_node	integer_types[itk_long_long]
 #define long_long_unsigned_type_node	integer_types[itk_unsigned_long_long]
-#define int128_integer_type_node	integer_types[itk_int128]
-#define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\
   ((NODE) == error_mark_node					\
    || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
@@ -4768,7 +4766,18 @@ extern tree get_inner_reference (tree, H
 				 bool);
 
 /* Return a tree representing the lower bound of the array mentioned in
    EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
 extern tree array_ref_low_bound (tree);
 
+
+struct GTY(()) int_n_trees_t {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+};
+
+/* This is also in machmode.h */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern GTY(()) struct int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 211858)
+++ gcc/toplev.c	(working copy)
@@ -1870,12 +1870,27 @@ finalize (bool no_backend)
     dump_profile_report ();
 
   /* Language-specific end of compilation actions.  */
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  /* As a special exception, we always want __int128 enabled if possible.  */
+  if (bitsize == 128)
+    return false;
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || (bitsize == LONG_LONG_TYPE_SIZE && LONG_LONG_TYPE_SIZE < GET_MODE_BITSIZE (TImode)))
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
 do_compile (void)
 {
   /* Initialize timing first.  The C front ends read the main file in
      the post_options hook, and C++ does file timings.  */
@@ -1885,20 +1900,33 @@ do_compile (void)
 
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
 	 predefined macros, such as __LDBL_MAX__, for targets using non
 	 default FP formats.  */
       init_adjust_machine_modes ();
       init_derived_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize)
+	    && int_n_data[i].bitsize <= HOST_BITS_PER_WIDE_INT * 2)
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
 	backend_init ();
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 211858)
+++ gcc/cp/typeck.c	(working copy)
@@ -267,12 +267,13 @@ original_type (tree t)
 static tree
 cp_common_type (tree t1, tree t2)
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
   tree attributes;
+  int i;
 
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -361,22 +362,25 @@ cp_common_type (tree t1, tree t2)
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
-      if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
 	{
-	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-		    ? int128_unsigned_type_node
-		    : int128_integer_type_node);
-	  return build_type_attribute_variant (t, attributes);
+	  if (int_n_enabled_p [i]
+	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			       int_n_trees[i].signed_type)
+		  || same_type_p (TYPE_MAIN_VARIANT (t2),
+				  int_n_trees[i].signed_type)))
+	    {
+	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+			? int_n_trees[i].unsigned_type
+			: int_n_trees[i].signed_type);
+	      return build_type_attribute_variant (t, attributes);
+	    }
 	}
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
 	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 211858)
+++ gcc/cp/decl.c	(working copy)
@@ -8749,13 +8749,13 @@ grokdeclarator (const cp_declarator *dec
 		enum decl_context decl_context,
 		int initialized,
 		tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int explicit_int128 = 0;
+  int explicit_intN = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
 
   tree typedef_decl = NULL_TREE;
@@ -8821,13 +8821,13 @@ grokdeclarator (const cp_declarator *dec
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
   short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
-  explicit_int128 = declspecs->explicit_int128_p;
+  explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
     funcdef_flag = true, decl_context = FIELD;
@@ -9162,22 +9162,26 @@ grokdeclarator (const cp_declarator *dec
 
       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
 
-  if (explicit_int128)
+  if (explicit_intN)
     {
-      if (int128_integer_type_node == NULL_TREE)
-	{
-	  error ("%<__int128%> is not supported by this target");
-	  explicit_int128 = false;
-	}
+      if (! int_n_enabled_p[declspecs->int_n_idx])
+       {
+         error ("%<__int%d%> is not supported by this target",
+		int_n_data[declspecs->int_n_idx].bitsize);
+         explicit_intN = false;
+       }
+#if 0 /* temporary - DJ */
       else if (pedantic && ! in_system_header_at (input_location))
-	pedwarn (input_location, OPT_Wpedantic,
-		 "ISO C++ does not support %<__int128%> for %qs", name);
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ does not support %<__int%d%> for %qs",
+		int_n_data[declspecs->int_n_idx].bitsize,  name);
+#endif
     }
 
   /* Now process the modifiers that were specified
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
@@ -9203,13 +9207,13 @@ grokdeclarator (const cp_declarator *dec
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
       else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
-      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
       else if (long_p && short_p)
 	error ("%<long%> and %<short%> specified together for %qs", name);
       else if (type == char16_type_node || type == char32_type_node)
@@ -9219,13 +9223,13 @@ grokdeclarator (const cp_declarator *dec
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
 		       name);
 	      if (flag_pedantic_errors)
 		ok = 0;
@@ -9261,14 +9265,14 @@ grokdeclarator (const cp_declarator *dec
 	     `signed int' cannot be so controlled.  */
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
-	type = int128_unsigned_type_node;
+      if (explicit_intN)
+	type = int_n_trees[declspecs->int_n_idx].unsigned_type;
       else if (longlong)
 	type = long_long_unsigned_type_node;
       else if (long_p)
 	type = long_unsigned_type_node;
       else if (short_p)
 	type = short_unsigned_type_node;
@@ -9278,14 +9282,14 @@ grokdeclarator (const cp_declarator *dec
 	type = unsigned_type_for (type);
       else
 	type = unsigned_type_node;
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
-  else if (explicit_int128)
-    type = int128_integer_type_node;
+  else if (explicit_intN)
+    type = int_n_trees[declspecs->int_n_idx].signed_type;
   else if (longlong)
     type = long_long_integer_type_node;
   else if (long_p)
     type = long_integer_type_node;
   else if (short_p)
     type = short_integer_type_node;
@@ -9295,13 +9299,13 @@ grokdeclarator (const cp_declarator *dec
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
 	error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
 	 "complex double", but if any modifiers at all are specified it is
 	 the complex form of TYPE.  E.g, "complex short" is
 	 "complex short int".  */
-      else if (defaulted_int && ! longlong && ! explicit_int128
+      else if (defaulted_int && ! longlong && ! explicit_intN
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
 	type = complex_integer_type_node;
       else if (type == float_type_node)
 	type = complex_float_type_node;
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c	(revision 211858)
+++ gcc/cp/rtti.c	(working copy)
@@ -1506,31 +1506,44 @@ emit_support_tinfo_1 (tree bltn)
 
 void
 emit_support_tinfos (void)
 {
   /* Dummy static variable so we can put nullptr in the array; it will be
      set before we actually start to walk the array.  */
-  static tree *const fundamentals[] =
+  static tree * fundamentals[] =
   {
     &void_type_node,
     &boolean_type_node,
     &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
-    &int128_integer_type_node, &int128_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
+#define FUND_INT_N_IDX 22
+    // These eight are for intN_t nodes
+    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
+    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
     &nullptr_type_node,
     0
   };
-  int ix;
+  int ix, i;
   tree bltn_type, dtor;
 
+  ix = FUND_INT_N_IDX;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	fundamentals [ix++] = &int_n_trees[i].signed_type;
+	fundamentals [ix++] = &int_n_trees[i].unsigned_type;
+      }
+  fundamentals [ix++] = &nullptr_type_node;
+  fundamentals [ix++] = 0;
+
   push_abi_namespace ();
   bltn_type = xref_tag (class_type,
 			get_identifier ("__fundamental_type_info"),
 			/*tag_scope=*/ts_current, false);
   pop_abi_namespace ();
   if (!COMPLETE_TYPE_P (bltn_type))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 211858)
+++ gcc/cp/parser.c	(working copy)
@@ -936,13 +936,12 @@ cp_lexer_next_token_is_decl_specifier_ke
     case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
-    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
       /* GNU extensions.  */ 
@@ -951,12 +950,16 @@ cp_lexer_next_token_is_decl_specifier_ke
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
       return true;
 
     default:
+      if (token->keyword >= RID_FIRST_INT_N
+	  && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Returns TRUE iff the token T begins a decltype type.  */
 
@@ -14502,12 +14505,13 @@ static tree
 cp_parser_simple_type_specifier (cp_parser* parser,
 				 cp_decl_specifier_seq *decl_specs,
 				 cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
+  int idx;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* If we're looking at a keyword, things are easy.  */
   switch (token->keyword)
@@ -14535,18 +14539,25 @@ cp_parser_simple_type_specifier (cp_pars
       break;
     case RID_INT:
       if (decl_specs)
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
-    case RID_INT128:
-      if (!int128_integer_type_node)
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
+      idx = token->keyword - RID_INT_N_0;
+      if (! int_n_enabled_p [idx])
 	break;
       if (decl_specs)
-        decl_specs->explicit_int128_p = true;
-      type = int128_integer_type_node;
+	{
+	  decl_specs->explicit_intN_p = true;
+	  decl_specs->int_n_idx = idx;
+	}
+      type = int_n_trees [idx].signed_type;
       break;
     case RID_LONG:
       if (decl_specs)
 	set_and_check_decl_spec_loc (decl_specs, ds_long, token);
       type = long_integer_type_node;
       break;
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 211858)
+++ gcc/cp/mangle.c	(working copy)
@@ -150,14 +150,14 @@ integer_type_codes[itk_none] =
   'i',  /* itk_int */
   'j',  /* itk_unsigned_int */
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
-  'n',  /* itk_int128 */
-  'o',  /* itk_unsigned_int128  */
+  /* __intN types are handled separately */
+  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 };
 
 static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
@@ -2149,12 +2149,14 @@ write_CV_qualifiers_for_type (const tree
       ++num_qualifiers;
     }
 
   return num_qualifiers;
 }
 
+#include "print-tree.h"
+
 /* Non-terminal <builtin-type>.
 
      <builtin-type> ::= v   # void
 		    ::= b   # bool
 		    ::= w   # wchar_t
 		    ::= c   # char
@@ -2208,12 +2210,13 @@ write_builtin_type (tree type)
 	  size_t itk;
 	  /* Assume TYPE is one of the shared integer type nodes.  Find
 	     it in the array of these nodes.  */
 	iagain:
 	  for (itk = 0; itk < itk_none; ++itk)
 	    if (integer_types[itk] != NULL_TREE
+		&& integer_type_codes[itk] != '\0'
 		&& type == integer_types[itk])
 	      {
 		/* Print the corresponding single-letter code.  */
 		write_char (integer_type_codes[itk]);
 		break;
 	      }
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 211858)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4849,12 +4849,14 @@ typedef struct cp_decl_specifier_seq {
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
   /* True iff multiple storage classes were (erroneously) specified
@@ -4864,14 +4866,14 @@ typedef struct cp_decl_specifier_seq {
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
   /* True iff at least one type-specifier was found.  */
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
-  /* True iff "__int128" was explicitly provided.  */
-  BOOL_BITFIELD explicit_int128_p : 1;
+  /* True iff "__intN" was explicitly provided.  */
+  BOOL_BITFIELD explicit_intN_p : 1;
   /* True iff "char" was explicitly provided.  */
   BOOL_BITFIELD explicit_char_p : 1;
   /* True iff ds_thread is set for __thread, not thread_local.  */
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
 } cp_decl_specifier_seq;
 
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(revision 211858)
+++ gcc/cp/lex.c	(working copy)
@@ -190,12 +190,21 @@ init_reswords (void)
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
       if (! (c_common_reswords[i].disable & mask))
 	C_IS_RESERVED_WORD (id) = 1;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 static void
 init_cp_pragma (void)
 {
   c_register_pragma (0, "vtable", handle_pragma_vtable);
Index: gcc/builtin-types.def
===================================================================
--- gcc/builtin-types.def	(revision 211858)
+++ gcc/builtin-types.def	(working copy)
@@ -62,14 +62,12 @@ DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_typ
 DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
-DEF_PRIMITIVE_TYPE (BT_INT128, int128_integer_type_node)
-DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
 DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	(revision 211858)
+++ gcc/machmode.def	(working copy)
@@ -189,12 +189,19 @@ INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
 
 /* No partial integer modes are defined by default.  */
 
+/* The target normally defines any target-specific __intN types and
+   their modes, but __int128 for TImode is fairly common so define it
+   here.  The type will not be created unless the target supports
+   TImode.  */
+
+INT_N (TI, 128);
+
 /* Basic floating point modes.  SF and DF are the only modes provided
    by default.  The names QF, HF, XF, and TF are reserved for targets
    that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
 
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE).  */
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 211858)
+++ gcc/expr.c	(working copy)
@@ -405,12 +405,32 @@ convert_move (rtx to, rtx from, int unsi
 								       from)
 			  : gen_rtx_FLOAT_EXTEND (to_mode, from));
       return;
     }
 
   /* Handle pointer conversion.  */			/* SPEE 900220.  */
+  /* If the target has a converter from FROM_MODE to TO_MODE, use it.  */
+  {
+    convert_optab ctab;
+
+    if (GET_MODE_PRECISION (from_mode) > GET_MODE_PRECISION (to_mode))
+      ctab = trunc_optab;
+    else if (unsignedp)
+      ctab = zext_optab;
+    else
+      ctab = sext_optab;
+
+    if (convert_optab_handler (ctab, to_mode, from_mode)
+	!= CODE_FOR_nothing)
+      {
+	emit_unop_insn (convert_optab_handler (ctab, to_mode, from_mode),
+			to, from, UNKNOWN);
+	return;
+      }
+  }
+
   /* 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)
     {
       enum machine_mode full_mode
 	= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 211858)
+++ gcc/stor-layout.c	(working copy)
@@ -309,23 +309,30 @@ finalize_size_functions (void)
    it may have padding as well.  If LIMIT is nonzero, modes of wider
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = BLKmode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size
+	  && int_n_enabled_p[i])
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +353,33 @@ mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+	  && int_n_enabled_p[i])
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
@@ -1754,12 +1772,13 @@ finalize_type_size (tree type)
        sizetype, so we force a conversion.  */
     TYPE_SIZE_UNIT (type)
       = fold_convert (sizetype,
 		      size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
 				  bitsize_unit_node));
 
+  /* DJ - this may break partial-int types.  */
   if (TYPE_SIZE (type) != 0)
     {
       TYPE_SIZE (type) = round_up (TYPE_SIZE (type), TYPE_ALIGN (type));
       TYPE_SIZE_UNIT (type)
 	= round_up (TYPE_SIZE_UNIT (type), TYPE_ALIGN_UNIT (type));
     }
@@ -2123,13 +2142,13 @@ layout_type (tree type)
 
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       SET_TYPE_MODE (type,
 		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE (type)));
       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
       break;
 
     case REAL_TYPE:
       SET_TYPE_MODE (type,
 		     mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
@@ -2194,13 +2213,13 @@ layout_type (tree type)
       TYPE_USER_ALIGN (type) = 0;
       SET_TYPE_MODE (type, VOIDmode);
       break;
 
     case OFFSET_TYPE:
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
-      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
+      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
       /* A pointer might be MODE_PARTIAL_INT,
 	 but ptrdiff_t must be integral.  */
       SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
@@ -2224,13 +2243,13 @@ layout_type (tree type)
 	    mode = targetm.addr_space.address_mode (as);
 	  }
 
 	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
-	TYPE_PRECISION (type) = GET_MODE_BITSIZE (mode);
+	TYPE_PRECISION (type) = GET_MODE_PRECISION (mode);
       }
       break;
 
     case ARRAY_TYPE:
       {
 	tree index = TYPE_DOMAIN (type);
@@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      precision = -1;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZETYPE) == 0)
+	      {
+		precision = int_n_data[i].bitsize;
+	      }
+	  }
+      if (precision == -1)
+	gcc_unreachable ();
+    }
 
   bprecision
-    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+    = MIN (precision, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
   /* Create stubs for sizetype and bitsizetype so we can create constants.  */
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(revision 211858)
+++ gcc/genmodes.c	(working copy)
@@ -71,23 +71,24 @@ struct mode_data
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
   bool need_bytesize_adj;	/* true if this mode need dynamic size
 				   adjustment */
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0, false
+  "<unknown>", 0, 0, 0, 0, false, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -629,12 +630,40 @@ reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(M,PREC)				\
+  make_int_n (#M, PREC, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (const char *m, int bitsize,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -1007,12 +1036,13 @@ mode_inner_inline (enum machine_mode mod
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -1067,12 +1097,19 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\n#if GCC_VERSION >= 4001\n");
   emit_mode_size_inline ();
   emit_mode_nunits_inline ();
   emit_mode_inner_inline ();
   puts ("#endif /* GCC_VERSION >= 4001 */");
 
@@ -1516,12 +1553,59 @@ emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+  struct mode_data **mode_sort;
+  int n_modes = 0;
+  int i, j;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_modes ++;
+  mode_sort = XALLOCAVEC (struct mode_data *, n_modes);
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      mode_sort[n_modes++] = m;
+
+  /* Yes, this is a bubblesort, but there are at most four (and
+     usually only 1-2) entries to sort.  */
+  for (i = 0; i<n_modes - 1; i++)
+    for (j = i + 1; j < n_modes; j++)
+      if (mode_sort[i]->int_n > mode_sort[j]->int_n)
+	{
+	  m = mode_sort[i];
+	  mode_sort[i] = mode_sort[j];
+	  mode_sort[j] = m;
+	}
+
+  for (i = 0; i < n_modes; i ++)
+    {
+      m = mode_sort[i];
+      printf(" {\n");
+      tagged_printf ("%u", m->int_n, m->name);
+      printf ("%smode,", m->name);
+      printf(" },\n");
+    }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1535,12 +1619,13 @@ emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 211858)
+++ gcc/expmed.c	(working copy)
@@ -115,19 +115,25 @@ static void
 init_expmed_one_conv (struct init_expmed_rtl *all, enum machine_mode to_mode,
 		      enum machine_mode from_mode, bool speed)
 {
   int to_size, from_size;
   rtx which;
 
-  /* We're given no information about the true size of a partial integer,
-     only the size of the "full" integer it requires for storage.  For
-     comparison purposes here, reduce the bit size by one in that case.  */
-  to_size = (GET_MODE_BITSIZE (to_mode)
-	     - (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT));
-  from_size = (GET_MODE_BITSIZE (from_mode)
-	       - (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT));
+  to_size = GET_MODE_PRECISION (to_mode);
+  from_size = GET_MODE_PRECISION (from_mode);
+
+  /* Most partial integers have a precision less than the "full"
+     integer it requires for storage.  In case one doesn't, for
+     comparison purposes here, reduce the bit size by one in that
+     case.  */
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT
+      && exact_log2 (to_size) != -1)
+    to_size --;
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT
+      && exact_log2 (from_size) != -1)
+    from_size --;
   
   /* Assume cost of zero-extend and sign-extend is the same.  */
   which = (to_size < from_size ? &all->trunc : &all->zext);
 
   PUT_MODE (&all->reg, from_mode);
   set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c	(revision 211858)
+++ gcc/tree-dfa.c	(working copy)
@@ -404,13 +404,13 @@ get_ref_base_and_extent (tree exp, HOST_
   else if (!VOID_TYPE_P (TREE_TYPE (exp)))
     {
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
       if (mode == BLKmode)
 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
       else
-	bitsize = int (GET_MODE_BITSIZE (mode));
+	bitsize = int (GET_MODE_PRECISION (mode));
     }
   if (size_tree != NULL_TREE
       && TREE_CODE (size_tree) == INTEGER_CST)
     bitsize = wi::to_offset (size_tree);
 
   /* Initially, maxsize is the same as the accessed element size.
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 211858)
+++ gcc/simplify-rtx.c	(working copy)
@@ -1361,14 +1361,14 @@ simplify_unary_operation_1 (enum rtx_cod
 	}
 
       /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
 	 (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>).  */
       if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND)
 	{
-	  gcc_assert (GET_MODE_BITSIZE (mode)
-		      > GET_MODE_BITSIZE (GET_MODE (op)));
+	  gcc_assert (GET_MODE_PRECISION (mode)
+		      > GET_MODE_PRECISION (GET_MODE (op)));
 	  return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0),
 				     GET_MODE (XEXP (op, 0)));
 	}
 
       /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I)))
 	 is (sign_extend:M (subreg:O <X>)) if there is mode with
Index: gcc/lto/lto-object.c
===================================================================
--- gcc/lto/lto-object.c	(revision 211858)
+++ gcc/lto/lto-object.c	(working copy)
@@ -335,13 +335,13 @@ lto_obj_begin_section (const char *name)
   lo = (struct lto_simple_object *) current_out_file;
   gcc_assert (lo != NULL
 	      && lo->sobj_r == NULL
 	      && lo->sobj_w != NULL
 	      && lo->section == NULL);
 
-  align = exact_log2 (POINTER_SIZE / BITS_PER_UNIT);
+  align = ceil_log2 (POINTER_SIZE_UNITS);
   lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
 						    &errmsg, &err);
   if (lo->section == NULL)
     {
       if (err == 0)
 	fatal_error ("%s", errmsg);
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(revision 211858)
+++ gcc/lto/lto-lang.c	(working copy)
@@ -1146,23 +1146,44 @@ lto_build_c_type_nodes (void)
     {
       intmax_type_node = long_long_integer_type_node;
       uintmax_type_node = long_long_unsigned_type_node;
       signed_size_type_node = long_long_integer_type_node;
     }
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      signed_size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		intmax_type_node = int_n_trees[i].signed_type;
+		uintmax_type_node = int_n_trees[i].unsigned_type;
+		signed_size_type_node = int_n_trees[i].signed_type;
+	      }
+	  }
+      if (signed_size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   wint_type_node = unsigned_type_node;
   pid_type_node = integer_type_node;
 }
 
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
+  int i;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = (flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
@@ -1228,14 +1249,19 @@ lto_init (void)
   NAME_TYPE (long_double_type_node, "long double");
   NAME_TYPE (void_type_node, "void");
   NAME_TYPE (boolean_type_node, "bool");
   NAME_TYPE (complex_float_type_node, "complex float");
   NAME_TYPE (complex_double_type_node, "complex double");
   NAME_TYPE (complex_long_double_type_node, "complex long double");
-  if (int128_integer_type_node)
-    NAME_TYPE (int128_integer_type_node, "__int128");
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    if (int_n_enabled_p[i])
+      {
+	char name[50];
+	sprintf (name, "__int%d", int_n_data[i].bitsize);
+	NAME_TYPE (int_n_trees[i].signed_type, name);
+      }
 #undef NAME_TYPE
 
   /* Initialize LTO-specific data structures.  */
   in_lto_p = true;
 
   return true;
Index: gcc/loop-iv.c
===================================================================
--- gcc/loop-iv.c	(revision 211858)
+++ gcc/loop-iv.c	(working copy)
@@ -2409,13 +2409,13 @@ iv_number_of_iterations (struct loop *lo
 
   if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
     goto fail;
 
   comp_mode = iv0.extend_mode;
   mode = iv0.mode;
-  size = GET_MODE_BITSIZE (mode);
+  size = GET_MODE_PRECISION (mode);
   get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
   mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
   mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
 
   if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
     goto fail;
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 211858)
+++ gcc/varasm.c	(working copy)
@@ -1466,13 +1466,13 @@ assemble_asm (tree string)
 /* Write the address of the entity given by SYMBOL to SEC.  */
 void
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
   assemble_align (POINTER_SIZE);
-  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (symbol, (POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT, POINTER_SIZE, 1);
 }
 
 /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
    not) section for PRIORITY.  */
 section *
 get_cdtor_priority_section (int priority, bool constructor_p)
@@ -2619,13 +2619,13 @@ default_assemble_integer (rtx x ATTRIBUT
 			  unsigned int size ATTRIBUTE_UNUSED,
 			  int aligned_p ATTRIBUTE_UNUSED)
 {
   const char *op = integer_asm_op (size, aligned_p);
   /* Avoid GAS bugs for large values.  Specifically negative values whose
      absolute value fits in a bfd_vma, but not in a bfd_signed_vma.  */
-  if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
+  if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
     return false;
   return op && (assemble_integer_with_op (op, x), true);
 }
 
 /* Assemble the integer constant X into an object of SIZE bytes.  ALIGN is
    the alignment of the integer in bits.  Return 1 if we were able to output
@@ -5750,15 +5750,15 @@ dump_tm_clone_pairs (vec<tm_alias_pair> 
 	  switch_to_section (targetm.asm_out.tm_clone_table_section ());
 	  assemble_align (POINTER_SIZE);
 	  switched = true;
 	}
 
       assemble_integer (XEXP (DECL_RTL (src), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
       assemble_integer (XEXP (DECL_RTL (dst), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
     }
 }
 
 /* Provide a default for the tm_clone_table section.  */
 
 section *
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(revision 211858)
+++ gcc/gimple.c	(working copy)
@@ -2091,12 +2091,13 @@ gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2108,16 +2109,21 @@ gimple_signed_or_unsigned_type (bool uns
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node
       || type1 == long_long_unsigned_type_node)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2224,16 +2230,20 @@ gimple_signed_or_unsigned_type (bool uns
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-	    ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 211858)
+++ gcc/tree-core.h	(working copy)
@@ -562,14 +562,22 @@ enum integer_type_kind {
   itk_int,
   itk_unsigned_int,
   itk_long,
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
+
+  itk_intN_0,
+  itk_unsigned_intN_0,
+  itk_intN_1,
+  itk_unsigned_intN_1,
+  itk_intN_2,
+  itk_unsigned_intN_2,
+  itk_intN_3,
+  itk_unsigned_intN_3,
+
   itk_none
 };
 
 /* A pointer-to-function member type looks like:
 
      struct {
@@ -1147,13 +1155,13 @@ enum omp_clause_map_kind
   OMP_CLAUSE_MAP_ALLOC,
   OMP_CLAUSE_MAP_TO,
   OMP_CLAUSE_MAP_FROM,
   OMP_CLAUSE_MAP_TOFROM,
   /* The following kind is an internal only map kind, used for pointer based
      array sections.  OMP_CLAUSE_SIZE for these is not the pointer size,
-     which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias.  */
+     which is implicitly POINTER_SIZE_UNITS, but the bias.  */
   OMP_CLAUSE_MAP_POINTER,
   /* Also internal, behaves like OMP_CLAUS_MAP_TO, but additionally any
      OMP_CLAUSE_MAP_POINTER records consecutive after it which have addresses
      falling into that range will not be ignored if OMP_CLAUSE_MAP_TO_PSET
      wasn't mapped already.  */
   OMP_CLAUSE_MAP_TO_PSET,
Index: gcc/config/msp430/msp430-protos.h
===================================================================
--- gcc/config/msp430/msp430-protos.h	(revision 211858)
+++ gcc/config/msp430/msp430-protos.h	(working copy)
@@ -27,12 +27,15 @@ void	msp430_expand_epilogue (int);
 void	msp430_expand_helper (rtx *operands, const char *, bool);
 void	msp430_expand_prologue (void);
 const char * msp430x_extendhisi (rtx *);
 void	msp430_fixup_compare_operands (enum machine_mode, rtx *);
 int	msp430_hard_regno_mode_ok (int, enum machine_mode);
 int	msp430_hard_regno_nregs (int, enum machine_mode);
+int	msp430_hard_regno_nregs_has_padding (int, enum machine_mode);
+int	msp430_hard_regno_nregs_with_padding (int, enum machine_mode);
+bool    msp430_hwmult_enabled (void);
 rtx	msp430_incoming_return_addr_rtx (void);
 void	msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
 int	msp430_initial_elimination_offset (int, int);
 bool    msp430_is_interrupt_func (void);
 const char * msp430x_logical_shift_right (rtx);
 const char * msp430_mcu_name (void);
Index: gcc/config/msp430/msp430.md
===================================================================
--- gcc/config/msp430/msp430.md	(revision 211858)
+++ gcc/config/msp430/msp430.md	(working copy)
@@ -176,12 +176,19 @@
   ""
   "@
    MOV.B\t%1, %0
    MOV%X1.B\t%1, %0"
 )
 
+(define_insn "movqi_topbyte"
+  [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r")
+	(subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))]
+  "msp430x"
+  "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
+)
+
 (define_insn "movqi"
   [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
 	(match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
   ""
   "@
   MOV.B\t%1, %0
@@ -220,27 +227,27 @@
 ;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
 (define_insn "movpsi"
   [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,Ya,rm")
 	(match_operand:PSI 1 "msp_general_operand" "riYa,r,rmi"))]
   ""
   "@
-  MOV%Q0\t%1, %0
-  MOV%Q0\t%1, %0
-  MOV%X0.%Q0\t%1, %0")
+  MOVA\t%1, %0
+  MOVA\t%1, %0
+  MOVX.A\t%1, %0")
 
 ; This pattern is identical to the truncsipsi2 pattern except
 ; that it uses a SUBREG instead of a TRUNC.  It is needed in
 ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
 ; into (SET:PSI (PSI)).
 ;
 ; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
 
 (define_insn "movsipsi2"
   [(set (match_operand:PSI            0 "register_operand" "=r")
 	(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
 )
 
 ;;------------------------------------------------------------
 ;; Math
 
@@ -564,49 +571,49 @@
   { return msp430x_extendhisi (operands); }
 )
 
 (define_insn "extendhipsi2"
   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
 	(subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #4, %0"
 )
 
 ;; Look for cases where integer/pointer conversions are suboptimal due
 ;; to missing patterns, despite us not having opcodes for these
 ;; patterns.  Doing these manually allows for alternate optimization
 ;; paths.
 (define_insn "zero_extendhisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
 	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))]
-  "TARGET_LARGE"
+  "msp430x"
   "MOV.W\t#0,%H0"
 )
 
 (define_insn "zero_extendhisipsi2"
   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
 	(subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "@
    AND.W\t#-1,%0
    MOV.W\t%1,%0"
 )
 
 (define_insn "extend_and_shift1_hipsi2"
   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
 	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
 		   (const_int 1)))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #3, %0"
 )
 
 (define_insn "extend_and_shift2_hipsi2"
   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
 	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
 		   (const_int 2)))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #2, %0"
 )
 
 ; Nasty - we are sign-extending a 20-bit PSI value in one register into
 ; two adjacent 16-bit registers to make an SI value.  There is no MSP430X
 ; instruction that will do this, so we push the 20-bit value onto the stack
@@ -645,13 +652,13 @@
 ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
 ;; it, we use a different method here.
 
 (define_insn "extendpsisi2"
   [(set (match_operand:SI                  0 "register_operand" "=r")
 	(sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
-  "TARGET_LARGE"
+  "msp430x"
   "*
     /* The intention here is that we copy the bottom 16-bits of
        %1 into %L0 (zeroing the top four bits).  Then we copy the
        entire 20-bits of %1 into %H0 and then arithmetically shift
        it right by 16 bits, to get the top four bits of the pointer
        sign-extended in %H0.  */
@@ -1174,13 +1181,13 @@
 		  (const_int 0))
               (label_ref (match_operand 2 "" ""))
 	      (pc)))
    (clobber (reg:BI CARRY))
    ]
   ""
-  "BIT%x0%X0%b0\t%1, %0 { JEQ\t%l2"
+  "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
   )
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
 	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
 			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	(revision 211858)
+++ gcc/config/msp430/msp430.c	(working copy)
@@ -225,12 +225,27 @@ msp430_option_override (void)
      command line and always sets -O2 in CFLAGS.  Thus it is not
      possible to build newlib with -Os enabled.  Until now...  */
   if (TARGET_OPT_SPACE && optimize < 3)
     optimize_size = 1;
 }
 
+#undef  TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
+
+static bool
+msp430_scalar_mode_supported_p (enum machine_mode m)
+{
+  if (m == PSImode && msp430x)
+    return true;
+#if 0
+  if (m == TImode)
+    return true;
+#endif
+  return default_scalar_mode_supported_p (m);
+}
+
 \f
 
 /* Storage Layout */
 
 #undef  TARGET_MS_BITFIELD_LAYOUT_P
 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
@@ -254,12 +269,33 @@ msp430_hard_regno_nregs (int regno ATTRI
   if (mode == PSImode && msp430x)
     return 1;
   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
 	  / UNITS_PER_WORD);
 }
 
+/* Implements HARD_REGNO_NREGS_HAS_PADDING.  */
+int
+msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
+				     enum machine_mode mode)
+{
+  if (mode == PSImode && msp430x)
+    return 1;
+  return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+	  / UNITS_PER_WORD);
+}
+
+/* Implements HARD_REGNO_NREGS_WITH_PADDING.  */
+int
+msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
+				     enum machine_mode mode)
+{
+  if (mode == PSImode)
+    return 2;
+  return msp430_hard_regno_nregs (regno, mode);
+}
+
 /* Implements HARD_REGNO_MODE_OK.  */
 int
 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
 			   enum machine_mode mode)
 {
   return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
@@ -367,13 +403,13 @@ msp430_addr_space_pointer_mode (addr_spa
 #undef  TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
 
 static enum machine_mode
 msp430_unwind_word_mode (void)
 {
-  return TARGET_LARGE ? SImode : HImode;
+  return TARGET_LARGE ? PSImode : HImode;
 }
 
 /* Determine if one named address space is a subset of another.  */
 #undef  TARGET_ADDR_SPACE_SUBSET_P
 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
 static bool
@@ -882,12 +918,49 @@ msp430_legitimate_address_p (enum machin
 
     default:
       return false;
     }
 }
 
+#undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
+
+bool
+msp430_addr_space_legitimate_address_p (enum machine_mode mode,
+					rtx x,
+					bool strict,
+					addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return msp430_legitimate_address_p (mode, x, strict);
+}
+
+#undef  TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER msp430_asm_integer
+static bool
+msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
+{
+  int c = GET_CODE (x);
+
+  if (size == 3 && GET_MODE (x) == PSImode)
+    size = 4;
+
+  switch (size)
+    {
+    case 4:
+      if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT)
+	{
+	  fprintf (asm_out_file, "\t.long\t");
+	  output_addr_const (asm_out_file, x);
+	  fputc ('\n', asm_out_file);
+	  return true;
+	}
+      break;
+    }
+  return default_assemble_integer (x, size, aligned_p);
+}
+
 #undef  TARGET_LEGITIMATE_CONSTANT_P
 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
 
 static bool
 msp430_legitimate_constant (enum machine_mode mode, rtx x)
 {
@@ -1740,12 +1813,39 @@ msp430_expand_eh_return (rtx eh_handler)
   tmp = gen_rtx_PLUS (Pmode, ap, sa);
   tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
   tmp = gen_rtx_MEM (Pmode, tmp);
   emit_move_insn (tmp, ra);
 }
 
+#undef  TARGET_INIT_DWARF_REG_SIZES_EXTRA
+#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
+void
+msp430_init_dwarf_reg_sizes_extra (tree address)
+{
+  int i;
+  rtx addr = expand_normal (address);
+  rtx mem = gen_rtx_MEM (BLKmode, addr);
+
+  if (!msp430x)
+    return;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      unsigned int dnum = DWARF_FRAME_REGNUM (i);
+      unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
+
+      if (rnum < DWARF_FRAME_REGISTERS)
+	{
+	  HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
+
+	  emit_move_insn (adjust_address (mem, QImode, offset),
+			  gen_int_mode (4, QImode));
+	}
+    }
+}
+
 /* This is a list of MD patterns that implement fixed-count shifts.  */
 static struct
 {
   const char *name;
   int count;
   int need_430x;
@@ -2350,13 +2450,13 @@ msp430_print_operand (FILE * file, rtx o
 	}
       break;
 
     case 'X':
       /* This is used to turn, for example, an ADD opcode into an ADDX
 	 opcode when we're using 20-bit addresses.  */
-      if (TARGET_LARGE)
+      if (TARGET_LARGE || GET_MODE (op) == PSImode)
 	fprintf (file, "X");
       /* We don't care which operand we use, but we want 'X' in the MD
 	 file, so we do it this way.  */
       return;
 
     case 'x':
Index: gcc/config/msp430/msp430-modes.def
===================================================================
--- gcc/config/msp430/msp430-modes.def	(revision 211858)
+++ gcc/config/msp430/msp430-modes.def	(working copy)
@@ -1,3 +1,4 @@
 /* 20-bit address */
 PARTIAL_INT_MODE (SI, 20, PSI);
 
+INT_N (PSI, 20);
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	(revision 211858)
+++ gcc/config/msp430/msp430.h	(working copy)
@@ -128,16 +128,15 @@ extern bool msp430x;
 #define FRAME_GROWS_DOWNWARD		1
 #define FIRST_PARM_OFFSET(FNDECL) 	0
 
 #define MAX_REGS_PER_ADDRESS 		1
 
 #define Pmode 				(TARGET_LARGE ? PSImode : HImode)
-/* Note: 32 is a lie.  Large pointers are actually 20-bits wide.  But gcc
-   thinks that any non-power-of-2 pointer size equates to BLKmode, which
-   causes all kinds of problems...  */
-#define POINTER_SIZE			(TARGET_LARGE ? 32 : 16)
+#define POINTER_SIZE			(TARGET_LARGE ? 20 : 16)
+/* This is just for .eh_frame, to match bfd.  */
+#define PTR_SIZE			(TARGET_LARGE ? 4 : 2)
 #define	POINTERS_EXTEND_UNSIGNED	1
 
 #define ADDR_SPACE_NEAR	1
 #define ADDR_SPACE_FAR	2
 
 #define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas()
@@ -155,15 +154,15 @@ extern bool msp430x;
     (MODE) = HImode;
 #endif
 \f
 /* Layout of Source Language Data Types */
 
 #undef  SIZE_TYPE
-#define SIZE_TYPE			(TARGET_LARGE ? "long unsigned int" : "unsigned int")
+#define SIZE_TYPE			(TARGET_LARGE ? "__int20 unsigned" : "unsigned int")
 #undef  PTRDIFF_TYPE
-#define PTRDIFF_TYPE			(TARGET_LARGE ? "long int" : "int")
+#define PTRDIFF_TYPE			(TARGET_LARGE ? "__int20" : "int")
 #undef  WCHAR_TYPE
 #define WCHAR_TYPE			"long int"
 #undef  WCHAR_TYPE_SIZE
 #define WCHAR_TYPE_SIZE			BITS_PER_WORD
 #define FUNCTION_MODE 			HImode
 #define CASE_VECTOR_MODE		Pmode
@@ -379,13 +378,13 @@ typedef struct
 
 #define JUMP_TABLES_IN_TEXT_SECTION	1
 \f
 #undef	DWARF2_ADDR_SIZE
 #define	DWARF2_ADDR_SIZE			4
 
-#define INCOMING_FRAME_SP_OFFSET		(POINTER_SIZE / BITS_PER_UNIT)
+#define INCOMING_FRAME_SP_OFFSET		(TARGET_LARGE ? 4 : 2)
 
 #undef  PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 
 #define DWARF2_ASM_LINE_DEBUG_INFO		1
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-06-21 16:24 ` DJ Delorie
@ 2014-06-21 17:35   ` Marc Glisse
  2014-06-24  5:40     ` DJ Delorie
  2014-06-21 20:17   ` Joseph S. Myers
  1 sibling, 1 reply; 49+ messages in thread
From: Marc Glisse @ 2014-06-21 17:35 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches, libstdc++

(Adding libstdc++@ in Cc: so they see the patch at
https://gcc.gnu.org/ml/gcc-patches/2014-06/msg01655.html )

On Sat, 21 Jun 2014, DJ Delorie wrote:

> New version of https://gcc.gnu.org/ml/gcc-patches/2014-04/msg00723.html
>
> This is a big patch, but it includes all the features/changes/support
> requested since the initial patch.  Tested with identical results
> before/after on x86-64 EXCEPT for g++.dg/ext/int128-1.C, which assumes
> __int128 is not supported with -std= but as per previous discussion,
> it now is (because __intN might be used for size_t, which is
> required).  Tested on msp430 with significant improvements but a few
> regressions (expected).
>
> This patch replaces the current int128 support with a generic intN
> support, which happens to provide int128 as well as up to three
> additional intN types per target.  I will post a separate patch for
> the msp430 backend demonstrating the use of this new feature for
> __int20, as well as a third to fix some problems with PSImode in
> general.
>
> The general idea is that genmodes has a new macro INT_N() for
> <tm>-modes.def, which gives the mode and precision to use for
> target-specific intN types.  These types are always created, but the
> parser will error with "unsupported" if the target does not support
> that mode for that compile (i.e. because of command line switches,
> etc).  There's an INT_N(TI,128) in the common sources.
>
> If the target defines any types larger than "long long", those types
> (like int128 before) will be used for type promotion, but types
> smaller than "long long" will not, to avoid confusing the C type
> promotion rules.  Otherwise, it's up to the source being compiled to
> specific __intN types as desired.

Nice. A couple quick comments on the parts I understand while
maintainers are resting for the week-end.

> Index: libstdc++-v3/src/c++11/limits.cc
> ===================================================================
[...]
> +#if !defined(__STRICT_ANSI__)

Since the test on __STRICT_ANSI__ is removed for all other uses, it would 
seem consistent to me to remove this one as well. Besides, you are already 
testing __GLIBCXX_USE_INT_N_0, which as far as I understand is protected 
by !flag_iso (with the exception of size_t).

> -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
> +  // Conditionalizing on __STRICT_ANSI__ here will break any port that
> +  // uses one of these types for size_t.
> +#if defined(__GLIBCXX_USE_INT_N_0)
>   template<>
> -    struct __is_integral_helper<__int128>
> +    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>

Since the check for __STRICT_ANSI__ is removed, do we need to add
__extension__ in front of __GLIBCXX_TYPE_INT_N_0 to avoid warning with
-Wsystem-headers?

> --- gcc/cp/rtti.c	(revision 211858)
> +++ gcc/cp/rtti.c	(working copy)
> @@ -1506,31 +1506,44 @@ emit_support_tinfo_1 (tree bltn)
>
> void
> emit_support_tinfos (void)
> {
>   /* Dummy static variable so we can put nullptr in the array; it will be
>      set before we actually start to walk the array.  */
> -  static tree *const fundamentals[] =
> +  static tree * fundamentals[] =
>   {
>     &void_type_node,
>     &boolean_type_node,
>     &wchar_type_node, &char16_type_node, &char32_type_node,
>     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
>     &short_integer_type_node, &short_unsigned_type_node,
>     &integer_type_node, &unsigned_type_node,
>     &long_integer_type_node, &long_unsigned_type_node,
>     &long_long_integer_type_node, &long_long_unsigned_type_node,
> -    &int128_integer_type_node, &int128_unsigned_type_node,
>     &float_type_node, &double_type_node, &long_double_type_node,
>     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
> +#define FUND_INT_N_IDX 22
> +    // These eight are for intN_t nodes
> +    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
> +    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
>     &nullptr_type_node,
>     0
>   };
> -  int ix;
> +  int ix, i;
>   tree bltn_type, dtor;
>
> +  ix = FUND_INT_N_IDX;
> +  for (i = 0; i < NUM_INT_N_ENTS; i ++)
> +    if (int_n_enabled_p[i])
> +      {
> +	fundamentals [ix++] = &int_n_trees[i].signed_type;
> +	fundamentals [ix++] = &int_n_trees[i].unsigned_type;
> +      }
> +  fundamentals [ix++] = &nullptr_type_node;
> +  fundamentals [ix++] = 0;
> +
>   push_abi_namespace ();
>   bltn_type = xref_tag (class_type,
> 			get_identifier ("__fundamental_type_info"),
> 			/*tag_scope=*/ts_current, false);
>   pop_abi_namespace ();
>   if (!COMPLETE_TYPE_P (bltn_type))

That seems complicated. You just need to call emit_support_tinfo_1 on
each of the types (see how fundamentals is used at the end of the
function), no need to put everything in the array.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-06-21 16:24 ` DJ Delorie
  2014-06-21 17:35   ` Marc Glisse
@ 2014-06-21 20:17   ` Joseph S. Myers
  2014-06-24  5:51     ` DJ Delorie
                       ` (4 more replies)
  1 sibling, 5 replies; 49+ messages in thread
From: Joseph S. Myers @ 2014-06-21 20:17 UTC (permalink / raw)
  To: DJ Delorie, gcc-patches

The changes to dwarf2asm.c, cppbuiltin.c, optabs.c, defaults.h, expr.c, 
expmed.c, tree-dfa.c, simplify-rtx.c, lto-object.c, loop-iv.c, varasm.c, 
the msp430 back end and some of the stor-layout.c changes don't look like 
they should depend on the rest of the patch.  I think it would help review 
if anything that can reasonably be separated from the main intN support is 
posted separately, as a much smaller patch with its own self-contained 
rationale (I presume all those changes should work fine without the main 
intN support), and then the intN patch only contains things directly 
related to intN support.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-06-21 17:35   ` Marc Glisse
@ 2014-06-24  5:40     ` DJ Delorie
  2014-06-28 10:09       ` Marc Glisse
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-06-24  5:40 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++


> Since the test on __STRICT_ANSI__ is removed for all other uses, it would 
> seem consistent to me to remove this one as well. Besides, you are already 
> testing __GLIBCXX_USE_INT_N_0, which as far as I understand is protected 
> by !flag_iso (with the exception of size_t).

Yup, I'll clean that up.

> > -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
> > +  // Conditionalizing on __STRICT_ANSI__ here will break any port that
> > +  // uses one of these types for size_t.
> > +#if defined(__GLIBCXX_USE_INT_N_0)
> >   template<>
> > -    struct __is_integral_helper<__int128>
> > +    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
> 
> Since the check for __STRICT_ANSI__ is removed, do we need to add
> __extension__ in front of __GLIBCXX_TYPE_INT_N_0 to avoid warning with
> -Wsystem-headers?

I copied the code from the __int128 case, and it explicitly bypassed
-Wsystem-headers...  so we don't have that problem.  Not sure if we
*should* have that problem, but we didn't before...  I can only assume
that either (1) someone found it too difficult to get __extension__ to
work right in all those cases, or (2) it's a bug.  Or (3) for some
reason they decided to do it that way anyway.  I don't know.

> That seems complicated. You just need to call emit_support_tinfo_1 on
> each of the types (see how fundamentals is used at the end of the
> function), no need to put everything in the array.

Sure, *now* you tell me that :-)

I can do it either way, but it's the same overhead to iterate through
the types.  Shoving it into the array is a bit more future-proof, but
keeping the index in sync is a bit of work if the table ever changes.
Your choice ;-)

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-06-21 20:17   ` Joseph S. Myers
@ 2014-06-24  5:51     ` DJ Delorie
  2014-06-24 23:32     ` [patch 1/4] " DJ Delorie
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-24  5:51 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches


> The changes to dwarf2asm.c, cppbuiltin.c, optabs.c, defaults.h, expr.c, 
> expmed.c, tree-dfa.c, simplify-rtx.c, lto-object.c, loop-iv.c, varasm.c, 
> the msp430 back end and some of the stor-layout.c changes don't look like 
> they should depend on the rest of the patch.  I think it would help review 
> if anything that can reasonably be separated from the main intN support is 
> posted separately, as a much smaller patch with its own self-contained 
> rationale (I presume all those changes should work fine without the main 
> intN support), and then the intN patch only contains things directly 
> related to intN support.

There are basically three types of changes working together here:

1. Changes that remove the "types are powers of two" assumptions
   throughout gcc.  At least, as many as I could find.  These could be
   applied without the intN support, but serve no purpose without it.

2. The intN patch itself.

3. The msp430's changes to use __int20 for size_t, which depends on
   the above two.

I'll split them up but I hope progress on set #2 isn't stalled on
bikeshedding set #1, especially since set #1 doesn't solve any
problems (or really, change *anything*) on its own.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-21 20:17   ` Joseph S. Myers
  2014-06-24  5:51     ` DJ Delorie
@ 2014-06-24 23:32     ` DJ Delorie
  2014-06-27 11:22       ` Eric Botcazou
  2014-06-24 23:38     ` [patch 2/4] " DJ Delorie
                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-06-24 23:32 UTC (permalink / raw)
  To: gcc-patches


Part 1 of 4, split from the full patch.  The purpose of this set of
changes is to remove assumptions in GCC about type sizes.  Previous to
this patch, GCC assumed that all types were powers-of-two in size, and
used naive math accordingly.

Old:
	POINTER_SIZE / BITS_PER_UNIT
	TYPE_SIZE
	GET_MODE_BITSIZE

New:
	POINTER_SIZE_UNITS  (ceil, not floor)
	TYPE_PRECISION
	GET_MODE_PRECISION


gcc/
	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Round
	pointer size up to a power of two.
	* defaults.h (DWARF2_ADDR_SIZE): Round up.
	(POINTER_SIZE_UNITS): New, rounded up value.
	* dwarf2asm.c (size_of_encoded_value): Use it.
	(dw2_output_indirect_constant_1): Likewise.
	* expmed.c (init_expmed_one_conv): We now know the sizes of
	partial int modes.
	* loop-iv.c (iv_number_of_iterations): Use precision, not size.
	* optabs.c (expand_float): Use precision, not size.
	(expand_fix): Likewise.
	* simplify-rtx (simplify_unary_operation_1): Likewise.
	* tree-dfa.c (get_ref_base_and_extent): Likewise.
	* varasm.c (assemble_addr_to_section): Round up pointer sizes.
	(default_assemble_integer) Likewise.
	(dump_tm_clone_pairs): Likewise.
	* tree-core.c: Adjust comment.

gcc/lto/
	* lto-object.c (lto_obj_begin_section): Do not assume pointers are
	powers-of-two in size.

gcc/c-family/
	* c-cppbuiltin.c (cpp_atomic_builtins): Round pointer sizes up.
	(type_suffix): Use type precision, not specific types.

Index: gcc/dwarf2asm.c
===================================================================
--- gcc/dwarf2asm.c	(revision 211858)
+++ gcc/dwarf2asm.c	(working copy)
@@ -387,13 +387,13 @@ size_of_encoded_value (int encoding)
   if (encoding == DW_EH_PE_omit)
     return 0;
 
   switch (encoding & 0x07)
     {
     case DW_EH_PE_absptr:
-      return POINTER_SIZE / BITS_PER_UNIT;
+      return POINTER_SIZE_UNITS;
     case DW_EH_PE_udata2:
       return 2;
     case DW_EH_PE_udata4:
       return 4;
     case DW_EH_PE_udata8:
       return 8;
@@ -917,13 +917,13 @@ dw2_output_indirect_constant_1 (splay_tr
       if (USE_LINKONCE_INDIRECT)
 	DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
     }
 
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
   assemble_variable (decl, 1, 1, 1);
-  assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
 
   return 0;
 }
 
 /* Emit the constants queued through dw2_force_const_mem.  */
 
Index: gcc/cppbuiltin.c
===================================================================
--- gcc/cppbuiltin.c	(revision 211858)
+++ gcc/cppbuiltin.c	(working copy)
@@ -172,13 +172,13 @@ define_builtin_macros_for_type_sizes (cp
                          ? "__ORDER_BIG_ENDIAN__"
                          : "__ORDER_LITTLE_ENDIAN__"));
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E switch.  */
   cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
-			POINTER_SIZE / BITS_PER_UNIT);
+			1 << ceil_log2 ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT));
 }
 
 
 /* Define macros builtins common to all language performing CPP
    preprocessing.  */
 void
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 211858)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -675,13 +675,13 @@ cpp_atomic_builtins (cpp_reader *pfile)
      to a boolean truth value, let the library work around that.  */
   builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
 				 targetm.atomic_test_and_set_trueval);
 
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E  or pch.  */
-  psize = POINTER_SIZE / BITS_PER_UNIT;
+  psize = POINTER_SIZE_UNITS;
   if (psize >= SWAP_LIMIT)
     psize = 0;
   builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE", 
 			(have_swap[psize]? 2 : 1));
 }
 
@@ -1227,18 +1269,21 @@ builtin_define_with_hex_fp_value (const 
 static const char *
 type_suffix (tree type)
 {
   static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
   int unsigned_suffix;
   int is_long;
+  int tp = TYPE_PRECISION (type);
 
   if (type == long_long_integer_type_node
-      || type == long_long_unsigned_type_node)
+      || type == long_long_unsigned_type_node
+      || tp > TYPE_PRECISION (long_integer_type_node))
     is_long = 2;
   else if (type == long_integer_type_node
-	   || type == long_unsigned_type_node)
+	   || type == long_unsigned_type_node
+	   || tp > TYPE_PRECISION (integer_type_node))
     is_long = 1;
   else if (type == integer_type_node
 	   || type == unsigned_type_node
 	   || type == short_integer_type_node
 	   || type == short_unsigned_type_node
 	   || type == signed_char_type_node
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 211858)
+++ gcc/optabs.c	(working copy)
@@ -5178,13 +5178,13 @@ expand_float (rtx to, rtx from, int unsi
     {
       rtx libfunc;
       rtx insns;
       rtx value;
       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
-      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
+      if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
 	from = convert_to_mode (SImode, from, unsignedp);
 
       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
       gcc_assert (libfunc);
 
       start_sequence ();
@@ -5354,13 +5354,13 @@ expand_fix (rtx to, rtx from, int unsign
 	}
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
      only library calls we know about.  */
 
-  if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
+  if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode))
     {
       target = gen_reg_rtx (SImode);
 
       expand_fix (target, from, unsignedp);
     }
   else
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(revision 211858)
+++ gcc/defaults.h	(working copy)
@@ -448,13 +448,13 @@ see the files COPYING3 and COPYING.RUNTI
 /* The size of addresses as they appear in the Dwarf 2 data.
    Some architectures use word addresses to refer to code locations,
    but Dwarf 2 info always uses byte addresses.  On such machines,
    Dwarf 2 addresses need to be larger than the architecture's
    pointers.  */
 #ifndef DWARF2_ADDR_SIZE
-#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#define DWARF2_ADDR_SIZE ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
 #endif
 
 /* The size in bytes of a DWARF field indicating an offset or length
    relative to a debug info section, specified to be 4 bytes in the
    DWARF-2 specification.  The SGI/MIPS ABI defines it to be the same
    as PTR_SIZE.  */
@@ -748,12 +748,16 @@ see the files COPYING3 and COPYING.RUNTI
 #endif
 
 /* Width in bits of a pointer.  Mind the value of the macro `Pmode'.  */
 #ifndef POINTER_SIZE
 #define POINTER_SIZE BITS_PER_WORD
 #endif
+#ifndef POINTER_SIZE_UNITS
+#define POINTER_SIZE_UNITS ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
+#endif
+
 
 #ifndef PIC_OFFSET_TABLE_REGNUM
 #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
 #endif
 
 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 211858)
+++ gcc/stor-layout.c	(working copy)
@@ -2123,13 +2142,13 @@ layout_type (tree type)
 
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       SET_TYPE_MODE (type,
 		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE (type)));
       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
       break;
 
     case REAL_TYPE:
       SET_TYPE_MODE (type,
 		     mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
@@ -2194,13 +2213,13 @@ layout_type (tree type)
       TYPE_USER_ALIGN (type) = 0;
       SET_TYPE_MODE (type, VOIDmode);
       break;
 
     case OFFSET_TYPE:
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
-      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
+      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
       /* A pointer might be MODE_PARTIAL_INT,
 	 but ptrdiff_t must be integral.  */
       SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
@@ -2224,13 +2243,13 @@ layout_type (tree type)
 	    mode = targetm.addr_space.address_mode (as);
 	  }
 
 	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
-	TYPE_PRECISION (type) = GET_MODE_BITSIZE (mode);
+	TYPE_PRECISION (type) = GET_MODE_PRECISION (mode);
       }
       break;
 
     case ARRAY_TYPE:
       {
 	tree index = TYPE_DOMAIN (type);
@@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
    gcc_unreachable ();
 
   bprecision
-    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+    = MIN (precision, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
   /* Create stubs for sizetype and bitsizetype so we can create constants.  */
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 211858)
+++ gcc/expmed.c	(working copy)
@@ -115,19 +115,25 @@ static void
 init_expmed_one_conv (struct init_expmed_rtl *all, enum machine_mode to_mode,
 		      enum machine_mode from_mode, bool speed)
 {
   int to_size, from_size;
   rtx which;
 
-  /* We're given no information about the true size of a partial integer,
-     only the size of the "full" integer it requires for storage.  For
-     comparison purposes here, reduce the bit size by one in that case.  */
-  to_size = (GET_MODE_BITSIZE (to_mode)
-	     - (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT));
-  from_size = (GET_MODE_BITSIZE (from_mode)
-	       - (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT));
+  to_size = GET_MODE_PRECISION (to_mode);
+  from_size = GET_MODE_PRECISION (from_mode);
+
+  /* Most partial integers have a precision less than the "full"
+     integer it requires for storage.  In case one doesn't, for
+     comparison purposes here, reduce the bit size by one in that
+     case.  */
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT
+      && exact_log2 (to_size) != -1)
+    to_size --;
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT
+      && exact_log2 (from_size) != -1)
+    from_size --;
   
   /* Assume cost of zero-extend and sign-extend is the same.  */
   which = (to_size < from_size ? &all->trunc : &all->zext);
 
   PUT_MODE (&all->reg, from_mode);
   set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c	(revision 211858)
+++ gcc/tree-dfa.c	(working copy)
@@ -404,13 +404,13 @@ get_ref_base_and_extent (tree exp, HOST_
   else if (!VOID_TYPE_P (TREE_TYPE (exp)))
     {
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
       if (mode == BLKmode)
 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
       else
-	bitsize = int (GET_MODE_BITSIZE (mode));
+	bitsize = int (GET_MODE_PRECISION (mode));
     }
   if (size_tree != NULL_TREE
       && TREE_CODE (size_tree) == INTEGER_CST)
     bitsize = wi::to_offset (size_tree);
 
   /* Initially, maxsize is the same as the accessed element size.
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 211858)
+++ gcc/simplify-rtx.c	(working copy)
@@ -1361,14 +1361,14 @@ simplify_unary_operation_1 (enum rtx_cod
 	}
 
       /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
 	 (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>).  */
       if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND)
 	{
-	  gcc_assert (GET_MODE_BITSIZE (mode)
-		      > GET_MODE_BITSIZE (GET_MODE (op)));
+	  gcc_assert (GET_MODE_PRECISION (mode)
+		      > GET_MODE_PRECISION (GET_MODE (op)));
 	  return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0),
 				     GET_MODE (XEXP (op, 0)));
 	}
 
       /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I)))
 	 is (sign_extend:M (subreg:O <X>)) if there is mode with
Index: gcc/lto/lto-object.c
===================================================================
--- gcc/lto/lto-object.c	(revision 211858)
+++ gcc/lto/lto-object.c	(working copy)
@@ -335,13 +335,13 @@ lto_obj_begin_section (const char *name)
   lo = (struct lto_simple_object *) current_out_file;
   gcc_assert (lo != NULL
 	      && lo->sobj_r == NULL
 	      && lo->sobj_w != NULL
 	      && lo->section == NULL);
 
-  align = exact_log2 (POINTER_SIZE / BITS_PER_UNIT);
+  align = ceil_log2 (POINTER_SIZE_UNITS);
   lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
 						    &errmsg, &err);
   if (lo->section == NULL)
     {
       if (err == 0)
 	fatal_error ("%s", errmsg);
Index: gcc/loop-iv.c
===================================================================
--- gcc/loop-iv.c	(revision 211858)
+++ gcc/loop-iv.c	(working copy)
@@ -2409,13 +2409,13 @@ iv_number_of_iterations (struct loop *lo
 
   if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
     goto fail;
 
   comp_mode = iv0.extend_mode;
   mode = iv0.mode;
-  size = GET_MODE_BITSIZE (mode);
+  size = GET_MODE_PRECISION (mode);
   get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
   mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
   mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
 
   if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
     goto fail;
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 211858)
+++ gcc/varasm.c	(working copy)
@@ -1466,13 +1466,13 @@ assemble_asm (tree string)
 /* Write the address of the entity given by SYMBOL to SEC.  */
 void
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
   assemble_align (POINTER_SIZE);
-  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (symbol, (POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT, POINTER_SIZE, 1);
 }
 
 /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
    not) section for PRIORITY.  */
 section *
 get_cdtor_priority_section (int priority, bool constructor_p)
@@ -2619,13 +2619,13 @@ default_assemble_integer (rtx x ATTRIBUT
 			  unsigned int size ATTRIBUTE_UNUSED,
 			  int aligned_p ATTRIBUTE_UNUSED)
 {
   const char *op = integer_asm_op (size, aligned_p);
   /* Avoid GAS bugs for large values.  Specifically negative values whose
      absolute value fits in a bfd_vma, but not in a bfd_signed_vma.  */
-  if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
+  if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
     return false;
   return op && (assemble_integer_with_op (op, x), true);
 }
 
 /* Assemble the integer constant X into an object of SIZE bytes.  ALIGN is
    the alignment of the integer in bits.  Return 1 if we were able to output
@@ -5750,15 +5750,15 @@ dump_tm_clone_pairs (vec<tm_alias_pair> 
 	  switch_to_section (targetm.asm_out.tm_clone_table_section ());
 	  assemble_align (POINTER_SIZE);
 	  switched = true;
 	}
 
       assemble_integer (XEXP (DECL_RTL (src), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
       assemble_integer (XEXP (DECL_RTL (dst), 0),
-			POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+			POINTER_SIZE_UNITS, POINTER_SIZE, 1);
     }
 }
 
 /* Provide a default for the tm_clone_table section.  */
 
 section *
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 211858)
+++ gcc/tree-core.h	(working copy)
@@ -1147,13 +1155,13 @@ enum omp_clause_map_kind
   OMP_CLAUSE_MAP_ALLOC,
   OMP_CLAUSE_MAP_TO,
   OMP_CLAUSE_MAP_FROM,
   OMP_CLAUSE_MAP_TOFROM,
   /* The following kind is an internal only map kind, used for pointer based
      array sections.  OMP_CLAUSE_SIZE for these is not the pointer size,
-     which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias.  */
+     which is implicitly POINTER_SIZE_UNITS, but the bias.  */
   OMP_CLAUSE_MAP_POINTER,
   /* Also internal, behaves like OMP_CLAUS_MAP_TO, but additionally any
      OMP_CLAUSE_MAP_POINTER records consecutive after it which have addresses
      falling into that range will not be ignored if OMP_CLAUSE_MAP_TO_PSET
      wasn't mapped already.  */
   OMP_CLAUSE_MAP_TO_PSET,

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 2/4] change specific int128 -> generic intN
  2014-06-21 20:17   ` Joseph S. Myers
  2014-06-24  5:51     ` DJ Delorie
  2014-06-24 23:32     ` [patch 1/4] " DJ Delorie
@ 2014-06-24 23:38     ` DJ Delorie
  2014-06-24 23:39     ` [patch 3/4] " DJ Delorie
  2014-06-24 23:42     ` [patch 4/4] " DJ Delorie
  4 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-24 23:38 UTC (permalink / raw)
  To: gcc-patches


Part 2 of 4, split from the full patch.  This is the main __int128 ->
__intN conversion patch.

(note: I haven't adjusted the __STRICT_ANSI__ conditionals yet, I'm
just splitting up the previously emailed patch)

gcc/
	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __int128 for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	(initialize_sizetypes): Support __intN types.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.


gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Check for all __intN types, not just
	__int128.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.

gcc/lto/
	* lto-lang.c (lto_build_c_type_nodes): Check intN types for
	size-type as well.
	(lto_init): Initialize all intN types, not just int128.

* libstdc++-v3/
	* include/bits/cpp_type_traits.h: Add support for __intN types.
	* include/c_global/cstdlib: Likewise.
	* include/c_std/cstdlib: Likewise.
	* include/std/limits: Likewise.
	* include/std/type_traits: Likewise.
	* src/c++11/limits.cc: Likewise.

Index: libstdc++-v3/src/c++11/limits.cc
===================================================================
--- libstdc++-v3/src/c++11/limits.cc	(revision 211858)
+++ libstdc++-v3/src/c++11/limits.cc	(working copy)
@@ -385,60 +385,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   const bool numeric_limits<unsigned long long>::is_bounded;
   const bool numeric_limits<unsigned long long>::is_modulo;
   const bool numeric_limits<unsigned long long>::traps;
   const bool numeric_limits<unsigned long long>::tinyness_before;
   const float_round_style numeric_limits<unsigned long long>::round_style;
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  const bool numeric_limits<__int128>::is_specialized;
-  const int  numeric_limits<__int128>::digits;
-  const int  numeric_limits<__int128>::digits10;
-  const int  numeric_limits<__int128>::max_digits10;
-  const bool numeric_limits<__int128>::is_signed;
-  const bool numeric_limits<__int128>::is_integer;
-  const bool numeric_limits<__int128>::is_exact;
-  const int  numeric_limits<__int128>::radix;
-  const int  numeric_limits<__int128>::min_exponent;
-  const int  numeric_limits<__int128>::min_exponent10;
-  const int  numeric_limits<__int128>::max_exponent;
-  const int  numeric_limits<__int128>::max_exponent10;
-  const bool numeric_limits<__int128>::has_infinity;
-  const bool numeric_limits<__int128>::has_quiet_NaN;
-  const bool numeric_limits<__int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<__int128>::has_denorm;
-  const bool numeric_limits<__int128>::has_denorm_loss;
-  const bool numeric_limits<__int128>::is_iec559;
-  const bool numeric_limits<__int128>::is_bounded;
-  const bool numeric_limits<__int128>::is_modulo;
-  const bool numeric_limits<__int128>::traps;
-  const bool numeric_limits<__int128>::tinyness_before;
-  const float_round_style numeric_limits<__int128>::round_style;
-
-  const bool numeric_limits<unsigned __int128>::is_specialized;
-  const int  numeric_limits<unsigned __int128>::digits;
-  const int  numeric_limits<unsigned __int128>::digits10;
-  const int  numeric_limits<unsigned __int128>::max_digits10;
-  const bool numeric_limits<unsigned __int128>::is_signed;
-  const bool numeric_limits<unsigned __int128>::is_integer;
-  const bool numeric_limits<unsigned __int128>::is_exact;
-  const int  numeric_limits<unsigned __int128>::radix;
-  const int  numeric_limits<unsigned __int128>::min_exponent;
-  const int  numeric_limits<unsigned __int128>::min_exponent10;
-  const int  numeric_limits<unsigned __int128>::max_exponent;
-  const int  numeric_limits<unsigned __int128>::max_exponent10;
-  const bool numeric_limits<unsigned __int128>::has_infinity;
-  const bool numeric_limits<unsigned __int128>::has_quiet_NaN;
-  const bool numeric_limits<unsigned __int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<unsigned __int128>::has_denorm;
-  const bool numeric_limits<unsigned __int128>::has_denorm_loss;
-  const bool numeric_limits<unsigned __int128>::is_iec559;
-  const bool numeric_limits<unsigned __int128>::is_bounded;
-  const bool numeric_limits<unsigned __int128>::is_modulo;
-  const bool numeric_limits<unsigned __int128>::traps;
-  const bool numeric_limits<unsigned __int128>::tinyness_before;
-  const float_round_style numeric_limits<unsigned __int128>::round_style;
+#if !defined(__STRICT_ANSI__)
+#define INT_N(__INT_N_TYPE)							\
+  const bool numeric_limits<__INT_N_TYPE>::is_specialized;			\
+  const int  numeric_limits<__INT_N_TYPE>::digits;				\
+  const int  numeric_limits<__INT_N_TYPE>::digits10;				\
+  const int  numeric_limits<__INT_N_TYPE>::max_digits10;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_signed;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_integer;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_exact;				\
+  const int  numeric_limits<__INT_N_TYPE>::radix;				\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent10;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent10;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_infinity;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_quiet_NaN;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_signaling_NaN;			\
+  const float_denorm_style numeric_limits<__INT_N_TYPE>::has_denorm;		\
+  const bool numeric_limits<__INT_N_TYPE>::has_denorm_loss;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_iec559;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_bounded;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_modulo;				\
+  const bool numeric_limits<__INT_N_TYPE>::traps;				\
+  const bool numeric_limits<__INT_N_TYPE>::tinyness_before;			\
+  const float_round_style numeric_limits<__INT_N_TYPE>::round_style;		\
+  									\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_specialized;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits10;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_digits10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_signed;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_integer;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_exact;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::radix;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent10;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_infinity;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_quiet_NaN;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_signaling_NaN;		\
+  const float_denorm_style numeric_limits<unsigned __INT_N_TYPE>::has_denorm;	\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_denorm_loss;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_iec559;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_bounded;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_modulo;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::traps;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::tinyness_before;		\
+  const float_round_style numeric_limits<unsigned __INT_N_TYPE>::round_style;
+
+#ifdef __GLIBCXX_USE_INT_N_0
+  INT_N (__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+  INT_N (__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+  INT_N (__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+  INT_N (__GLIBCXX_TYPE_INT_N_3)
+#endif
 #endif
 
   // float
   const bool numeric_limits<float>::is_specialized;
   const int  numeric_limits<float>::digits;
   const int  numeric_limits<float>::digits10;
Index: libstdc++-v3/include/std/type_traits
===================================================================
--- libstdc++-v3/include/std/type_traits	(revision 211858)
+++ libstdc++-v3/include/std/type_traits	(working copy)
@@ -236,19 +236,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 
   template<>
     struct __is_integral_helper<unsigned long long>
     : public true_type { };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  // Conditionalizing on __STRICT_ANSI__ here will break any port that
+  // uses one of these types for size_t.
+#if defined(__GLIBCXX_USE_INT_N_0)
   template<>
-    struct __is_integral_helper<__int128>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
     : public true_type { };
 
   template<>
-    struct __is_integral_helper<unsigned __int128>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
     : public true_type { };
 #endif
 
   /// is_integral
   template<typename _Tp>
     struct is_integral
@@ -1598,16 +1627,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
   template<>
     struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_USE_INT_N_0)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
   template<>
-    struct __make_unsigned<__int128>
-    { typedef unsigned __int128 __type; };
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
@@ -1695,16 +1739,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
   template<>
     struct __make_signed<char32_t> : __make_signed<uint_least32_t>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_USE_INT_N_0)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
+    { typedef __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_1>
+    { typedef __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_2>
+    { typedef __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
   template<>
-    struct __make_signed<unsigned __int128>
-    { typedef __int128 __type; };
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
+    { typedef __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
Index: libstdc++-v3/include/std/limits
===================================================================
--- libstdc++-v3/include/std/limits	(revision 211858)
+++ libstdc++-v3/include/std/limits	(working copy)
@@ -1396,159 +1396,191 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
       static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
       static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 
        = round_toward_zero;
     };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  /// numeric_limits<__int128> specialization.
-  template<>
-    struct numeric_limits<__int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (__int128); }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (__int128); }
-
-#if __cplusplus >= 201103L
-      static constexpr __int128
-      lowest() noexcept { return min(); }
-#endif
-
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (__int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (__int128);
-#if __cplusplus >= 201103L
-      static constexpr int max_digits10 = 0;
-#endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
+#if !defined(__STRICT_ANSI__)
 
-      static _GLIBCXX_USE_CONSTEXPR bool traps
-       = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
+#define __INT_N(TYPE, MIN, MAX, UMAX, BITSIZE, EXT, UEXT)			\
+  template<> 									\
+    struct numeric_limits<TYPE> 						\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      min() _GLIBCXX_USE_NOEXCEPT { return MIN; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      max() _GLIBCXX_USE_NOEXCEPT { return MAX; } 				\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE - 1; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = (BITSIZE - 1) * 643L / 2136; 						\
+      										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      EXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps 					\
+       = __glibcxx_integral_traps; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
+    }; 										\
+ 										\
+  template<> 									\
+    struct numeric_limits<unsigned TYPE> 					\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      min() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      max() _GLIBCXX_USE_NOEXCEPT { return UMAX; } 				\
+ 										\
+      UEXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = BITSIZE * 643L / 2136; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; 	\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
     };
 
-  /// numeric_limits<unsigned __int128> specialization.
-  template<>
-    struct numeric_limits<unsigned __int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (unsigned __int128); }
-
 #if __cplusplus >= 201103L
-      static constexpr unsigned __int128
-      lowest() noexcept { return min(); }
-#endif
 
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (unsigned __int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (unsigned __int128);
-#if __cplusplus >= 201103L
+#define __INT_N_201103(TYPE)							\
+      static constexpr TYPE 							\
+      lowest() noexcept { return min(); }					\
       static constexpr int max_digits10 = 0;
-#endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
 
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
+#define __INT_N_U201103(TYPE)							\
+      static constexpr unsigned TYPE 						\
+      lowest() noexcept { return min(); }					\
+      static constexpr int max_digits10 = 0;
 
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
+#else
+#define __INT_N_201103(TYPE)
+#define __INT_N_U201103(TYPE)
+#endif
+
+#ifdef __GLIBCXX_USE_INT_N_0
+  __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_MIN_INT_N_0, __GLIBCXX_MAX_INT_N_0,
+	  __GLIBCXX_UMAX_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+  __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_MIN_INT_N_1, __GLIBCXX_MAX_INT_N_1,
+	   __GLIBCXX_UMAX_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+  __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_MIN_INT_N_2, __GLIBCXX_MAX_INT_N_2,
+	   __GLIBCXX_UMAX_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2))
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+  __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_MIN_INT_N_3, __GLIBCXX_MAX_INT_N_3,
+	   __GLIBCXX_UMAX_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3))
+#endif
+
+#undef __INT_N
+#undef __INT_N_201103
+#undef __INT_N_U201103
 
-      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
-    };
 #endif
 
   /// numeric_limits<float> specialization.
   template<>
     struct numeric_limits<float>
     {
Index: libstdc++-v3/include/c_std/cstdlib
===================================================================
--- libstdc++-v3/include/c_std/cstdlib	(revision 211858)
+++ libstdc++-v3/include/c_std/cstdlib	(working copy)
@@ -166,15 +166,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_USE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
   inline ldiv_t
   div(long __i, long __j) { return ldiv(__i, __j); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
Index: libstdc++-v3/include/bits/cpp_type_traits.h
===================================================================
--- libstdc++-v3/include/bits/cpp_type_traits.h	(revision 211858)
+++ libstdc++-v3/include/bits/cpp_type_traits.h	(working copy)
@@ -138,13 +138,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       enum { __value = 0 };
       typedef __false_type __type;
     };
 
   // Thirteen specializations (yes there are eleven standard integer
   // types; <em>long long</em> and <em>unsigned long long</em> are
-  // supported as extensions)
+  // supported as extensions).  Up to four target-specific __int<N>
+  // types are supported as well.
   template<>
     struct __is_integer<bool>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
@@ -248,12 +249,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_integer<unsigned long long>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
 
+#define __INT_N(TYPE) 			\
+  template<>				\
+    struct __is_integer<TYPE>		\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };					\
+  template<>				\
+    struct __is_integer<unsigned TYPE>	\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };
+
+#ifdef __GLIBCXX_USE_INT_N_0
+__INT_N(__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_1
+__INT_N(__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_2
+__INT_N(__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_USE_INT_N_3
+__INT_N(__GLIBCXX_TYPE_INT_N_3)
+#endif
+
+#undef __INT_N
+
   //
   // Floating point types
   //
   template<typename _Tp>
     struct __is_floating
     {
Index: libstdc++-v3/include/c_global/cstdlib
===================================================================
--- libstdc++-v3/include/c_global/cstdlib	(revision 211858)
+++ libstdc++-v3/include/c_global/cstdlib	(working copy)
@@ -171,17 +171,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_USE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_USE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #if _GLIBCXX_USE_C99
 
 #undef _Exit
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	(revision 211858)
+++ gcc/machmode.h	(working copy)
@@ -342,7 +342,19 @@ extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  unsigned int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+/* This is also in tree.h.  genmodes.c guarantees the're sorted from
+   smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(revision 211858)
+++ gcc/c-family/c-pretty-print.c	(working copy)
@@ -917,12 +917,14 @@ pp_c_void_constant (c_pretty_printer *pp
 
 /* Pretty-print an INTEGER literal.  */
 
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
+  int idx;
+
   /* We are going to compare the type of I to other types using
      pointer comparison so we need to use its canonical type.  */
   tree type =
     TYPE_CANONICAL (TREE_TYPE (i))
     ? TYPE_CANONICAL (TREE_TYPE (i))
     : TREE_TYPE (i);
@@ -947,15 +949,23 @@ pp_c_integer_constant (c_pretty_printer 
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
-  else if (type == int128_integer_type_node
-           || type == int128_unsigned_type_node)
-    pp_string (pp, "I128");
+  else for (idx = 0; idx < NUM_INT_N_ENTS; idx ++)
+    if (int_n_enabled_p[idx])
+      {
+	char buf[2+20];
+	if (type == int_n_trees[idx].signed_type
+	    || type == int_n_trees[idx].unsigned_type)
+	  {
+	    sprintf (buf, "I%d", int_n_data[idx].bitsize);
+	    pp_string (pp, buf);
+	  }
+      }
 }
 
 /* Print out a CHARACTER literal.  */
 
 static void
 pp_c_character_constant (c_pretty_printer *pp, tree c)
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 211858)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -775,12 +775,14 @@ cpp_iec_559_complex_value (void)
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
 {
+  int i;
+
   /* -undef turns off target-specific built-ins.  */
   if (flag_undef)
     return;
 
   define_language_independent_builtin_macros (pfile);
 
@@ -844,12 +846,47 @@ c_cpp_builtins (cpp_reader *pfile)
   builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node);
   builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__",
 			      underlying_wchar_type_node);
   builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", wint_type_node);
   builtin_define_type_max ("__PTRDIFF_MAX__", ptrdiff_type_node);
   builtin_define_type_max ("__SIZE_MAX__", size_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[35+20+20];
+	char buf_min[15+20];
+	char buf_max[15+20];
+
+	sprintf(buf_min, "__INT%d_MIN__", int_n_data[i].bitsize);
+	sprintf(buf_max, "__INT%d_MAX__", int_n_data[i].bitsize);
+	builtin_define_type_minmax (buf_min, buf_max,
+				    int_n_trees[i].signed_type);
+	sprintf(buf_max, "__UINT%d_MAX__", int_n_data[i].bitsize);
+	builtin_define_type_max (buf_max,
+				 int_n_trees[i].unsigned_type);
+
+	/* These are used to configure the C++ library.  */
+
+	sprintf (buf, "__GLIBCXX_USE_INT_N_%d", i);
+	if (!flag_iso || int_n_data[i].bitsize == POINTER_SIZE)
+	  builtin_define_with_int_value (buf, 1);
+
+	sprintf (buf, "__GLIBCXX_TYPE_INT_N_%d=__int%d", i, int_n_data[i].bitsize);
+	cpp_define (parse_in, buf);
+
+	sprintf (buf, "__GLIBCXX_BITSIZE_INT_N_%d=%d", i, int_n_data[i].bitsize);
+	cpp_define (parse_in, buf);
+
+	sprintf(buf_min, "__GLIBCXX_MIN_INT_N_%d", i);
+	sprintf(buf_max, "__GLIBCXX_MAX_INT_N_%d", i);
+	builtin_define_type_minmax (buf_min, buf_max,
+				    int_n_trees[i].signed_type);
+	sprintf(buf_max, "__GLIBCXX_UMAX_INT_N_%d", i);
+	builtin_define_type_max (buf_max,
+				 int_n_trees[i].unsigned_type);
+      }
 
   /* stdint.h and the testsuite need to know these.  */
   builtin_define_stdint_macros ();
 
   /* Provide information for library headers to determine whether to
      define macros such as __STDC_IEC_559__ and
@@ -993,15 +1030,20 @@ c_cpp_builtins (cpp_reader *pfile)
   else if (flag_stack_protect == 1)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201307");
 
-  if (int128_integer_type_node != NULL_TREE)
-    builtin_define_type_sizeof ("__SIZEOF_INT128__",
-			        int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[15+20];
+	sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+	builtin_define_type_sizeof (buf,
+				    int_n_trees[i].signed_type);
+      }
   builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
   builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
   builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
 			      unsigned_ptrdiff_type_node);
 
   /* A straightforward target hook doesn't work, because of problems
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 211858)
+++ gcc/c-family/c-common.c	(working copy)
@@ -58,18 +58,16 @@ cpp_reader *parse_in;		/* Declared in c-
 
    INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
 
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
-	tree int128_integer_type_node;
 
 	tree short_unsigned_type_node;
 	tree long_unsigned_type_node;
 	tree long_long_unsigned_type_node;
-	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
 	tree truthvalue_false_node;
 	tree truthvalue_true_node;
 
 	tree ptrdiff_type_node;
@@ -461,13 +459,12 @@ const struct c_common_resword c_common_r
   { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
   { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
-  { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
   { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
@@ -3438,12 +3435,14 @@ check_case_bounds (location_t loc, tree 
 /* Return an integer type with BITS bits of precision,
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 tree
 c_common_type_for_size (unsigned int bits, int unsignedp)
 {
+  int i;
+
   if (bits == TYPE_PRECISION (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (bits == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 
@@ -3454,16 +3453,17 @@ c_common_type_for_size (unsigned int bit
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (bits == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
-  if (int128_integer_type_node
-      && bits == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& bits == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
   if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -3521,12 +3521,13 @@ tree registered_builtin_types;
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
+  int i;
 
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -3537,15 +3538,17 @@ c_common_type_for_mode (enum machine_mod
   if (mode == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
-  if (int128_integer_type_node
-      && mode == TYPE_MODE (int128_integer_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& mode == int_n_data[i].m)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
 		     : widest_integer_literal_type_node;
 
   if (mode == QImode)
@@ -3737,12 +3740,13 @@ c_common_signed_type (tree type)
    signed according to UNSIGNEDP.  */
 
 tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   /* This block of code emulates the behavior of the old
      c_common_unsigned_type. In particular, it returns
      long_unsigned_type_node if passed a long, even when a int would
      have the same size. This is necessary for warnings to work
      correctly in archs where sizeof(int) == sizeof(long) */
@@ -3755,16 +3759,20 @@ c_common_signed_or_unsigned_type (int un
   if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
-  if (int128_integer_type_node
-      && (type1 == int128_integer_type_node
-	  || type1 == int128_unsigned_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
     return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3873,15 +3881,20 @@ c_common_signed_or_unsigned_type (int un
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -3902,12 +3915,14 @@ c_common_signed_or_unsigned_type (int un
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 
 tree
 c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
 {
+  int i;
+
   /* Extended integer types of the same width as a standard type have
      lesser rank, so those of the same width as int promote to int or
      unsigned int and are valid for printf formats expecting int or
      unsigned int.  To avoid such special cases, avoid creating
      extended integer types for bit-fields if a standard integer type
      is available.  */
@@ -3919,16 +3934,17 @@ c_build_bitfield_integer_type (unsigned 
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (width == TYPE_PRECISION (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node
-      && width == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& width == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -5339,12 +5355,13 @@ c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5355,19 +5372,25 @@ c_common_nodes_and_builtins (void)
   if (c_dialect_cxx ())
     record_builtin_type (RID_SIGNED, NULL, integer_type_node);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
-  if (int128_integer_type_node != NULL_TREE)
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
     {
-      record_builtin_type (RID_INT128, "__int128",
-			   int128_integer_type_node);
-      record_builtin_type (RID_MAX, "__int128 unsigned",
-			   int128_unsigned_type_node);
+      char name[25];
+
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), xstrdup (name),
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, xstrdup (name),
+			   int_n_trees[i].unsigned_type);
     }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -5397,12 +5420,14 @@ c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intSI_type_node));
   lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  /* Note that this is different than the __int128 type that's part of
+     the generic __intN support.  */
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
 					   get_identifier ("__int128_t"),
 					   intTI_type_node));
 #endif
@@ -11695,13 +11720,12 @@ keyword_begins_type_specifier (enum rid 
     case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-    case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
     case RID_SHORT:
     case RID_SIGNED:
     case RID_DFLOAT32:
     case RID_DFLOAT64:
@@ -11718,12 +11742,16 @@ keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 211858)
+++ gcc/c-family/c-common.h	(working copy)
@@ -88,13 +88,12 @@ enum rid
   /* C (reserved and imaginary types not implemented, so any use is a
      syntax error) */
   RID_IMAGINARY,
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
   RID_ENUM,    RID_STRUCT, RID_UNION,    RID_IF,     RID_ELSE,
   RID_WHILE,   RID_DO,     RID_FOR,      RID_SWITCH, RID_CASE,
   RID_DEFAULT, RID_BREAK,  RID_CONTINUE, RID_RETURN, RID_GOTO,
   RID_SIZEOF,
 
   /* C extensions */
@@ -185,12 +184,29 @@ enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN_t keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13_t.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 211858)
+++ gcc/c/c-parser.c	(working copy)
@@ -110,12 +110,22 @@ c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      /* We always create the symbols but they aren't always supported.  */
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (xstrdup (name));
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 \f
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -485,13 +495,12 @@ c_token_starts_typename (c_token *token)
 	}
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -513,12 +522,16 @@ c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -643,13 +656,12 @@ c_token_starts_declspecs (c_token *token
 	case RID_INLINE:
 	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -672,12 +684,16 @@ c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2149,13 +2165,13 @@ c_parser_static_assert_declaration_no_se
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
      __auto_type
-     __int128
+     __intN
      _Decimal32
      _Decimal64
      _Decimal128
      _Fract
      _Accum
      _Sat
@@ -2303,13 +2319,12 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_AUTO_TYPE:
 	  if (!auto_type_ok)
 	    goto out;
 	  /* Fall through.  */
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -2319,12 +2334,16 @@ c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3739,13 +3758,12 @@ c_parser_attribute_any_word (c_parser *p
       bool ok;
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_SHORT:
 	case RID_INLINE:
@@ -3769,12 +3787,16 @@ c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8926,13 +8948,12 @@ c_parser_objc_selector (c_parser *parser
     case RID_ASM:
     case RID_SIZEOF:
     case RID_TYPEOF:
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
-    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
     case RID_SIGNED:
     case RID_RESTRICT:
     case RID_COMPLEX:
@@ -8947,12 +8968,16 @@ c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	(revision 211858)
+++ gcc/c/c-tree.h	(working copy)
@@ -196,13 +196,13 @@ enum c_typespec_keyword {
   cts_none,
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
-  cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -263,12 +263,14 @@ struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 211858)
+++ gcc/c/c-decl.c	(working copy)
@@ -9195,16 +9195,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<long%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		  error_at (loc,
-			    ("both %<long%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<long%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<long%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9243,16 +9244,17 @@ declspecs_add_type (location_t loc, stru
 			  ("both %<short%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		error_at (loc,
-			  ("both %<short%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<short%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<short%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9420,17 +9422,18 @@ declspecs_add_type (location_t loc, stru
 		}
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
 	      pedwarn (loc, OPT_Wpedantic,
 		       "ISO C does not support saturating types");
-	      if (specs->typespec_word == cts_int128)
+	      if (specs->typespec_word == cts_int_n)
 	        {
 		  error_at (loc,
-			    ("both %<_Sat%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<_Sat%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	        }
 	      else if (specs->typespec_word == cts_auto_type)
 		error_at (loc,
 			  ("both %<_Sat%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
@@ -9488,13 +9491,13 @@ declspecs_add_type (location_t loc, stru
 
 	  return specs;
 	}
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+	     "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
 	     "__auto_type".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
 			"two or more data types in declaration specifiers");
 	      return specs;
@@ -9529,37 +9532,44 @@ declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_auto_type;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
-	    case RID_INT128:
-	      if (int128_integer_type_node == NULL_TREE)
-		{
-		  error_at (loc, "%<__int128%> is not supported for this target");
-		  return specs;
-		}
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      specs->int_n_idx = i - RID_INT_N_0;
 	      if (!in_system_header_at (input_location))
 		pedwarn (loc, OPT_Wpedantic,
-			 "ISO C does not support %<__int128%> type");
+			 "ISO C does not support %<__int%d%> types",
+			 int_n_data[specs->int_n_idx].bitsize);
 
 	      if (specs->long_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<long%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<long%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->saturating_p)
 		error_at (loc,
-			  ("both %<_Sat%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<_Sat%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->short_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<short%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<short%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
+	      else if (! int_n_enabled_p [specs->int_n_idx])
+		error_at (loc,
+			  "%<__int%d%> is not supported on this target",
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else
 		{
-		  specs->typespec_word = cts_int128;
+		  specs->typespec_word = cts_int_n;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
@@ -10121,18 +10131,18 @@ finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
-    case cts_int128:
+    case cts_int_n:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       specs->type = (specs->unsigned_p
-		     ? int128_unsigned_type_node
-		     : int128_integer_type_node);
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
       if (specs->complex_p)
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 211858)
+++ gcc/tree.c	(working copy)
@@ -234,12 +234,15 @@ static unsigned int type_hash_list (cons
 static unsigned int attribute_hash_list (const_tree, hashval_t);
 static bool decls_same_for_odr (tree decl1, tree decl2);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+bool int_n_enabled_p[NUM_INT_N_ENTS];
+struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9485,26 +9488,31 @@ make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (size == LONG_TYPE_SIZE)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
-  if (size == 128 && int128_integer_type_node)
-    return (unsignedp ? int128_unsigned_type_node
-            : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize
+	&& int_n_enabled_p[i])
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
@@ -9614,12 +9622,14 @@ build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9641,23 +9651,26 @@ build_common_tree_nodes (bool signed_cha
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-#if HOST_BITS_PER_WIDE_INT >= 64
-    /* TODO: This isn't correct, but as logic depends at the moment on
-       host's instead of target's wide-integer.
-       If there is a target not supporting TImode, but has an 128-bit
-       integer-scalar register, this target check needs to be adjusted. */
-    if (targetm.scalar_mode_supported_p (TImode))
-      {
-        int128_integer_type_node = make_signed_type (128);
-        int128_unsigned_type_node = make_unsigned_type (128);
-      }
-#endif
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+      int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+
+      if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE)
+	{
+	  integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
+	  integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
+	}
+    }
 
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
   TYPE_PRECISION (boolean_type_node) = 1;
@@ -9670,13 +9683,30 @@ build_common_tree_nodes (bool signed_cha
     size_type_node = long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
     size_type_node = long_long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
     size_type_node = short_unsigned_type_node;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		size_type_node = int_n_trees[i].unsigned_type;
+	      }
+	  }
+      if (size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
      when possible.  */
   intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
   intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
   intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 211858)
+++ gcc/tree.h	(working copy)
@@ -3417,14 +3417,12 @@ tree_operand_check_code (const_tree __t,
 #define integer_type_node		integer_types[itk_int]
 #define unsigned_type_node		integer_types[itk_unsigned_int]
 #define long_integer_type_node		integer_types[itk_long]
 #define long_unsigned_type_node		integer_types[itk_unsigned_long]
 #define long_long_integer_type_node	integer_types[itk_long_long]
 #define long_long_unsigned_type_node	integer_types[itk_unsigned_long_long]
-#define int128_integer_type_node	integer_types[itk_int128]
-#define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\
   ((NODE) == error_mark_node					\
    || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
@@ -4768,7 +4766,18 @@ extern tree get_inner_reference (tree, H
 				 bool);
 
 /* Return a tree representing the lower bound of the array mentioned in
    EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
 extern tree array_ref_low_bound (tree);
 
+
+struct GTY(()) int_n_trees_t {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+};
+
+/* This is also in machmode.h */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern GTY(()) struct int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 211858)
+++ gcc/toplev.c	(working copy)
@@ -1870,12 +1870,27 @@ finalize (bool no_backend)
     dump_profile_report ();
 
   /* Language-specific end of compilation actions.  */
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  /* As a special exception, we always want __int128 enabled if possible.  */
+  if (bitsize == 128)
+    return false;
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || (bitsize == LONG_LONG_TYPE_SIZE && LONG_LONG_TYPE_SIZE < GET_MODE_BITSIZE (TImode)))
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
 do_compile (void)
 {
   /* Initialize timing first.  The C front ends read the main file in
      the post_options hook, and C++ does file timings.  */
@@ -1885,20 +1900,33 @@ do_compile (void)
 
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
 	 predefined macros, such as __LDBL_MAX__, for targets using non
 	 default FP formats.  */
       init_adjust_machine_modes ();
       init_derived_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize)
+	    && int_n_data[i].bitsize <= HOST_BITS_PER_WIDE_INT * 2)
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
 	backend_init ();
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 211858)
+++ gcc/cp/typeck.c	(working copy)
@@ -267,12 +267,13 @@ original_type (tree t)
 static tree
 cp_common_type (tree t1, tree t2)
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
   tree attributes;
+  int i;
 
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -361,22 +362,25 @@ cp_common_type (tree t1, tree t2)
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
-      if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
 	{
-	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-		    ? int128_unsigned_type_node
-		    : int128_integer_type_node);
-	  return build_type_attribute_variant (t, attributes);
+	  if (int_n_enabled_p [i]
+	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			       int_n_trees[i].signed_type)
+		  || same_type_p (TYPE_MAIN_VARIANT (t2),
+				  int_n_trees[i].signed_type)))
+	    {
+	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+			? int_n_trees[i].unsigned_type
+			: int_n_trees[i].signed_type);
+	      return build_type_attribute_variant (t, attributes);
+	    }
 	}
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
 	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 211858)
+++ gcc/cp/decl.c	(working copy)
@@ -8749,13 +8749,13 @@ grokdeclarator (const cp_declarator *dec
 		enum decl_context decl_context,
 		int initialized,
 		tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int explicit_int128 = 0;
+  int explicit_intN = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
 
   tree typedef_decl = NULL_TREE;
@@ -8821,13 +8821,13 @@ grokdeclarator (const cp_declarator *dec
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
   short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
-  explicit_int128 = declspecs->explicit_int128_p;
+  explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
     funcdef_flag = true, decl_context = FIELD;
@@ -9162,22 +9162,26 @@ grokdeclarator (const cp_declarator *dec
 
       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
 
-  if (explicit_int128)
+  if (explicit_intN)
     {
-      if (int128_integer_type_node == NULL_TREE)
-	{
-	  error ("%<__int128%> is not supported by this target");
-	  explicit_int128 = false;
-	}
+      if (! int_n_enabled_p[declspecs->int_n_idx])
+       {
+         error ("%<__int%d%> is not supported by this target",
+		int_n_data[declspecs->int_n_idx].bitsize);
+         explicit_intN = false;
+       }
+#if 0 /* temporary - DJ */
       else if (pedantic && ! in_system_header_at (input_location))
-	pedwarn (input_location, OPT_Wpedantic,
-		 "ISO C++ does not support %<__int128%> for %qs", name);
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ does not support %<__int%d%> for %qs",
+		int_n_data[declspecs->int_n_idx].bitsize,  name);
+#endif
     }
 
   /* Now process the modifiers that were specified
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
@@ -9203,13 +9207,13 @@ grokdeclarator (const cp_declarator *dec
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
       else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
-      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
       else if (long_p && short_p)
 	error ("%<long%> and %<short%> specified together for %qs", name);
       else if (type == char16_type_node || type == char32_type_node)
@@ -9219,13 +9223,13 @@ grokdeclarator (const cp_declarator *dec
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
 		       name);
 	      if (flag_pedantic_errors)
 		ok = 0;
@@ -9261,14 +9265,14 @@ grokdeclarator (const cp_declarator *dec
 	     `signed int' cannot be so controlled.  */
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
-	type = int128_unsigned_type_node;
+      if (explicit_intN)
+	type = int_n_trees[declspecs->int_n_idx].unsigned_type;
       else if (longlong)
 	type = long_long_unsigned_type_node;
       else if (long_p)
 	type = long_unsigned_type_node;
       else if (short_p)
 	type = short_unsigned_type_node;
@@ -9278,14 +9282,14 @@ grokdeclarator (const cp_declarator *dec
 	type = unsigned_type_for (type);
       else
 	type = unsigned_type_node;
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
-  else if (explicit_int128)
-    type = int128_integer_type_node;
+  else if (explicit_intN)
+    type = int_n_trees[declspecs->int_n_idx].signed_type;
   else if (longlong)
     type = long_long_integer_type_node;
   else if (long_p)
     type = long_integer_type_node;
   else if (short_p)
     type = short_integer_type_node;
@@ -9295,13 +9299,13 @@ grokdeclarator (const cp_declarator *dec
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
 	error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
 	 "complex double", but if any modifiers at all are specified it is
 	 the complex form of TYPE.  E.g, "complex short" is
 	 "complex short int".  */
-      else if (defaulted_int && ! longlong && ! explicit_int128
+      else if (defaulted_int && ! longlong && ! explicit_intN
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
 	type = complex_integer_type_node;
       else if (type == float_type_node)
 	type = complex_float_type_node;
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c	(revision 211858)
+++ gcc/cp/rtti.c	(working copy)
@@ -1506,31 +1506,44 @@ emit_support_tinfo_1 (tree bltn)
 
 void
 emit_support_tinfos (void)
 {
   /* Dummy static variable so we can put nullptr in the array; it will be
      set before we actually start to walk the array.  */
-  static tree *const fundamentals[] =
+  static tree * fundamentals[] =
   {
     &void_type_node,
     &boolean_type_node,
     &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
-    &int128_integer_type_node, &int128_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
+#define FUND_INT_N_IDX 22
+    // These eight are for intN_t nodes
+    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
+    &nullptr_type_node, &nullptr_type_node, &nullptr_type_node, &nullptr_type_node,
     &nullptr_type_node,
     0
   };
-  int ix;
+  int ix, i;
   tree bltn_type, dtor;
 
+  ix = FUND_INT_N_IDX;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	fundamentals [ix++] = &int_n_trees[i].signed_type;
+	fundamentals [ix++] = &int_n_trees[i].unsigned_type;
+      }
+  fundamentals [ix++] = &nullptr_type_node;
+  fundamentals [ix++] = 0;
+
   push_abi_namespace ();
   bltn_type = xref_tag (class_type,
 			get_identifier ("__fundamental_type_info"),
 			/*tag_scope=*/ts_current, false);
   pop_abi_namespace ();
   if (!COMPLETE_TYPE_P (bltn_type))
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 211858)
+++ gcc/cp/parser.c	(working copy)
@@ -936,13 +936,12 @@ cp_lexer_next_token_is_decl_specifier_ke
     case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
-    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
       /* GNU extensions.  */ 
@@ -951,12 +950,16 @@ cp_lexer_next_token_is_decl_specifier_ke
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
       return true;
 
     default:
+      if (token->keyword >= RID_FIRST_INT_N
+	  && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Returns TRUE iff the token T begins a decltype type.  */
 
@@ -14502,12 +14505,13 @@ static tree
 cp_parser_simple_type_specifier (cp_parser* parser,
 				 cp_decl_specifier_seq *decl_specs,
 				 cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
+  int idx;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* If we're looking at a keyword, things are easy.  */
   switch (token->keyword)
@@ -14535,18 +14539,25 @@ cp_parser_simple_type_specifier (cp_pars
       break;
     case RID_INT:
       if (decl_specs)
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
-    case RID_INT128:
-      if (!int128_integer_type_node)
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
+      idx = token->keyword - RID_INT_N_0;
+      if (! int_n_enabled_p [idx])
 	break;
       if (decl_specs)
-        decl_specs->explicit_int128_p = true;
-      type = int128_integer_type_node;
+	{
+	  decl_specs->explicit_intN_p = true;
+	  decl_specs->int_n_idx = idx;
+	}
+      type = int_n_trees [idx].signed_type;
       break;
     case RID_LONG:
       if (decl_specs)
 	set_and_check_decl_spec_loc (decl_specs, ds_long, token);
       type = long_integer_type_node;
       break;
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 211858)
+++ gcc/cp/mangle.c	(working copy)
@@ -150,14 +150,14 @@ integer_type_codes[itk_none] =
   'i',  /* itk_int */
   'j',  /* itk_unsigned_int */
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
-  'n',  /* itk_int128 */
-  'o',  /* itk_unsigned_int128  */
+  /* __intN types are handled separately */
+  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 };
 
 static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
@@ -2149,12 +2149,14 @@ write_CV_qualifiers_for_type (const tree
       ++num_qualifiers;
     }
 
   return num_qualifiers;
 }
 
+#include "print-tree.h"
+
 /* Non-terminal <builtin-type>.
 
      <builtin-type> ::= v   # void
 		    ::= b   # bool
 		    ::= w   # wchar_t
 		    ::= c   # char
@@ -2208,12 +2210,13 @@ write_builtin_type (tree type)
 	  size_t itk;
 	  /* Assume TYPE is one of the shared integer type nodes.  Find
 	     it in the array of these nodes.  */
 	iagain:
 	  for (itk = 0; itk < itk_none; ++itk)
 	    if (integer_types[itk] != NULL_TREE
+		&& integer_type_codes[itk] != '\0'
 		&& type == integer_types[itk])
 	      {
 		/* Print the corresponding single-letter code.  */
 		write_char (integer_type_codes[itk]);
 		break;
 	      }
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 211858)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4849,12 +4849,14 @@ typedef struct cp_decl_specifier_seq {
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
   /* True iff multiple storage classes were (erroneously) specified
@@ -4864,14 +4866,14 @@ typedef struct cp_decl_specifier_seq {
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
   /* True iff at least one type-specifier was found.  */
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
-  /* True iff "__int128" was explicitly provided.  */
-  BOOL_BITFIELD explicit_int128_p : 1;
+  /* True iff "__intN" was explicitly provided.  */
+  BOOL_BITFIELD explicit_intN_p : 1;
   /* True iff "char" was explicitly provided.  */
   BOOL_BITFIELD explicit_char_p : 1;
   /* True iff ds_thread is set for __thread, not thread_local.  */
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
 } cp_decl_specifier_seq;
 
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(revision 211858)
+++ gcc/cp/lex.c	(working copy)
@@ -190,12 +190,21 @@ init_reswords (void)
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
       if (! (c_common_reswords[i].disable & mask))
 	C_IS_RESERVED_WORD (id) = 1;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 static void
 init_cp_pragma (void)
 {
   c_register_pragma (0, "vtable", handle_pragma_vtable);
Index: gcc/builtin-types.def
===================================================================
--- gcc/builtin-types.def	(revision 211858)
+++ gcc/builtin-types.def	(working copy)
@@ -62,14 +62,12 @@ DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_typ
 DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
-DEF_PRIMITIVE_TYPE (BT_INT128, int128_integer_type_node)
-DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
 DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	(revision 211858)
+++ gcc/machmode.def	(working copy)
@@ -189,12 +189,19 @@ INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
 
 /* No partial integer modes are defined by default.  */
 
+/* The target normally defines any target-specific __intN types and
+   their modes, but __int128 for TImode is fairly common so define it
+   here.  The type will not be created unless the target supports
+   TImode.  */
+
+INT_N (TI, 128);
+
 /* Basic floating point modes.  SF and DF are the only modes provided
    by default.  The names QF, HF, XF, and TF are reserved for targets
    that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
 
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE).  */
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 211858)
+++ gcc/stor-layout.c	(working copy)
@@ -309,23 +309,30 @@ finalize_size_functions (void)
    it may have padding as well.  If LIMIT is nonzero, modes of wider
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = BLKmode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size
+	  && int_n_enabled_p[i])
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +353,33 @@ mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+	  && int_n_enabled_p[i])
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
@@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      precision = -1;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZETYPE) == 0)
+	      {
+		precision = int_n_data[i].bitsize;
+	      }
+	  }
+      if (precision == -1)
+	gcc_unreachable ();
+    }
 
   bprecision
    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
   /* Create stubs for sizetype and bitsizetype so we can create constants.  */
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(revision 211858)
+++ gcc/genmodes.c	(working copy)
@@ -71,23 +71,24 @@ struct mode_data
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
   bool need_bytesize_adj;	/* true if this mode need dynamic size
 				   adjustment */
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0, false
+  "<unknown>", 0, 0, 0, 0, false, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -629,12 +630,40 @@ reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(M,PREC)				\
+  make_int_n (#M, PREC, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (const char *m, int bitsize,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -1007,12 +1036,13 @@ mode_inner_inline (enum machine_mode mod
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -1067,12 +1097,19 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\n#if GCC_VERSION >= 4001\n");
   emit_mode_size_inline ();
   emit_mode_nunits_inline ();
   emit_mode_inner_inline ();
   puts ("#endif /* GCC_VERSION >= 4001 */");
 
@@ -1516,12 +1553,59 @@ emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+  struct mode_data **mode_sort;
+  int n_modes = 0;
+  int i, j;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_modes ++;
+  mode_sort = XALLOCAVEC (struct mode_data *, n_modes);
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      mode_sort[n_modes++] = m;
+
+  /* Yes, this is a bubblesort, but there are at most four (and
+     usually only 1-2) entries to sort.  */
+  for (i = 0; i<n_modes - 1; i++)
+    for (j = i + 1; j < n_modes; j++)
+      if (mode_sort[i]->int_n > mode_sort[j]->int_n)
+	{
+	  m = mode_sort[i];
+	  mode_sort[i] = mode_sort[j];
+	  mode_sort[j] = m;
+	}
+
+  for (i = 0; i < n_modes; i ++)
+    {
+      m = mode_sort[i];
+      printf(" {\n");
+      tagged_printf ("%u", m->int_n, m->name);
+      printf ("%smode,", m->name);
+      printf(" },\n");
+    }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1535,12 +1619,13 @@ emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(revision 211858)
+++ gcc/lto/lto-lang.c	(working copy)
@@ -1146,23 +1146,44 @@ lto_build_c_type_nodes (void)
     {
       intmax_type_node = long_long_integer_type_node;
       uintmax_type_node = long_long_unsigned_type_node;
       signed_size_type_node = long_long_integer_type_node;
     }
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      signed_size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		intmax_type_node = int_n_trees[i].signed_type;
+		uintmax_type_node = int_n_trees[i].unsigned_type;
+		signed_size_type_node = int_n_trees[i].signed_type;
+	      }
+	  }
+      if (signed_size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   wint_type_node = unsigned_type_node;
   pid_type_node = integer_type_node;
 }
 
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
+  int i;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = (flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
@@ -1228,14 +1249,19 @@ lto_init (void)
   NAME_TYPE (long_double_type_node, "long double");
   NAME_TYPE (void_type_node, "void");
   NAME_TYPE (boolean_type_node, "bool");
   NAME_TYPE (complex_float_type_node, "complex float");
   NAME_TYPE (complex_double_type_node, "complex double");
   NAME_TYPE (complex_long_double_type_node, "complex long double");
-  if (int128_integer_type_node)
-    NAME_TYPE (int128_integer_type_node, "__int128");
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    if (int_n_enabled_p[i])
+      {
+	char name[50];
+	sprintf (name, "__int%d", int_n_data[i].bitsize);
+	NAME_TYPE (int_n_trees[i].signed_type, name);
+      }
 #undef NAME_TYPE
 
   /* Initialize LTO-specific data structures.  */
   in_lto_p = true;
 
   return true;
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(revision 211858)
+++ gcc/gimple.c	(working copy)
@@ -2091,12 +2091,13 @@ gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2108,16 +2109,21 @@ gimple_signed_or_unsigned_type (bool uns
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node
       || type1 == long_long_unsigned_type_node)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2224,16 +2230,20 @@ gimple_signed_or_unsigned_type (bool uns
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-	    ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 211858)
+++ gcc/tree-core.h	(working copy)
@@ -562,14 +562,22 @@ enum integer_type_kind {
   itk_int,
   itk_unsigned_int,
   itk_long,
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
+
+  itk_intN_0,
+  itk_unsigned_intN_0,
+  itk_intN_1,
+  itk_unsigned_intN_1,
+  itk_intN_2,
+  itk_unsigned_intN_2,
+  itk_intN_3,
+  itk_unsigned_intN_3,
+
   itk_none
 };
 
 /* A pointer-to-function member type looks like:
 
      struct {

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 3/4] change specific int128 -> generic intN
  2014-06-21 20:17   ` Joseph S. Myers
                       ` (2 preceding siblings ...)
  2014-06-24 23:38     ` [patch 2/4] " DJ Delorie
@ 2014-06-24 23:39     ` DJ Delorie
  2014-06-24 23:42     ` [patch 4/4] " DJ Delorie
  4 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-24 23:39 UTC (permalink / raw)
  To: gcc-patches


Part 3 of 4, split from the full patch.  Additional optimization
opportunity, since the MSP430 does a lot of conversions between HImode
and PSImode.

gcc/
	* expr.c (convert_move): If the target has an explicit converter,
	use it.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 211858)
+++ gcc/expr.c	(working copy)
@@ -405,12 +405,32 @@ convert_move (rtx to, rtx from, int unsi
 								       from)
 			  : gen_rtx_FLOAT_EXTEND (to_mode, from));
       return;
     }
 
   /* Handle pointer conversion.  */			/* SPEE 900220.  */
+  /* If the target has a converter from FROM_MODE to TO_MODE, use it.  */
+  {
+    convert_optab ctab;
+
+    if (GET_MODE_PRECISION (from_mode) > GET_MODE_PRECISION (to_mode))
+      ctab = trunc_optab;
+    else if (unsignedp)
+      ctab = zext_optab;
+    else
+      ctab = sext_optab;
+
+    if (convert_optab_handler (ctab, to_mode, from_mode)
+	!= CODE_FOR_nothing)
+      {
+	emit_unop_insn (convert_optab_handler (ctab, to_mode, from_mode),
+			to, from, UNKNOWN);
+	return;
+      }
+  }
+
   /* 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)
     {
       enum machine_mode full_mode
 	= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 4/4] change specific int128 -> generic intN
  2014-06-21 20:17   ` Joseph S. Myers
                       ` (3 preceding siblings ...)
  2014-06-24 23:39     ` [patch 3/4] " DJ Delorie
@ 2014-06-24 23:42     ` DJ Delorie
  4 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-24 23:42 UTC (permalink / raw)
  To: gcc-patches


Part 4 of 4, split from the full patch.  This is the MSP430-specific
use of the new intN framework to enable true 20-bit pointers.  Since
I'm one of the MSP430 maintainers, this patch is being posted for
reference, not for approval.


gcc/config/msp430
	* config/msp430/msp430-protos.h (msp430_hard_regno_nregs_has_padding): New.
	(msp430_hard_regno_nregs_with_padding): New.
	* config/msp430/msp430.c (msp430_scalar_mode_supported_p): New.
	(msp430_hard_regno_nregs_has_padding): New.
	(msp430_hard_regno_nregs_with_padding): New.
	(msp430_unwind_word_mode): Use PSImode instead of SImode.
	(msp430_addr_space_legitimate_address_p): New.
	(msp430_asm_integer): New.
	(msp430_init_dwarf_reg_sizes_extra): New.
	(msp430_print_operand): Use X suffix for PSImode even in small model.
	* config/msp430/msp430.h (POINTER_SIZE): Use 20 bits, not 32.
	(PTR_SIZE): ...but 4 bytes for EH.
	(SIZE_TYPE): Use __int20.
	(PTRDIFF_TYPE): Likewise.
	(INCOMING_FRAME_SP_OFFSET): Adjust.
	* config/msp430/msp430.md (movqi_topbyte): New.
	(movpsi): Use fixed suffixes.
	(movsipsi2): Enable for 430X, not large model.
	(extendhipsi2): Likewise.
	(zero_extendhisi2): Likewise.
	(zero_extendhisipsi2): Likewise.
	(extend_and_shift1_hipsi2): Likewise.
	(extendpsisi2): Likewise.
	(*bitbranch<mode>4_z): Fix suffix logic.

Index: gcc/config/msp430/msp430-protos.h
===================================================================
--- gcc/config/msp430/msp430-protos.h	(revision 211858)
+++ gcc/config/msp430/msp430-protos.h	(working copy)
@@ -27,12 +27,15 @@ void	msp430_expand_epilogue (int);
 void	msp430_expand_helper (rtx *operands, const char *, bool);
 void	msp430_expand_prologue (void);
 const char * msp430x_extendhisi (rtx *);
 void	msp430_fixup_compare_operands (enum machine_mode, rtx *);
 int	msp430_hard_regno_mode_ok (int, enum machine_mode);
 int	msp430_hard_regno_nregs (int, enum machine_mode);
+int	msp430_hard_regno_nregs_has_padding (int, enum machine_mode);
+int	msp430_hard_regno_nregs_with_padding (int, enum machine_mode);
+bool    msp430_hwmult_enabled (void);
 rtx	msp430_incoming_return_addr_rtx (void);
 void	msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
 int	msp430_initial_elimination_offset (int, int);
 bool    msp430_is_interrupt_func (void);
 const char * msp430x_logical_shift_right (rtx);
 const char * msp430_mcu_name (void);
Index: gcc/config/msp430/msp430.md
===================================================================
--- gcc/config/msp430/msp430.md	(revision 211858)
+++ gcc/config/msp430/msp430.md	(working copy)
@@ -176,12 +176,19 @@
   ""
   "@
    MOV.B\t%1, %0
    MOV%X1.B\t%1, %0"
 )
 
+(define_insn "movqi_topbyte"
+  [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r")
+	(subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))]
+  "msp430x"
+  "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
+)
+
 (define_insn "movqi"
   [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
 	(match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
   ""
   "@
   MOV.B\t%1, %0
@@ -220,27 +227,27 @@
 ;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
 (define_insn "movpsi"
   [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,Ya,rm")
 	(match_operand:PSI 1 "msp_general_operand" "riYa,r,rmi"))]
   ""
   "@
-  MOV%Q0\t%1, %0
-  MOV%Q0\t%1, %0
-  MOV%X0.%Q0\t%1, %0")
+  MOVA\t%1, %0
+  MOVA\t%1, %0
+  MOVX.A\t%1, %0")
 
 ; This pattern is identical to the truncsipsi2 pattern except
 ; that it uses a SUBREG instead of a TRUNC.  It is needed in
 ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
 ; into (SET:PSI (PSI)).
 ;
 ; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
 
 (define_insn "movsipsi2"
   [(set (match_operand:PSI            0 "register_operand" "=r")
 	(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
 )
 
 ;;------------------------------------------------------------
 ;; Math
 
@@ -564,49 +571,49 @@
   { return msp430x_extendhisi (operands); }
 )
 
 (define_insn "extendhipsi2"
   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
 	(subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #4, %0"
 )
 
 ;; Look for cases where integer/pointer conversions are suboptimal due
 ;; to missing patterns, despite us not having opcodes for these
 ;; patterns.  Doing these manually allows for alternate optimization
 ;; paths.
 (define_insn "zero_extendhisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
 	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))]
-  "TARGET_LARGE"
+  "msp430x"
   "MOV.W\t#0,%H0"
 )
 
 (define_insn "zero_extendhisipsi2"
   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
 	(subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
-  "TARGET_LARGE"
+  "msp430x"
   "@
    AND.W\t#-1,%0
    MOV.W\t%1,%0"
 )
 
 (define_insn "extend_and_shift1_hipsi2"
   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
 	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
 		   (const_int 1)))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #3, %0"
 )
 
 (define_insn "extend_and_shift2_hipsi2"
   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
 	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
 		   (const_int 2)))]
-  "TARGET_LARGE"
+  "msp430x"
   "RLAM #4, %0 { RRAM #2, %0"
 )
 
 ; Nasty - we are sign-extending a 20-bit PSI value in one register into
 ; two adjacent 16-bit registers to make an SI value.  There is no MSP430X
 ; instruction that will do this, so we push the 20-bit value onto the stack
@@ -645,13 +652,13 @@
 ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
 ;; it, we use a different method here.
 
 (define_insn "extendpsisi2"
   [(set (match_operand:SI                  0 "register_operand" "=r")
 	(sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
-  "TARGET_LARGE"
+  "msp430x"
   "*
     /* The intention here is that we copy the bottom 16-bits of
        %1 into %L0 (zeroing the top four bits).  Then we copy the
        entire 20-bits of %1 into %H0 and then arithmetically shift
        it right by 16 bits, to get the top four bits of the pointer
        sign-extended in %H0.  */
@@ -1174,13 +1181,13 @@
 		  (const_int 0))
               (label_ref (match_operand 2 "" ""))
 	      (pc)))
    (clobber (reg:BI CARRY))
    ]
   ""
-  "BIT%x0%X0%b0\t%1, %0 { JEQ\t%l2"
+  "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
   )
 
 (define_insn "*bitbranch<mode>4"
   [(set (pc) (if_then_else
 	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
 			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	(revision 211858)
+++ gcc/config/msp430/msp430.c	(working copy)
@@ -225,12 +225,27 @@ msp430_option_override (void)
      command line and always sets -O2 in CFLAGS.  Thus it is not
      possible to build newlib with -Os enabled.  Until now...  */
   if (TARGET_OPT_SPACE && optimize < 3)
     optimize_size = 1;
 }
 
+#undef  TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
+
+static bool
+msp430_scalar_mode_supported_p (enum machine_mode m)
+{
+  if (m == PSImode && msp430x)
+    return true;
+#if 0
+  if (m == TImode)
+    return true;
+#endif
+  return default_scalar_mode_supported_p (m);
+}
+
 \f
 
 /* Storage Layout */
 
 #undef  TARGET_MS_BITFIELD_LAYOUT_P
 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
@@ -254,12 +269,33 @@ msp430_hard_regno_nregs (int regno ATTRI
   if (mode == PSImode && msp430x)
     return 1;
   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
 	  / UNITS_PER_WORD);
 }
 
+/* Implements HARD_REGNO_NREGS_HAS_PADDING.  */
+int
+msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
+				     enum machine_mode mode)
+{
+  if (mode == PSImode && msp430x)
+    return 1;
+  return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+	  / UNITS_PER_WORD);
+}
+
+/* Implements HARD_REGNO_NREGS_WITH_PADDING.  */
+int
+msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
+				     enum machine_mode mode)
+{
+  if (mode == PSImode)
+    return 2;
+  return msp430_hard_regno_nregs (regno, mode);
+}
+
 /* Implements HARD_REGNO_MODE_OK.  */
 int
 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
 			   enum machine_mode mode)
 {
   return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
@@ -367,13 +403,13 @@ msp430_addr_space_pointer_mode (addr_spa
 #undef  TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
 
 static enum machine_mode
 msp430_unwind_word_mode (void)
 {
-  return TARGET_LARGE ? SImode : HImode;
+  return TARGET_LARGE ? PSImode : HImode;
 }
 
 /* Determine if one named address space is a subset of another.  */
 #undef  TARGET_ADDR_SPACE_SUBSET_P
 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
 static bool
@@ -882,12 +918,49 @@ msp430_legitimate_address_p (enum machin
 
     default:
       return false;
     }
 }
 
+#undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
+
+bool
+msp430_addr_space_legitimate_address_p (enum machine_mode mode,
+					rtx x,
+					bool strict,
+					addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return msp430_legitimate_address_p (mode, x, strict);
+}
+
+#undef  TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER msp430_asm_integer
+static bool
+msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
+{
+  int c = GET_CODE (x);
+
+  if (size == 3 && GET_MODE (x) == PSImode)
+    size = 4;
+
+  switch (size)
+    {
+    case 4:
+      if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT)
+	{
+	  fprintf (asm_out_file, "\t.long\t");
+	  output_addr_const (asm_out_file, x);
+	  fputc ('\n', asm_out_file);
+	  return true;
+	}
+      break;
+    }
+  return default_assemble_integer (x, size, aligned_p);
+}
+
 #undef  TARGET_LEGITIMATE_CONSTANT_P
 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
 
 static bool
 msp430_legitimate_constant (enum machine_mode mode, rtx x)
 {
@@ -1740,12 +1813,39 @@ msp430_expand_eh_return (rtx eh_handler)
   tmp = gen_rtx_PLUS (Pmode, ap, sa);
   tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
   tmp = gen_rtx_MEM (Pmode, tmp);
   emit_move_insn (tmp, ra);
 }
 
+#undef  TARGET_INIT_DWARF_REG_SIZES_EXTRA
+#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
+void
+msp430_init_dwarf_reg_sizes_extra (tree address)
+{
+  int i;
+  rtx addr = expand_normal (address);
+  rtx mem = gen_rtx_MEM (BLKmode, addr);
+
+  if (!msp430x)
+    return;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      unsigned int dnum = DWARF_FRAME_REGNUM (i);
+      unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
+
+      if (rnum < DWARF_FRAME_REGISTERS)
+	{
+	  HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
+
+	  emit_move_insn (adjust_address (mem, QImode, offset),
+			  gen_int_mode (4, QImode));
+	}
+    }
+}
+
 /* This is a list of MD patterns that implement fixed-count shifts.  */
 static struct
 {
   const char *name;
   int count;
   int need_430x;
@@ -2350,13 +2450,13 @@ msp430_print_operand (FILE * file, rtx o
 	}
       break;
 
     case 'X':
       /* This is used to turn, for example, an ADD opcode into an ADDX
 	 opcode when we're using 20-bit addresses.  */
-      if (TARGET_LARGE)
+      if (TARGET_LARGE || GET_MODE (op) == PSImode)
 	fprintf (file, "X");
       /* We don't care which operand we use, but we want 'X' in the MD
 	 file, so we do it this way.  */
       return;
 
     case 'x':
Index: gcc/config/msp430/msp430-modes.def
===================================================================
--- gcc/config/msp430/msp430-modes.def	(revision 211858)
+++ gcc/config/msp430/msp430-modes.def	(working copy)
@@ -1,3 +1,4 @@
 /* 20-bit address */
 PARTIAL_INT_MODE (SI, 20, PSI);
 
+INT_N (PSI, 20);
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	(revision 211858)
+++ gcc/config/msp430/msp430.h	(working copy)
@@ -128,16 +128,15 @@ extern bool msp430x;
 #define FRAME_GROWS_DOWNWARD		1
 #define FIRST_PARM_OFFSET(FNDECL) 	0
 
 #define MAX_REGS_PER_ADDRESS 		1
 
 #define Pmode 				(TARGET_LARGE ? PSImode : HImode)
-/* Note: 32 is a lie.  Large pointers are actually 20-bits wide.  But gcc
-   thinks that any non-power-of-2 pointer size equates to BLKmode, which
-   causes all kinds of problems...  */
-#define POINTER_SIZE			(TARGET_LARGE ? 32 : 16)
+#define POINTER_SIZE			(TARGET_LARGE ? 20 : 16)
+/* This is just for .eh_frame, to match bfd.  */
+#define PTR_SIZE			(TARGET_LARGE ? 4 : 2)
 #define	POINTERS_EXTEND_UNSIGNED	1
 
 #define ADDR_SPACE_NEAR	1
 #define ADDR_SPACE_FAR	2
 
 #define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas()
@@ -155,15 +154,15 @@ extern bool msp430x;
     (MODE) = HImode;
 #endif
 \f
 /* Layout of Source Language Data Types */
 
 #undef  SIZE_TYPE
-#define SIZE_TYPE			(TARGET_LARGE ? "long unsigned int" : "unsigned int")
+#define SIZE_TYPE			(TARGET_LARGE ? "__int20 unsigned" : "unsigned int")
 #undef  PTRDIFF_TYPE
-#define PTRDIFF_TYPE			(TARGET_LARGE ? "long int" : "int")
+#define PTRDIFF_TYPE			(TARGET_LARGE ? "__int20" : "int")
 #undef  WCHAR_TYPE
 #define WCHAR_TYPE			"long int"
 #undef  WCHAR_TYPE_SIZE
 #define WCHAR_TYPE_SIZE			BITS_PER_WORD
 #define FUNCTION_MODE 			HImode
 #define CASE_VECTOR_MODE		Pmode
@@ -379,13 +378,13 @@ typedef struct
 
 #define JUMP_TABLES_IN_TEXT_SECTION	1
 \f
 #undef	DWARF2_ADDR_SIZE
 #define	DWARF2_ADDR_SIZE			4
 
-#define INCOMING_FRAME_SP_OFFSET		(POINTER_SIZE / BITS_PER_UNIT)
+#define INCOMING_FRAME_SP_OFFSET		(TARGET_LARGE ? 4 : 2)
 
 #undef  PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 
 #define DWARF2_ASM_LINE_DEBUG_INFO		1
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-24 23:32     ` [patch 1/4] " DJ Delorie
@ 2014-06-27 11:22       ` Eric Botcazou
  2014-06-27 21:04         ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-06-27 11:22 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> gcc/
> 	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Round
> 	pointer size up to a power of two.
> 	* defaults.h (DWARF2_ADDR_SIZE): Round up.
> 	(POINTER_SIZE_UNITS): New, rounded up value.
> 	* dwarf2asm.c (size_of_encoded_value): Use it.
> 	(dw2_output_indirect_constant_1): Likewise.
> 	* expmed.c (init_expmed_one_conv): We now know the sizes of
> 	partial int modes.
> 	* loop-iv.c (iv_number_of_iterations): Use precision, not size.
> 	* optabs.c (expand_float): Use precision, not size.
> 	(expand_fix): Likewise.
> 	* simplify-rtx (simplify_unary_operation_1): Likewise.
> 	* tree-dfa.c (get_ref_base_and_extent): Likewise.
> 	* varasm.c (assemble_addr_to_section): Round up pointer sizes.
> 	(default_assemble_integer) Likewise.
> 	(dump_tm_clone_pairs): Likewise.
> 	* tree-core.c: Adjust comment.

No stor-layout.c listed here but...

> Index: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c	(revision 211858)
> +++ gcc/stor-layout.c	(working copy)
> @@ -2123,13 +2142,13 @@ layout_type (tree type)
> 
>      case BOOLEAN_TYPE:
>      case INTEGER_TYPE:
>      case ENUMERAL_TYPE:
>        SET_TYPE_MODE (type,
>  		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

This doesn't look correct, you might end up with types smaller than their 
modes and breaking the TYPE_SIZE/TYPE_SIZE_UNIT relationship.

> @@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
>      precision = LONG_TYPE_SIZE;
>    else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
>      precision = LONG_LONG_TYPE_SIZE;
>    else if (strcmp (SIZETYPE, "short unsigned int") == 0)
>      precision = SHORT_TYPE_SIZE;
>    else
>     gcc_unreachable ();
> 
>    bprecision
> -    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
> +    = MIN (precision, MAX_FIXED_MODE_SIZE);
>    bprecision
>      = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
>    if (bprecision > HOST_BITS_PER_DOUBLE_INT)
>      bprecision = HOST_BITS_PER_DOUBLE_INT;
> 
>    /* Create stubs for sizetype and bitsizetype so we can create constants. 

Why are you reducing the precision here?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 11:22       ` Eric Botcazou
@ 2014-06-27 21:04         ` DJ Delorie
  2014-06-27 21:38           ` Joseph S. Myers
  2014-07-02  8:18           ` Eric Botcazou
  0 siblings, 2 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-27 21:04 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> No stor-layout.c listed here but...

I knew I'd miss at least one in the split-up...

> > Index: gcc/stor-layout.c
> > ===================================================================
> > --- gcc/stor-layout.c	(revision 211858)
> > +++ gcc/stor-layout.c	(working copy)
> > @@ -2123,13 +2142,13 @@ layout_type (tree type)
> > 
> >      case BOOLEAN_TYPE:
> >      case INTEGER_TYPE:
> >      case ENUMERAL_TYPE:
> >        SET_TYPE_MODE (type,
> >  		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
> > -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> > +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> > (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> > (type))); break;
> 
> This doesn't look correct, you might end up with types smaller than their 
> modes and breaking the TYPE_SIZE/TYPE_SIZE_UNIT relationship.

The whole point of using _PRECISION is to have the size be exactly the
same as the mode (bitsize is bigger than the mode for partial-int
modes).  TYPE_SIZE_UNIT should be its storage size, right?  If the
type is not a multiple of BITS_PER_UNIT, the actual size and
stored-in-memory size are going to be different.

The problem in the old code is that BITSIZE is not the size in bits of
the type, it's the size in bytes times BITS_PER_UNIT.  This meant that
all partial-int modes would be converted into their non-partial modes
eventually.  Most of my patch is about avoiding that.

If you still disagree, let's first figure out what the right
relationship between TYPE_SIZE and TYPE_SIZE_UNIT is, for types that
aren't a multiple of BITS_PER_UNIT.

> > @@ -2516,16 +2535,33 @@ initialize_sizetypes (void)
> >      precision = LONG_TYPE_SIZE;
> >    else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
> >      precision = LONG_LONG_TYPE_SIZE;
> >    else if (strcmp (SIZETYPE, "short unsigned int") == 0)
> >      precision = SHORT_TYPE_SIZE;
> >    else
> >     gcc_unreachable ();
> > 
> >    bprecision
> > -    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
> > +    = MIN (precision, MAX_FIXED_MODE_SIZE);
> >    bprecision
> >      = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
> >    if (bprecision > HOST_BITS_PER_DOUBLE_INT)
> >      bprecision = HOST_BITS_PER_DOUBLE_INT;
> > 
> >    /* Create stubs for sizetype and bitsizetype so we can create constants. 
> 
> Why are you reducing the precision here?

I'm not reducing it, I'm removing a case where it's rounded up.
Rounding up a 20-bit PSImode gives you SImode eventually.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:04         ` DJ Delorie
@ 2014-06-27 21:38           ` Joseph S. Myers
  2014-06-27 21:50             ` DJ Delorie
  2014-07-02  8:18           ` Eric Botcazou
  1 sibling, 1 reply; 49+ messages in thread
From: Joseph S. Myers @ 2014-06-27 21:38 UTC (permalink / raw)
  To: DJ Delorie; +Cc: Eric Botcazou, gcc-patches

On Fri, 27 Jun 2014, DJ Delorie wrote:

> If you still disagree, let's first figure out what the right
> relationship between TYPE_SIZE and TYPE_SIZE_UNIT is, for types that
> aren't a multiple of BITS_PER_UNIT.

My suggestion: TYPE_SIZE should always be TYPE_SIZE_UNIT times 
BITS_PER_UNIT, so including any padding bits (and so should not exist, 
really - it's an extra pointer bulking up lots of trees with redundant 
information), while TYPE_PRECISION is what gives the number of value / 
sign bits.  If you're allocating bit-fields, TYPE_PRECISION will say how 
many bits to use; if you're allocating registers (which might not always 
correspond neatly to multiples of BITS_PER_UNIT), TYPE_MODE is what's 
relevant; otherwise, you're allocating whole bytes in memory and can use 
TYPE_SIZE_UNIT.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:38           ` Joseph S. Myers
@ 2014-06-27 21:50             ` DJ Delorie
  2014-06-27 21:57               ` Joseph S. Myers
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-06-27 21:50 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: ebotcazou, gcc-patches


Are you proposing we remove TYPE_SIZE completely?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:50             ` DJ Delorie
@ 2014-06-27 21:57               ` Joseph S. Myers
  2014-06-27 23:31                 ` DJ Delorie
  2014-07-01  2:23                 ` DJ Delorie
  0 siblings, 2 replies; 49+ messages in thread
From: Joseph S. Myers @ 2014-06-27 21:57 UTC (permalink / raw)
  To: DJ Delorie; +Cc: ebotcazou, gcc-patches

On Fri, 27 Jun 2014, DJ Delorie wrote:

> Are you proposing we remove TYPE_SIZE completely?

Yes; I think that makes sense, unless someone produces a clearer 
definition of what TYPE_SIZE means that isn't redundant.

If you find a particular use of TYPE_SIZE is using a size that isn't 
correct for your type whose precision is not a multiple of BITS_PER_UNIT, 
then in my model the correct fix is to change that use of TYPE_SIZE rather 
than to change the value of TYPE_SIZE for that type - and such a change 
(to use TYPE_PRECISION, maybe) would also be incremental progress towards 
eliminating TYPE_SIZE.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:57               ` Joseph S. Myers
@ 2014-06-27 23:31                 ` DJ Delorie
  2014-07-01  2:23                 ` DJ Delorie
  1 sibling, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-06-27 23:31 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: ebotcazou, gcc-patches


> Yes; I think that makes sense, unless someone produces a clearer 
> definition of what TYPE_SIZE means that isn't redundant.

Does TYPE_SIZE have a different meaning than TYPE_PRECISION
for non-integer types?  Floats, vectors, complex?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-06-24  5:40     ` DJ Delorie
@ 2014-06-28 10:09       ` Marc Glisse
  0 siblings, 0 replies; 49+ messages in thread
From: Marc Glisse @ 2014-06-28 10:09 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches, libstdc++

(oups, the message got stuck in my mailer, should have been sent a while 
ago)

On Tue, 24 Jun 2014, DJ Delorie wrote:

>> Since the check for __STRICT_ANSI__ is removed, do we need to add
>> __extension__ in front of __GLIBCXX_TYPE_INT_N_0 to avoid warning with
>> -Wsystem-headers?
>
> I copied the code from the __int128 case, and it explicitly bypassed
> -Wsystem-headers...  so we don't have that problem.

Ah... indeed.

>> That seems complicated. You just need to call emit_support_tinfo_1 on
>> each of the types (see how fundamentals is used at the end of the
>> function), no need to put everything in the array.
>
> Sure, *now* you tell me that :-)

Sorry, I should have made that clearer when I introduced 
emit_support_tinfo_1...

> I can do it either way, but it's the same overhead to iterate through
> the types.  Shoving it into the array is a bit more future-proof, but
> keeping the index in sync is a bit of work if the table ever changes.

We are already going to have a second loop, not on the fundamentals array, 
calling emit_support_tinfo_1 for __float128 when available, so the array 
won't be complete anymore. More precisely, it will iterate either on all 
the types on which register_builtin_type was called or on float modes that 
don't correspond to float/double/long double (depends on how much they 
break ARM).

> Your choice ;-)

Well, Jason's.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:57               ` Joseph S. Myers
  2014-06-27 23:31                 ` DJ Delorie
@ 2014-07-01  2:23                 ` DJ Delorie
  1 sibling, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-07-01  2:23 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: ebotcazou, gcc-patches


> If you find a particular use of TYPE_SIZE is using a size that isn't
> correct for your type whose precision is not a multiple of
> BITS_PER_UNIT, then in my model the correct fix is to change that
> use of TYPE_SIZE rather than to change the value of TYPE_SIZE for
> that type - and such a change (to use TYPE_PRECISION, maybe) would
> also be incremental progress towards eliminating TYPE_SIZE.

What about DECL_SIZE ?  It's set from TYPE_SIZE but there is no
DECL_PRECISION.

Also, TYPE_PRECISION is an integer, where TYPE_SIZE is a tree.
They're not universally swappable code-wise.

And I noticed that sizetype and bitsizetype are not really any
different any more either, why have both?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-06-27 21:04         ` DJ Delorie
  2014-06-27 21:38           ` Joseph S. Myers
@ 2014-07-02  8:18           ` Eric Botcazou
  2014-07-02 14:57             ` DJ Delorie
  1 sibling, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-07-02  8:18 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> The whole point of using _PRECISION is to have the size be exactly the
> same as the mode (bitsize is bigger than the mode for partial-int
> modes).  TYPE_SIZE_UNIT should be its storage size, right?  If the
> type is not a multiple of BITS_PER_UNIT, the actual size and
> stored-in-memory size are going to be different.

But you cannot use the PRECISION of a mode to set a size, since the SIZE of 
the mode can be used by the machine to access the object in that mode, so 
you'll end up with types whose TYPE_SIZE is smaller than the access size.

You need to use TYPE_PRECISION here.

> The problem in the old code is that BITSIZE is not the size in bits of
> the type, it's the size in bytes times BITS_PER_UNIT.  This meant that
> all partial-int modes would be converted into their non-partial modes
> eventually.  Most of my patch is about avoiding that.

Yes, BITSIZE is the size rounded up to BITS_PER_UNIT, but why is that a 
problem exactly?  Do you have modes whose size is not multiple of the unit?

> I'm not reducing it, I'm removing a case where it's rounded up.
> Rounding up a 20-bit PSImode gives you SImode eventually.

Yes, you are reducing it, the precision of bitsize must be at least that of 
sizetype + BITS_PER_UNIT_LOG + 1.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-02  8:18           ` Eric Botcazou
@ 2014-07-02 14:57             ` DJ Delorie
  2014-07-03 15:53               ` Eric Botcazou
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-07-02 14:57 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> Do you have modes whose size is not multiple of the unit?

Yes.  That's exactly the problem I'm trying to solve here.  I'm making
partial int modes have real corresponding types, and they can be any
bit size, with target PS*modes to match.  The MSP430, for example, has
20-bit modes, 20-bit operands, and __int20.  Rounding up to byte sizes
forces everything into an emulated SImode which makes code size huge
and performance much worse.

Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have a
"* BITS_PER_UNIT" mathematical relationship.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-02 14:57             ` DJ Delorie
@ 2014-07-03 15:53               ` Eric Botcazou
  2014-07-03 16:12                 ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-07-03 15:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: DJ Delorie

> Yes.  That's exactly the problem I'm trying to solve here.  I'm making
> partial int modes have real corresponding types, and they can be any
> bit size, with target PS*modes to match.  The MSP430, for example, has
> 20-bit modes, 20-bit operands, and __int20.  Rounding up to byte sizes
> forces everything into an emulated SImode which makes code size huge
> and performance much worse.

And the hardware really loads 20 bits and not 24 bits?  If so, I think you 
might want to consider changing the unit to 4 bits instead of 8 bits.  If no,
the mode is padded and has 24-bit size so why is setting TYPE_PRECISION to 20 
not sufficient to achieve what you want?

> Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have a
> "* BITS_PER_UNIT" mathematical relationship.

I'm skeptical this can work, it's pretty fundamental.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-03 15:53               ` Eric Botcazou
@ 2014-07-03 16:12                 ` DJ Delorie
  2014-07-03 16:30                   ` Bernd Schmidt
  2014-07-04  9:45                   ` Eric Botcazou
  0 siblings, 2 replies; 49+ messages in thread
From: DJ Delorie @ 2014-07-03 16:12 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> And the hardware really loads 20 bits and not 24 bits?  If so, I
> think you might want to consider changing the unit to 4 bits instead
> of 8 bits.  If no, the mode is padded and has 24-bit size so why is
> setting TYPE_PRECISION to 20 not sufficient to achieve what you
> want?

The hardware transfers data in and out of byte-oriented memory in
TYPE_SIZE_UNITS chunks.  Once in a hardware register, all operations
are either 8, 16, or 20 bits (TYPE_SIZE) in size.  So yes, values are
padded in memory, but no, they are not padded in registers.

Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
it's the same as TYPE_SIZE and ignores it.  Heck, most of gcc is
oblivious to the idea that types might not be powers-of-two in size.
GCC doesn't even bother with a DECL_PRECISION.

> > Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have
> > a "* BITS_PER_UNIT" mathematical relationship.
> 
> I'm skeptical this can work, it's pretty fundamental.

It seems to work just fine in testing, and I'm trying to make it
non-fundamental.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-03 16:12                 ` DJ Delorie
@ 2014-07-03 16:30                   ` Bernd Schmidt
  2014-07-03 20:01                     ` DJ Delorie
  2014-07-04  9:45                   ` Eric Botcazou
  1 sibling, 1 reply; 49+ messages in thread
From: Bernd Schmidt @ 2014-07-03 16:30 UTC (permalink / raw)
  To: DJ Delorie, Eric Botcazou; +Cc: gcc-patches

On 07/03/2014 06:12 PM, DJ Delorie wrote:
> The hardware transfers data in and out of byte-oriented memory in
> TYPE_SIZE_UNITS chunks.  Once in a hardware register, all operations
> are either 8, 16, or 20 bits (TYPE_SIZE) in size.  So yes, values are
> padded in memory, but no, they are not padded in registers.
>
> Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
> it's the same as TYPE_SIZE and ignores it.

That's what'll need fixing then. I doubt there are too many places that 
require changing.

Also, the above seems inaccurate:
$ grep  TYPE_PREC *.c|wc -l
633
$ grep  TYPE_SIZE *.c|wc -l
551

>  Heck, most of gcc is
> oblivious to the idea that types might not be powers-of-two in size.
> GCC doesn't even bother with a DECL_PRECISION.

Sure - why would you even need one?

>>> Thus, in these cases, TYPE_SIZE and TYPE_SIZE_UNIT no longer have
>>> a "* BITS_PER_UNIT" mathematical relationship.
>>
>> I'm skeptical this can work, it's pretty fundamental.
>
> It seems to work just fine in testing, and I'm trying to make it
> non-fundamental.

I also think this is not a very good idea.


Bernd

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-03 16:30                   ` Bernd Schmidt
@ 2014-07-03 20:01                     ` DJ Delorie
  2014-07-04  9:50                       ` Eric Botcazou
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-07-03 20:01 UTC (permalink / raw)
  To: Bernd Schmidt; +Cc: ebotcazou, gcc-patches


> That's what'll need fixing then.

Can I change TYPE_SIZE to TYPE_SIZE_WITH_PADDING then?  Because it's
not reflecting the type's size any more.  Why do we have to round up a
type's size anyway?  That's a pointless assumption *unless* you're
allocating memory space for it, and in that case, you want
TYPE_SIZE_UNITS anyway.

> I doubt there are too many places that require changing.

I don't doubt it, because I've been fighting these assumptions for
years.

> > Heck, most of gcc is oblivious to the idea that types might not be
> > powers-of-two in size.  GCC doesn't even bother with a
> > DECL_PRECISION.
> 
> Sure - why would you even need one?

Why do we need to have DECL_SIZE_UNITS (the size of the type, rounded
up to whole number of bytes) and DECL_SIZE (the size of the type,
rounded up to whole number of bytes), yet not have something that says
how big the decl *really is* ?

A pointer on MSP430 is 20 bits.  All the general registers are 20
bits.  Not 16, and not 24.  20.  There's nothing in a decl that says
"I'm 20 bits" and inevitably it ends up being SImode instead of
PSImode.

> > It seems to work just fine in testing, and I'm trying to make it
> > non-fundamental.
> 
> I also think this is not a very good idea.

Then please provide a "very good idea" for how to teach gcc about true
20-bit types in a system with 8-bit memory and 16-bit words.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-03 16:12                 ` DJ Delorie
  2014-07-03 16:30                   ` Bernd Schmidt
@ 2014-07-04  9:45                   ` Eric Botcazou
  2014-07-07  6:01                     ` DJ Delorie
  1 sibling, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-07-04  9:45 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> Setting TYPE_PRECISION is mostly useless, because most of gcc assumes
> it's the same as TYPE_SIZE and ignores it.

Then you need to change that and not TYPE_SIZE.

> It seems to work just fine in testing, and I'm trying to make it
> non-fundamental.

I'm very skeptical...  In any case, having a type whose TYPE_SIZE is smaller 
than the size of its MODE is a lie which will bite you back at some point.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-03 20:01                     ` DJ Delorie
@ 2014-07-04  9:50                       ` Eric Botcazou
  0 siblings, 0 replies; 49+ messages in thread
From: Eric Botcazou @ 2014-07-04  9:50 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches, Bernd Schmidt

> I don't doubt it, because I've been fighting these assumptions for years.

The fight needs to be resumed/sped up, that's clearly the right thing to do.

> Then please provide a "very good idea" for how to teach gcc about true
> 20-bit types in a system with 8-bit memory and 16-bit words.

TYPE_PRECISION was designed precisely for this purpose.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-04  9:45                   ` Eric Botcazou
@ 2014-07-07  6:01                     ` DJ Delorie
  2014-07-10  8:32                       ` Eric Botcazou
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-07-07  6:01 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> I'm very skeptical...  In any case, having a type whose TYPE_SIZE is smaller 
> than the size of its MODE is a lie which will bite you back at some point.

Except gcc now knows the size of partial int modes.  In this case,
PSImode is 20 bits and TYPE_SIZE is 20 bits, so they match.

The code was biting me when TYPE_SIZE was bigger than PSImode, and the
code kept choosing SImode instead.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-07  6:01                     ` DJ Delorie
@ 2014-07-10  8:32                       ` Eric Botcazou
  2014-07-10 16:35                         ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-07-10  8:32 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> Except gcc now knows the size of partial int modes.  In this case,
> PSImode is 20 bits and TYPE_SIZE is 20 bits, so they match.

I don't understand.  The problematic change is

> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

which means that the precision of the mode is used to set the size of the 
type, which very likely means that the size of the mode is larger.  So the 
size of the mode will be larger than the size of the type, which is a lie.

> The code was biting me when TYPE_SIZE was bigger than PSImode, and the
> code kept choosing SImode instead.

IMO you're papering over the real issue, which appears to be the choice of the 
mode.  Why does the code choose PSImode instead of SImode, if the type and the 
mode have the same precision (20) and size (24)?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-10  8:32                       ` Eric Botcazou
@ 2014-07-10 16:35                         ` DJ Delorie
  2014-07-11  9:06                           ` Eric Botcazou
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-07-10 16:35 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> which means that the precision of the mode is used to set the size
> of the type, which very likely means that the size of the mode is
> larger.  So the size of the mode will be larger than the size of the
> type, which is a lie.

For partial int modes, the precision and size are the same, and
normally not a power of two.  The assumption that "PSImode is the same
size as SImode" is no longer valid.

> > The code was biting me when TYPE_SIZE was bigger than PSImode, and
> > the code kept choosing SImode instead.
> 
> IMO you're papering over the real issue, which appears to be the
> choice of the mode.  Why does the code choose PSImode instead of
> SImode, if the type and the mode have the same precision (20) and
> size (24)?

PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.

SImode is 32 bits, fits in two 16 bit registers, and uses 32 bit operations.

If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.

If you look at part 2 of the patch, you'll see lots of code that
implements this logic, although the change to specify the sizes of
partial int modes has been in for a while.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-10 16:35                         ` DJ Delorie
@ 2014-07-11  9:06                           ` Eric Botcazou
  2014-07-11 16:31                             ` DJ Delorie
  0 siblings, 1 reply; 49+ messages in thread
From: Eric Botcazou @ 2014-07-11  9:06 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.

Then why do you need this change?

> -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> (type))); break;

What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?

> If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
> larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.

Size or precision?  That's the crux of the matter.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-11  9:06                           ` Eric Botcazou
@ 2014-07-11 16:31                             ` DJ Delorie
  2014-07-12  9:15                               ` Eric Botcazou
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-07-11 16:31 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches


> > PSImode is 20 bits, fits in a 20 bit register, and uses 20 bit operations.
> 
> Then why do you need this change?

Because parts of the gcc code use the byte size instead of the bit
size, or round up, or assume powers-of-two sizes.

> > -      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> > +      TYPE_SIZE (type) = bitsize_int (GET_MODE_PRECISION (TYPE_MODE
> > (type))); TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE
> > (type))); break;
> 
> What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?

It *should* be 20 and 20 for msp430.  But GET_MODE_BITSIZE returns 32,
because it's a macro that does GET_MODE_SIZE * BITS_PER_UNIT, so it
cannot return 20.

> > If a type is 17-20 bits, PSImode is chosen.  If it's 21 bits or
> > larger, SImode is chosen.  If it's 16 or fewer bits, HImode is chosen.
> 
> Size or precision?  That's the crux of the matter.

GCC typically uses size for "fits in a" tests.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch 1/4] change specific int128 -> generic intN
  2014-07-11 16:31                             ` DJ Delorie
@ 2014-07-12  9:15                               ` Eric Botcazou
  0 siblings, 0 replies; 49+ messages in thread
From: Eric Botcazou @ 2014-07-12  9:15 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

> > What are GET_MODE_BITSIZE and GET_MODE_PRECISION for PSImode?
> 
> It *should* be 20 and 20 for msp430.  But GET_MODE_BITSIZE returns 32,
> because it's a macro that does GET_MODE_SIZE * BITS_PER_UNIT, so it
> cannot return 20.

No, it should not be 20, mode sizes are multiple of the unit, you're mixing 
precision and size.  I doubt the hardware accesses 20 bits, more probably 24 
or 32 bits, so the mode size cannot be 20 bits.

> GCC typically uses size for "fits in a" tests.

Then change them to use the precision when this matters, the wide-int folks 
have already changed them in a few places but that's probably not sufficient.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-07 16:44     ` Joseph S. Myers
@ 2014-05-08  3:08       ` DJ Delorie
  0 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-05-08  3:08 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches


> OK (presuming the usual bootstrap and regression test, which should 
> provide a reasonably thorough test of this code through the <stdint.h> 
> tests).

Bootstrapped with and without the patch on x86-64, no regressions.
Committed.  Thanks!

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-04 21:09   ` DJ Delorie
  2014-05-05 18:58     ` Mike Stump
@ 2014-05-07 16:44     ` Joseph S. Myers
  2014-05-08  3:08       ` DJ Delorie
  1 sibling, 1 reply; 49+ messages in thread
From: Joseph S. Myers @ 2014-05-07 16:44 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

On Sun, 4 May 2014, DJ Delorie wrote:

> > I'm not aware of any reason those macros need to have decimal values.  I'd 
> > suggest removing the precomputed table and printing them in hex, which is 
> > easy for values of any precision.
> 
> Here's an independent change that removes the decimal table and
> replaces it with generated hex values.  I included the relevent output
> of gcc -E -dM also.

OK (presuming the usual bootstrap and regression test, which should 
provide a reasonably thorough test of this code through the <stdint.h> 
tests).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-05 18:58     ` Mike Stump
@ 2014-05-05 19:01       ` DJ Delorie
  0 siblings, 0 replies; 49+ messages in thread
From: DJ Delorie @ 2014-05-05 19:01 UTC (permalink / raw)
  To: Mike Stump; +Cc: joseph, gcc-patches


> After tomorrow, this should be:
> 
> MAX_BITSIZE_MODE_ANY_INT, not 128.

Heh.

Ok, after tomorrow, assume my patch has that instead :-)

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-04 21:09   ` DJ Delorie
@ 2014-05-05 18:58     ` Mike Stump
  2014-05-05 19:01       ` DJ Delorie
  2014-05-07 16:44     ` Joseph S. Myers
  1 sibling, 1 reply; 49+ messages in thread
From: Mike Stump @ 2014-05-05 18:58 UTC (permalink / raw)
  To: DJ Delorie; +Cc: Joseph S. Myers, gcc-patches@gcc.gnu.org Patches

On May 4, 2014, at 2:09 PM, DJ Delorie <dj@redhat.com> wrote:
> Here's an independent change that removes the decimal table and
> replaces it with generated hex values.  I included the relevent output
> of gcc -E -dM also.

> +  /* Allows bit sizes up to 128 bits.  */
> +#define PBOH_SZ (128/4+4)

After tomorrow, this should be:

MAX_BITSIZE_MODE_ANY_INT, not 128.

> +  char value[PBOH_SZ];

:-)

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-01 22:15 ` Joseph S. Myers
  2014-05-01 23:35   ` DJ Delorie
@ 2014-05-04 21:09   ` DJ Delorie
  2014-05-05 18:58     ` Mike Stump
  2014-05-07 16:44     ` Joseph S. Myers
  1 sibling, 2 replies; 49+ messages in thread
From: DJ Delorie @ 2014-05-04 21:09 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches


> I'm not aware of any reason those macros need to have decimal values.  I'd 
> suggest removing the precomputed table and printing them in hex, which is 
> easy for values of any precision.

Here's an independent change that removes the decimal table and
replaces it with generated hex values.  I included the relevent output
of gcc -E -dM also.

Index: c-family/c-cppbuiltin.c
===================================================================
--- c-family/c-cppbuiltin.c	(revision 209391)
+++ c-family/c-cppbuiltin.c	(working copy)
@@ -1285,45 +1295,71 @@ builtin_define_constants (const char *ma
 static void
 builtin_define_type_max (const char *macro, tree type)
 {
   builtin_define_type_minmax (NULL, macro, type);
 }
 
+static void
+print_bits_of_hex (char *buf, int bufsz, int count)
+{
+  gcc_assert (bufsz > 3);
+  *buf++ = '0';
+  *buf++ = 'x';
+  bufsz -= 2;
+
+  gcc_assert (count > 0);
+
+  switch (count % 4) {
+  case 0:
+    break;
+  case 1:
+    *buf++ = '1';
+    bufsz --;
+    count -= 1;
+    break;
+  case 2:
+    *buf++ = '3';
+    bufsz --;
+    count -= 2;
+    break;
+  case 3:
+    *buf++ = '7';
+    bufsz --;
+    count -= 3;
+    break;
+  }
+  while (count >= 4)
+    {
+      gcc_assert (bufsz > 1);
+      *buf++ = 'f';
+      bufsz --;
+      count -= 4;
+    }
+  gcc_assert (bufsz > 0);
+  *buf++ = 0;
+}
+
 /* Define MIN_MACRO (if not NULL) and MAX_MACRO for TYPE based on the
    precision of the type.  */
 
 static void
 builtin_define_type_minmax (const char *min_macro, const char *max_macro,
 			    tree type)
 {
-  static const char *const values[]
-    = { "127", "255",
-	"32767", "65535",
-	"2147483647", "4294967295",
-	"9223372036854775807", "18446744073709551615",
-	"170141183460469231731687303715884105727",
-	"340282366920938463463374607431768211455" };
+  /* Allows bit sizes up to 128 bits.  */
+#define PBOH_SZ (128/4+4)
+  char value[PBOH_SZ];
 
-  const char *value, *suffix;
+  const char *suffix;
   char *buf;
-  size_t idx;
+  int bits;
 
-  /* Pre-rendering the values mean we don't have to futz with printing a
-     multi-word decimal value.  There are also a very limited number of
-     precisions that we support, so it's really a waste of time.  */
-  switch (TYPE_PRECISION (type))
-    {
-    case 8:	idx = 0; break;
-    case 16:	idx = 2; break;
-    case 32:	idx = 4; break;
-    case 64:	idx = 6; break;
-    case 128:	idx = 8; break;
-    default:    gcc_unreachable ();
-    }
+  bits = TYPE_PRECISION (type) + (TYPE_UNSIGNED (type) ? 0 : -1);
+
+  print_bits_of_hex (value, PBOH_SZ, bits);
 
-  value = values[idx + TYPE_UNSIGNED (type)];
   suffix = type_suffix (type);
 
   buf = (char *) alloca (strlen (max_macro) + 1 + strlen (value)
                          + strlen (suffix) + 1);
   sprintf (buf, "%s=%s%s", max_macro, value, suffix);
 


 $ ./cc1 -quiet -E -dM dj.c | egrep -i '(min|max)' | grep 0x | sort
#define __INT16_MAX__ 0x7fff
#define __INT20_MAX__ 0x7ffffL
#define __INT32_MAX__ 0x7fffffffL
#define __INT64_MAX__ 0x7fffffffffffffffLL
#define __INT8_MAX__ 0x7f
#define __INTMAX_MAX__ 0x7fffffffffffffffLL
#define __INTPTR_MAX__ 0x7fff
#define __INT_FAST16_MAX__ 0x7fff
#define __INT_FAST32_MAX__ 0x7fffffffL
#define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
#define __INT_FAST8_MAX__ 0x7fff
#define __INT_LEAST16_MAX__ 0x7fff
#define __INT_LEAST32_MAX__ 0x7fffffffL
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
#define __INT_LEAST8_MAX__ 0x7f
#define __INT_MAX__ 0x7fff
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
#define __LONG_MAX__ 0x7fffffffL
#define __PTRDIFF_MAX__ 0x7fff
#define __SCHAR_MAX__ 0x7f
#define __SHRT_MAX__ 0x7fff
#define __SIG_ATOMIC_MAX__ 0x7fff
#define __SIZE_MAX__ 0xffffU
#define __UINT16_MAX__ 0xffffU
#define __UINT20_MAX__ 0xfffffUL
#define __UINT32_MAX__ 0xffffffffUL
#define __UINT64_MAX__ 0xffffffffffffffffULL
#define __UINT8_MAX__ 0xff
#define __UINTMAX_MAX__ 0xffffffffffffffffULL
#define __UINTPTR_MAX__ 0xffffU
#define __UINT_FAST16_MAX__ 0xffffU
#define __UINT_FAST32_MAX__ 0xffffffffUL
#define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
#define __UINT_FAST8_MAX__ 0xffffU
#define __UINT_LEAST16_MAX__ 0xffffU
#define __UINT_LEAST32_MAX__ 0xffffffffUL
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
#define __UINT_LEAST8_MAX__ 0xff
#define __WCHAR_MAX__ 0x7fffffffL
#define __WINT_MAX__ 0xffffU

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-01 23:35   ` DJ Delorie
@ 2014-05-02 17:45     ` Joseph S. Myers
  0 siblings, 0 replies; 49+ messages in thread
From: Joseph S. Myers @ 2014-05-02 17:45 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

On Thu, 1 May 2014, DJ Delorie wrote:

> Do we have a routine to do that already?

I don't know.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-05-01 22:15 ` Joseph S. Myers
@ 2014-05-01 23:35   ` DJ Delorie
  2014-05-02 17:45     ` Joseph S. Myers
  2014-05-04 21:09   ` DJ Delorie
  1 sibling, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-05-01 23:35 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches


Do we have a routine to do that already?

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [patch] change specific int128 -> generic intN
  2014-04-14 23:01 [patch] " DJ Delorie
@ 2014-05-01 22:15 ` Joseph S. Myers
  2014-05-01 23:35   ` DJ Delorie
  2014-05-04 21:09   ` DJ Delorie
  0 siblings, 2 replies; 49+ messages in thread
From: Joseph S. Myers @ 2014-05-01 22:15 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

On Mon, 14 Apr 2014, DJ Delorie wrote:

> The only non-automatic part of this is the table of pre-computed
> constants in builtin_define_type_minmax() (c-family/c-cppbuiltin.c).

I'm not aware of any reason those macros need to have decimal values.  I'd 
suggest removing the precomputed table and printing them in hex, which is 
easy for values of any precision.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [patch] change specific int128 -> generic intN
@ 2014-04-14 23:01 DJ Delorie
  2014-05-01 22:15 ` Joseph S. Myers
  0 siblings, 1 reply; 49+ messages in thread
From: DJ Delorie @ 2014-04-14 23:01 UTC (permalink / raw)
  To: gcc-patches


This patch replaces the current int128 support with a generic intN
support, which happens to provide int128 as well as up to three
additional intN types per target.  I will post a separate patch for
the msp430 backend demonstrating the use of this new feature for
__int20, as well as a third to fix some problems with PSImode in
general.

The general idea is that genmodes has a new macro INT_N() for
<tm>-modes.def, which gives the mode and precision to use for
target-specific intN types.  These types are always created, but the
parser will error with "unsupported" if the target does not support
that mode for that compile (i.e. because of command line switches,
etc).  There's an INT_N(TI,128) in the common sources.

If the target defines any types larger than "long long", those types
(like int128 before) will be used for type promotion, but types
smaller than "long long" will not, to avoid confusing the C type
promotion rules.  Otherwise, it's up to the source being compiled to
specific __intN types as desired.

The only non-automatic part of this is the table of pre-computed
constants in builtin_define_type_minmax() (c-family/c-cppbuiltin.c).
I've added the entries for int20 and int24 but each target will need
to expand the table as needed.

gcc/

	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __intN for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.

gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Remove __int128-specific entries.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.

gcc/lto/
	* lto-lang.c (lto_build_c_type_nodes): Check intN types for
	size-type as well.
	(lto_init): Initialize all intN types, not just int128.

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2014-07-12  9:15 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-14 23:03 [patch] change specific int128 -> generic intN DJ Delorie
2014-04-15  5:54 ` Marc Glisse
2014-04-15  6:17   ` DJ Delorie
2014-04-17 20:17     ` Marc Glisse
2014-05-08 23:34 ` DJ Delorie
2014-05-09  0:26   ` Marc Glisse
2014-05-09  2:21     ` DJ Delorie
2014-05-09  7:59       ` Marc Glisse
2014-05-09 18:29         ` DJ Delorie
2014-06-21 16:24 ` DJ Delorie
2014-06-21 17:35   ` Marc Glisse
2014-06-24  5:40     ` DJ Delorie
2014-06-28 10:09       ` Marc Glisse
2014-06-21 20:17   ` Joseph S. Myers
2014-06-24  5:51     ` DJ Delorie
2014-06-24 23:32     ` [patch 1/4] " DJ Delorie
2014-06-27 11:22       ` Eric Botcazou
2014-06-27 21:04         ` DJ Delorie
2014-06-27 21:38           ` Joseph S. Myers
2014-06-27 21:50             ` DJ Delorie
2014-06-27 21:57               ` Joseph S. Myers
2014-06-27 23:31                 ` DJ Delorie
2014-07-01  2:23                 ` DJ Delorie
2014-07-02  8:18           ` Eric Botcazou
2014-07-02 14:57             ` DJ Delorie
2014-07-03 15:53               ` Eric Botcazou
2014-07-03 16:12                 ` DJ Delorie
2014-07-03 16:30                   ` Bernd Schmidt
2014-07-03 20:01                     ` DJ Delorie
2014-07-04  9:50                       ` Eric Botcazou
2014-07-04  9:45                   ` Eric Botcazou
2014-07-07  6:01                     ` DJ Delorie
2014-07-10  8:32                       ` Eric Botcazou
2014-07-10 16:35                         ` DJ Delorie
2014-07-11  9:06                           ` Eric Botcazou
2014-07-11 16:31                             ` DJ Delorie
2014-07-12  9:15                               ` Eric Botcazou
2014-06-24 23:38     ` [patch 2/4] " DJ Delorie
2014-06-24 23:39     ` [patch 3/4] " DJ Delorie
2014-06-24 23:42     ` [patch 4/4] " DJ Delorie
  -- strict thread matches above, loose matches on Subject: below --
2014-04-14 23:01 [patch] " DJ Delorie
2014-05-01 22:15 ` Joseph S. Myers
2014-05-01 23:35   ` DJ Delorie
2014-05-02 17:45     ` Joseph S. Myers
2014-05-04 21:09   ` DJ Delorie
2014-05-05 18:58     ` Mike Stump
2014-05-05 19:01       ` DJ Delorie
2014-05-07 16:44     ` Joseph S. Myers
2014-05-08  3:08       ` DJ Delorie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).