diff mbox

__int256

Message ID 1880D85D-1D97-4345-A1A6-5DBF434D3998@comcast.net
State New
Headers show

Commit Message

Mike Stump July 13, 2012, 10:53 p.m. UTC
On Jul 13, 2012, at 6:39 AM, Joseph S. Myers wrote:
> On Fri, 13 Jul 2012, Mike Stump wrote:
> 
>> As I said, in Kenny's next patch, we add support for all constants of 
>> any size the port needs.  I don't know if you've ever tried to use the 
>> compiler with OImode, but, what I can say is the bugs are not terribly 
>> latent at times and they are not hidden very well at all, today.  The 
>> goal of course, is to improve that and make it work better.  These 
>> issues that I know about existed, prior to my patch, and we are in the 
>> process of fixing them.  Some have been fixed, others remain to be 
>> fixed.  The issues I'm thinking about exist with or without my patch to 
>> the frontend to support __int256.  Merely adding __int256 doesn't make 
>> any of the issues I'm aware of appear, and the issues I'm aware of don't 
>> appear with sizes less than 256.
> 
> I think the patches allowing constants of such a type to work should go in 
> first,

I understand the beauty of putting in the const wide int stuff first...  I don't think it matters much to me...  but I might ask why?  I think we have added support for all in-tree gcc ports for all possible testcases.  Do you know of a single testcase that fails on a single port?

> and the libgcc support,


I wanted to separate the patches and keep them in small well focused review groups, as they hit wildly different reviewers.

> before we consider the support for the type from the front ends using keywords as opposed to mode attributes.

I believe that libgcc support for all existing in-tree ports of gcc is already complete.  We'd be happy to do any libgcc work necessary to make any testcase work on any existing in-tree gcc port.  If you know of any work that remains to be done, please provide a testcase, and I can ensure the work is complete.

> You're using OImode in target-independent code.

> But I don't see a change to machmode.def to add it as a machine-independent mode.

Ah, good catch.  I've moved OImode up from the ports in the patch below.

> Nor do I think
> it *should* be a machine-independent mode; it's sufficiently specialised 
> that it should be possible to do things without it needing to be one.

Hum, how about this, if you fix __int128 to do it the way you want, then I will fix __int256 to copy the style that is set by __int128.  I'd rather have them be exactly the same, so that testing for one will more likely help the other one.  I don't have a good idea of a better way to do this.  Longer term, I'd like __int256 to be universally available, just like long is and just like long long is.  We can't do that yet, I think doing that is premature.

> See my comments (several messages on 1 July 2011) about 40-bit integer 
> support;

Ick, 40 / 8 is 5, and 5 isn't a power of 2, therefore, they are different cases to me.	  I appreciate that you'd like to see HImode go, wake me up when that is done.

> carefully designed target hooks to specify the keywords / modes 
> for target-specific integer types are better than adding more and more 
> cases to several difference places in the target-independent compiler.

Agreed, on general principals.  And, if I waned 60 bit support, or 250 bit support, I'm right there with you.  However, 32 support, has, over time, proven to be the right answer.  Likewise, merely shifted by some years later, 64 bit support.  While 128 and 256 may seem to you to be as odd now as 64 bit support was back when 8 was all the rage...  well, I'll stop there.  Let me just say, these are special because they are powers of 2.

If you can sketch out a better incantation for the 128 and 256 bit support, I can try my hand at improving it.  I just don't know any better form for it.  I'd argue that all powers of twos in use by any port, should be put into machmode.def.  I can rip out all TImode handling, leaving the int128 handling, the TImode code I think is redundant with the int128 code.  Would you like me to do that?  I just don't want to be on the hook when it doesn't work out for someone.

> __int128_t and __uint128_t are legacy built-in typedef names and I don't 
> think there should be any analogue for 256-bit integers; just __int256 and 
> unsigned __int256.

Ok, fixed.

>> I have put the patch through the C test suite, and it doesn't show any 
>> failures.
> 
> Certainly you should add analogues of 
> gcc.dg/torture/fp-int-convert-*timode.c for the new type and verify that 
> those tests all work for it.  It would seem advisable to add tests 
> covering pure integer operations for the new type (all the C integer 
> operations), for both constants and runtime evaluation, as well.

Ok, fixed.  I put in the portable testcase, esoteric things like 80 bit floating point numbers can be added by people that like such things.

Comments

Joseph Myers July 13, 2012, 11:21 p.m. UTC | #1
On Fri, 13 Jul 2012, Mike Stump wrote:

> I understand the beauty of putting in the const wide int stuff first...  
> I don't think it matters much to me...  but I might ask why?  I think we 
> have added support for all in-tree gcc ports for all possible testcases.  
> Do you know of a single testcase that fails on a single port?

We need to be careful about putting in changes that are only relevant for 
out-of-tree ports, because it's impossible for anyone using FSF GCC to 
validate whether the code in question works properly.  Fixing issues that 
look like they would appear with a port with 256-bit integer support, and 
adding associated testcases, helps convince peopel that the code is sound.  
So does implementing it in a suitably generic way, so that the same code 
paths are used by narrower types for in-tree ports rather than there being 
code purely for 256-bit integers that is dead code for FSF GCC.

> I believe that libgcc support for all existing in-tree ports of gcc is 
> already complete.  We'd be happy to do any libgcc work necessary to make 
> any testcase work on any existing in-tree gcc port.  If you know of any 
> work that remains to be done, please provide a testcase, and I can 
> ensure the work is complete.

The question is whether someone could just add their own 256-bit port and 
reasonably expect it to work.  And when submitting patches, it's the job 
of the submitter to make it easy for the reviewer to give them an A - 
submit a patch series that makes it transparent to the reviewer that any 
questions they thought up have already been addressed (because they can 
see relevant testcases added to the testsuite, for example).

> Hum, how about this, if you fix __int128 to do it the way you want, then 
> I will fix __int256 to copy the style that is set by __int128.  I'd 
> rather have them be exactly the same, so that testing for one will more 
> likely help the other one.  I don't have a good idea of a better way to 
> do this.  Longer term, I'd like __int256 to be universally available, 
> just like long is and just like long long is.  We can't do that yet, I 
> think doing that is premature.

Making a type universally available is dangerous because there are ABI 
implications - the function-calling ABI for a type should be worked out 
with the ABI maintainers for each relevant architecture rather than just 
blindly adding it and hoping that what the back end happens to do is a 
sensible ABI for all other compilers for that architecture to copy.  The 
ABI for complex numbers on some architectures is an awful mess because of 
just blindly making them universally available without working out ABIs 
properly....

> If you can sketch out a better incantation for the 128 and 256 bit 
> support, I can try my hand at improving it.  I just don't know any 
> better form for it.  I'd argue that all powers of twos in use by any 
> port, should be put into machmode.def.  I can rip out all TImode 
> handling, leaving the int128 handling, the TImode code I think is 
> redundant with the int128 code.  Would you like me to do that?  I just 
> don't want to be on the hook when it doesn't work out for someone.

I believe I sketched things in July 2011 - I'd guess sorting this out 
properly and incrementally is on the order of a ten-patch series (each 
patch being small and clearly safe for existing targets), not a 
hundred-patch series.  For example, I said:

  * The c_common_type_for_size code using those nodes is suspicious.  Front 
  ends shouldn't care about modes like that.  Check standard types, 
  otherwise defer to something generic that loops over available types or 
  modes or builds a type as needed.

So in that case I'd do the following:

* Check standard types, int, signed char, short, long, long long, as at 
present.

* Check a list of __intN types.  The list would be target-dependent.  
Targets supporting __int128 would define a relevant hook to produce the 
list containing just __int128.  Your new target would define it to contain 
__int128 and __int256.

* Check widest_integer_literal_type_node, as at present.

* Check for modes, not through globals hardcoded for each mode as at 
present but through iterating through integer modes.

Maybe getting rid of the globals such as intQI_type_node, replacing them 
by something sized to cover whatever integer modes on the target can be 
used for integer types and replacing code using those globals by something 
iterating over integer modes, would be a good first step.  It shouldn't be 
that hard to move on to making the existence of TImode target-specific 
(I'd guess there would be a common .def file used by all targets that have 
TImode).
Mike Stump July 14, 2012, 4:22 a.m. UTC | #2
On Jul 13, 2012, at 4:21 PM, Joseph S. Myers wrote:
> On Fri, 13 Jul 2012, Mike Stump wrote:
>> I understand the beauty of putting in the const wide int stuff first...  
>> I don't think it matters much to me...  but I might ask why?  I think we 
>> have added support for all in-tree gcc ports for all possible testcases.  
>> Do you know of a single testcase that fails on a single port?
> 
> We need to be careful about putting in changes that are only relevant for 
> out-of-tree ports, because it's impossible for anyone using FSF GCC to 
> validate whether the code in question works properly.

Anyone that wants to validate my work can trivially do so.  They are free to grab any of the OI ports, and turn on scalar OImode, and then test.  Because it is trivial to validate it, I have no clue what you mean by impossible.  Does that mean that you have no access to an x86_64?  I just can't begin to understand what you mean by impossible, can you elaborate?

> The question is whether someone could just add their own 256-bit port and 
> reasonably expect it to work.

No, they can not reasonable expect it to work.  They are guaranteed that any expectations of goodness are misplaced, I will personally make that guarantee.  What they can expect to work, are those things they have tested that work; that's all.  The compiler has bugs, that those bugs prevent good code from working.  This has always been the case, and will always be the case.  I'm a realist, what I can say about the patch is that the compiler will work better with the patch, than without the patch.  The patch lies in the direction of goodness, and that it is impossible to get to goodness without either applying the patch, or creating a virtually identical patch.

> And when submitting patches, it's the job 
> of the submitter to make it easy for the reviewer to give them an A

I don't see what you all see.  For example, you see that it is impossible to validate my work, I only see that it is trivially possible to validate my work.  I can't explain the difference in viewpoint.  Richard says that the patch introduces wrong-code bugs almost everywhere in the compiler, I only see that it does not.  I can't explain the difference.  Richard says I expose users to bugs, I see that I do not.  I can't explain the difference.  I see that you worry that the patch is unsound, I only see that it is not.  I can't explain the difference.  I see that you want to pend this on libgcc work.  I see that there is no benefit to doing that.  I can't explain the difference.  I see that Richard wants to pend the work on the cont_wide_int work,  I see that there is no benefit to doing that.  I can't explain the difference.  The list is seemingly endless...

I don't have a proof the work is sound, and cannot sign up to provide one at this time.  I do not have the time at this point to fix all 256-bit bugs in the compiler.  I don't have time to add support for all possible future ports of gcc.  I don't have time to craft abis for all gcc ports.  I don't have time to implement argument passing for all other ports.  I don't have time to validate __int256 for you.  I don't have time to re-implement __int128 support in the compiler for you.

So, are there any other specific actionable things I can do for you to make the patch acceptable?
Joseph Myers July 14, 2012, 8:13 p.m. UTC | #3
On Fri, 13 Jul 2012, Mike Stump wrote:

> I don't have time to re-implement __int128 support in the compiler for 
> you.
> 
> So, are there any other specific actionable things I can do for you to 
> make the patch acceptable?

No.  The right way to make __int256 support - the feature, not the present 
patch at all - acceptable for me is a series of incremental patches 
converting the existing __int128 support to use hooks for the target to 
define what __intN types it has without the architecture-independent 
compiler needing to hardcode the details of those types.  You might push 
on whoever added __int128 support to add testcases for it - tests that 
__int128 works as expected including execution of all the usual C integer 
operations as well as __int128 being accecpted and rejected in the right 
contexts - since such tests are unfortunately missing.  Having such tests 
would both help validate that a reworking of __int128 support does not 
cause regressions, as well as being a possible basis to add tests of 
__int256.
diff mbox

Patch

diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index d8e9e56..564e5c7 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -72,6 +72,8 @@  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_INT256, int256_integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT256, int256_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)
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index bbb437d..387105a 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -8945,6 +8945,10 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_int256)
+		  error_at (loc,
+			    ("both %<long%> and %<__int256%> in "
+			     "declaration specifiers"));
 	      else if (specs->typespec_word == cts_int128)
 		  error_at (loc,
 			    ("both %<long%> and %<__int128%> in "
@@ -8989,6 +8993,10 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
+	      else if (specs->typespec_word == cts_int256)
+		error_at (loc,
+			  ("both %<short%> and %<__int256%> in "
+			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_int128)
 		error_at (loc,
 			  ("both %<short%> and %<__int128%> in "
@@ -9154,7 +9162,13 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
 	      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_int256)
+	        {
+		  error_at (loc,
+			    ("both %<_Sat%> and %<__int256%> in "
+			     "declaration specifiers"));
+	        }
+	      else if (specs->typespec_word == cts_int128)
 	        {
 		  error_at (loc,
 			    ("both %<_Sat%> and %<__int128%> in "
@@ -9218,7 +9232,7 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
+	     "__int256", "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
@@ -9227,6 +9241,34 @@  declspecs_add_type (location_t loc, struct c_declspecs *specs,
 	    }
 	  switch (i)
 	    {
+	    case RID_INT256:
+	      if (int256_integer_type_node == NULL_TREE)
+		{
+		  error_at (loc, "%<__int256%> is not supported for this target");
+		  return specs;
+		}
+	      if (!in_system_header)
+		pedwarn (loc, OPT_Wpedantic,
+			 "ISO C does not support %<__int256%> type");
+
+	      if (specs->long_p)
+		error_at (loc,
+			  ("both %<__int256%> and %<long%> in "
+			   "declaration specifiers"));
+	      else if (specs->saturating_p)
+		error_at (loc,
+			  ("both %<_Sat%> and %<__int256%> in "
+			   "declaration specifiers"));
+	      else if (specs->short_p)
+		error_at (loc,
+			  ("both %<__int256%> and %<short%> in "
+			   "declaration specifiers"));
+	      else
+		{
+		  specs->typespec_word = cts_int256;
+		  specs->locations[cdw_typespec] = loc;
+		}
+	      return specs;
 	    case RID_INT128:
 	      if (int128_integer_type_node == NULL_TREE)
 		{
@@ -9788,6 +9830,19 @@  finish_declspecs (struct c_declspecs *specs)
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
+    case cts_int256:
+      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
+		     ? int256_unsigned_type_node
+		     : int256_integer_type_node);
+      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);
+	}
+      break;
     case cts_int128:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8fb9443..f6597d5 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -59,11 +59,13 @@  cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
+	tree int256_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 int256_unsigned_type_node;
 	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
@@ -97,12 +99,14 @@  cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 	tree intSI_type_node;
 	tree intDI_type_node;
 	tree intTI_type_node;
+	tree intOI_type_node;
 
 	tree unsigned_intQI_type_node;
 	tree unsigned_intHI_type_node;
 	tree unsigned_intSI_type_node;
 	tree unsigned_intDI_type_node;
 	tree unsigned_intTI_type_node;
+	tree unsigned_intOI_type_node;
 
 	tree widest_integer_literal_type_node;
 	tree widest_unsigned_literal_type_node;
@@ -456,6 +460,7 @@  const struct c_common_resword c_common_reswords[] =
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
+  { "__int256",		RID_INT256,	0 },
   { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
@@ -3047,6 +3052,11 @@  c_common_type_for_size (unsigned int bits, int unsignedp)
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
+  if (int256_integer_type_node
+      && bits == TYPE_PRECISION (int256_integer_type_node))
+    return (unsignedp ? int256_unsigned_type_node
+	    : int256_integer_type_node);
+
   if (int128_integer_type_node
       && bits == TYPE_PRECISION (int128_integer_type_node))
     return (unsignedp ? int128_unsigned_type_node
@@ -3130,6 +3140,10 @@  c_common_type_for_mode (enum machine_mode mode, int unsignedp)
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
+  if (int256_integer_type_node
+      && mode == TYPE_MODE (int256_integer_type_node))
+    return unsignedp ? int256_unsigned_type_node : int256_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;
@@ -3151,6 +3165,8 @@  c_common_type_for_mode (enum machine_mode mode, int unsignedp)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
+  if (mode == TYPE_MODE (intOI_type_node))
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
   if (mode == TYPE_MODE (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3348,6 +3364,10 @@  c_common_signed_or_unsigned_type (int unsignedp, tree type)
     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 (int256_integer_type_node
+      && (type1 == int256_integer_type_node
+	  || type1 == int256_unsigned_type_node))
+    return unsignedp ? int256_unsigned_type_node : int256_integer_type_node;
   if (int128_integer_type_node
       && (type1 == int128_integer_type_node
 	  || type1 == int128_unsigned_type_node))
@@ -3355,6 +3375,8 @@  c_common_signed_or_unsigned_type (int unsignedp, tree 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 == intOI_type_node || type1 == unsigned_intOI_type_node)
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3469,11 +3491,16 @@  c_common_signed_or_unsigned_type (int unsignedp, tree type)
   if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
     return (unsignedp ? int128_unsigned_type_node
 	    : int128_integer_type_node);
+  if (int256_integer_type_node && TYPE_OK (int256_integer_type_node))
+    return (unsignedp ? int256_unsigned_type_node
+	    : int256_integer_type_node);
   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 (intOI_type_node))
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3512,6 +3539,10 @@  c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
+  if (int256_integer_type_node
+      && width == TYPE_PRECISION (int256_integer_type_node))
+    return (unsignedp ? int256_unsigned_type_node
+	    : int256_integer_type_node);
   if (int128_integer_type_node
       && width == TYPE_PRECISION (int128_integer_type_node))
     return (unsignedp ? int128_unsigned_type_node
@@ -4920,6 +4951,13 @@  c_common_nodes_and_builtins (void)
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
+  if (int256_integer_type_node != NULL_TREE)
+    {
+      record_builtin_type (RID_INT256, "__int256",
+			   int256_integer_type_node);
+      record_builtin_type (RID_MAX, "__int256 unsigned",
+			   int256_unsigned_type_node);
+    }
   if (int128_integer_type_node != NULL_TREE)
     {
       record_builtin_type (RID_INT128, "__int128",
@@ -10844,6 +10882,7 @@  keyword_begins_type_specifier (enum rid keyword)
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
+    case RID_INT256:
     case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index ab9d0f9..90d4303 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -93,7 +93,7 @@  enum rid
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
+  RID_INT256,  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,
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 89a22a3..27f8730 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -897,6 +897,9 @@  c_cpp_builtins (cpp_reader *pfile)
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201107");
 
+  if (int256_integer_type_node != NULL_TREE)
+    builtin_define_type_sizeof ("__SIZEOF_INT256__",
+			        int256_integer_type_node);
   if (int128_integer_type_node != NULL_TREE)
     builtin_define_type_sizeof ("__SIZEOF_INT128__",
 			        int128_integer_type_node);
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index d445187..3a25241 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -937,6 +937,9 @@  pp_c_integer_constant (c_pretty_printer *pp, tree i)
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
+  else if (type == int256_integer_type_node
+           || type == int256_unsigned_type_node)
+    pp_string (pp, "I256");
   else if (type == int128_integer_type_node
            || type == int128_unsigned_type_node)
     pp_string (pp, "I128");
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index b4135ee..37eab46 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -473,6 +473,7 @@  c_token_starts_typename (c_token *token)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
+	case RID_INT256:
 	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
@@ -628,6 +629,7 @@  c_token_starts_declspecs (c_token *token)
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
+	case RID_INT256:
 	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
@@ -1964,6 +1966,7 @@  c_parser_static_assert_declaration_no_semi (c_parser *parser)
 
    type-specifier:
      typeof-specifier
+     __int256
      __int128
      _Decimal32
      _Decimal64
@@ -2110,6 +2113,7 @@  c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
 	  break;
 	case RID_UNSIGNED:
 	case RID_LONG:
+	case RID_INT256:
 	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
@@ -3439,6 +3443,7 @@  c_parser_attribute_any_word (c_parser *parser)
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
+	case RID_INT256:
 	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
@@ -8029,6 +8034,7 @@  c_parser_objc_selector (c_parser *parser)
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
+    case RID_INT256:
     case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 145df35..98ee22e 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -204,6 +204,7 @@  enum c_storage_class {
 };
 
 /* A type specifier keyword "void", "_Bool", "char", "int", "float",
+   "__int256", "__int128",
    "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
    or none of these.  */
 enum c_typespec_keyword {
@@ -213,6 +214,7 @@  enum c_typespec_keyword {
   cts_char,
   cts_int,
   cts_float,
+  cts_int256,
   cts_int128,
   cts_double,
   cts_dfloat32,
diff --git a/gcc/config/arm/arm-modes.def b/gcc/config/arm/arm-modes.def
index 7f19ebe..697ee9c 100644
--- a/gcc/config/arm/arm-modes.def
+++ b/gcc/config/arm/arm-modes.def
@@ -79,6 +79,5 @@  VECTOR_MODES (UACCUM, 4);     /*       V2UHA */
 /* Opaque integer modes for 3, 4, 6 or 8 Neon double registers (2 is
    TImode).  */
 INT_MODE (EI, 24);
-INT_MODE (OI, 32);
 INT_MODE (CI, 48);
 INT_MODE (XI, 64);
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index c1e82cc..33e4c42 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -85,7 +85,5 @@  VECTOR_MODE (INT, DI, 1);     /*                   V1DI */
 VECTOR_MODE (INT, SI, 1);     /*                   V1SI */
 VECTOR_MODE (INT, QI, 2);     /*                   V2QI */
 
-INT_MODE (OI, 32);
-
 /* The symbol Pmode stands for one of the above machine modes (usually SImode).
    The tm.h file specifies which one.  It is not a distinct mode.  */
diff --git a/gcc/config/ia64/ia64-modes.def b/gcc/config/ia64/ia64-modes.def
index a3d04d9..66c7291 100644
--- a/gcc/config/ia64/ia64-modes.def
+++ b/gcc/config/ia64/ia64-modes.def
@@ -64,9 +64,6 @@  ADJUST_ALIGNMENT (RF, (TARGET_ILP32 && !TARGET_HPUX) ?  4 : 16);
 
 ADJUST_ALIGNMENT (TF, (TARGET_ILP32 &&  TARGET_HPUX) ?  8 : 16);
 
-/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE.  */
-INT_MODE (OI, 32);
-
 /* Add any extra modes needed to represent the condition code.
 
    CCImode is used to mark a single predicate register instead
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index be2bf6e..05b9fcb 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -19,9 +19,6 @@  You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE.  */
-INT_MODE (OI, 32);
-
 /* Define TFmode to work around reload problem PR 20927.  */
 FLOAT_MODE (TF, 16, ieee_quad_format);
 
diff --git a/gcc/config/spu/spu-modes.def b/gcc/config/spu/spu-modes.def
index ef21012..f5674ea 100644
--- a/gcc/config/spu/spu-modes.def
+++ b/gcc/config/spu/spu-modes.def
@@ -23,7 +23,3 @@  VECTOR_MODES (INT, 16);       /* V16QI V8HI V4SI V2DI */
         
 VECTOR_MODES (FLOAT, 8);      /*            V4HF V2SF */ 
 VECTOR_MODES (FLOAT, 16);     /*       V8HF V4SF V2DF */ 
-        
-/* cse_insn needs an INT_MODE larger than WORD_MODE, otherwise some
-   parts of it will go into an infinite loop. */
-INT_MODE (OI, 32);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a4b7ae3..ac92a56 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4712,6 +4712,8 @@  typedef struct cp_decl_specifier_seq {
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
+  /* True iff "__int256" was explicitly provided.  */
+  BOOL_BITFIELD explicit_int256_p : 1;
   /* True iff "__int128" was explicitly provided.  */
   BOOL_BITFIELD explicit_int128_p : 1;
   /* True iff "char" was explicitly provided.  */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1346f92..e55fba1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8366,6 +8366,7 @@  grokdeclarator (const cp_declarator *declarator,
 {
   tree type = NULL_TREE;
   int longlong = 0;
+  int explicit_int256 = 0;
   int explicit_int128 = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
@@ -8433,6 +8434,7 @@  grokdeclarator (const cp_declarator *declarator,
   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_int256 = declspecs->explicit_int256_p;
   explicit_int128 = declspecs->explicit_int128_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
@@ -8774,6 +8776,17 @@  grokdeclarator (const cp_declarator *declarator,
 
   ctype = NULL_TREE;
 
+  if (explicit_int256)
+    {
+      if (int256_integer_type_node == NULL_TREE)
+	{
+	  error ("%<__int256%> is not supported by this target");
+	  explicit_int256 = false;
+	}
+      else if (pedantic && ! in_system_header)
+	pedwarn (input_location, OPT_Wpedantic,
+		 "ISO C++ does not support %<__int256%> for %qs", name);
+    }
   if (explicit_int128)
     {
       if (int128_integer_type_node == NULL_TREE)
@@ -8815,6 +8828,8 @@  grokdeclarator (const cp_declarator *declarator,
 	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_int256)
+	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
@@ -8831,7 +8846,7 @@  grokdeclarator (const cp_declarator *declarator,
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && !explicit_int256 && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
@@ -8873,7 +8888,9 @@  grokdeclarator (const cp_declarator *declarator,
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
+      if (explicit_int256)
+	type = int256_unsigned_type_node;
+      else if (explicit_int128)
 	type = int128_unsigned_type_node;
       else if (longlong)
 	type = long_long_unsigned_type_node;
@@ -8890,6 +8907,8 @@  grokdeclarator (const cp_declarator *declarator,
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
+  else if (explicit_int256)
+    type = int256_integer_type_node;
   else if (explicit_int128)
     type = int128_integer_type_node;
   else if (longlong)
@@ -8907,7 +8926,7 @@  grokdeclarator (const cp_declarator *declarator,
 	 "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_int256 && ! explicit_int128
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 5bdf020..b0a2816 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -151,6 +151,8 @@  integer_type_codes[itk_none] =
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
+  'q',  /* itk_int256 */
+  'k',  /* itk_unsigned_int256  */
   'n',  /* itk_int128 */
   'o',  /* itk_unsigned_int128  */
 };
@@ -2105,6 +2107,8 @@  write_CV_qualifiers_for_type (const tree type)
 		    ::= m   # unsigned long
 		    ::= x   # long long, __int64
 		    ::= y   # unsigned long long, __int64
+		    ::= q   # __int256
+		    ::= k   # unsigned __int256
 		    ::= n   # __int128
 		    ::= o   # unsigned __int128
 		    ::= f   # float
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 46f1401..6981c13 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -884,6 +884,7 @@  cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
+    case RID_INT256:
     case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
@@ -13496,6 +13497,7 @@  cp_parser_type_specifier (cp_parser* parser,
    GNU Extension:
 
    simple-type-specifier:
+     __int256
      __int128
      __typeof__ unary-expression
      __typeof__ ( type-id )
@@ -13543,6 +13545,13 @@  cp_parser_simple_type_specifier (cp_parser* parser,
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
+    case RID_INT256:
+      if (!int256_integer_type_node)
+	break;
+      if (decl_specs)
+        decl_specs->explicit_int256_p = true;
+      type = int256_integer_type_node;
+      break;
     case RID_INT128:
       if (!int128_integer_type_node)
 	break;
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index a19a893..8e8a215 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1483,6 +1483,7 @@  emit_support_tinfos (void)
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
+    &int256_integer_type_node, &int256_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,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9c261e4..3c31a40 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -364,6 +364,17 @@  cp_common_type (tree t1, tree t2)
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
+      if (int256_integer_type_node != NULL_TREE
+	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			   int256_integer_type_node)
+	      || same_type_p (TYPE_MAIN_VARIANT (t2),
+			      int256_integer_type_node)))
+	{
+	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+		    ? int256_unsigned_type_node
+		    : int256_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)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 91e7385..363e836 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -34,6 +34,7 @@  extensions, accepted by GCC in C90 mode and in C++.
 * Conditionals::        Omitting the middle operand of a @samp{?:} expression.
 * Long Long::           Double-word integers---@code{long long int}.
 * __int128::			128-bit integers---@code{__int128}.
+* __int256::			256-bit integers---@code{__int256}.
 * Complex::             Data types for complex numbers.
 * Floating Types::      Additional Floating Types.
 * Half-Precision::      Half-Precision Floating Point.
@@ -818,6 +819,17 @@  Simply write @code{__int128} for a signed 128-bit integer, or
 support in GCC to express an integer constant of type @code{__int128}
 for targets having @code{long long} integer with less then 128 bit width.
 
+@node __int256
+@section 256-bits integers
+@cindex @code{__int256} data types
+
+As an extension the integer scalar type @code{__int256} is supported for
+targets having an integer mode wide enough to hold 256-bit.
+Simply write @code{__int256} for a signed 256-bit integer, or
+@code{unsigned __int256} for an unsigned 256-bit integer.  There is no
+support in GCC to express an integer constant of type @code{__int256}
+for targets having @code{long long} integer with less then 256 bit width.
+
 @node Long Long
 @section Double-Word Integers
 @cindex @code{long long} data types
diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def
index f8673b9..d0c9286 100644
--- a/gcc/fortran/iso-c-binding.def
+++ b/gcc/fortran/iso-c-binding.def
@@ -75,6 +75,8 @@  NAMED_INTCST (ISOCBINDING_INT32_T, "c_int32_t", \
 NAMED_INTCST (ISOCBINDING_INT64_T, "c_int64_t", \
               get_int_kind_from_name (INT64_TYPE), GFC_STD_F2003)
 /* GNU Extension.  */
+NAMED_INTCST (ISOCBINDING_INT256_T, "c_int256_t", \
+              get_int_kind_from_width (256), GFC_STD_GNU)
 NAMED_INTCST (ISOCBINDING_INT128_T, "c_int128_t", \
               get_int_kind_from_width (128), GFC_STD_GNU)
 
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index aa50e3d..b2f62dc 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -758,6 +758,8 @@  gfc_build_int_type (gfc_integer_info *info)
     return intDI_type_node;
   if (TYPE_PRECISION (intTI_type_node) == mode_precision)
     return intTI_type_node;
+  if (TYPE_PRECISION (intOI_type_node) == mode_precision)
+    return intOI_type_node;
 
   return make_signed_type (mode_precision);
 }
@@ -2860,6 +2862,8 @@  gfc_type_for_size (unsigned bits, int unsignedp)
 #if HOST_BITS_PER_WIDE_INT >= 64
       if (bits == TYPE_PRECISION (intTI_type_node))
 	return intTI_type_node;
+      if (bits == TYPE_PRECISION (intOI_type_node))
+	return intOI_type_node;
 #endif
 
       if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -2872,6 +2876,8 @@  gfc_type_for_size (unsigned bits, int unsignedp)
 	return intDI_type_node;
       if (bits <= TYPE_PRECISION (intTI_type_node))
 	return intTI_type_node;
+      if (bits <= TYPE_PRECISION (intOI_type_node))
+	return intOI_type_node;
     }
   else
     {
@@ -2885,6 +2891,8 @@  gfc_type_for_size (unsigned bits, int unsignedp)
 	return unsigned_intDI_type_node;
       if (bits <= TYPE_PRECISION (unsigned_intTI_type_node))
 	return unsigned_intTI_type_node;
+      if (bits <= TYPE_PRECISION (unsigned_intOI_type_node))
+	return unsigned_intOI_type_node;
     }
 
   return NULL_TREE;
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 398cb1f..f8da33b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -4739,11 +4739,17 @@  gimple_signed_or_unsigned_type (bool unsignedp, tree type)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
+  if (int256_integer_type_node && (type1 == int256_integer_type_node || type1 == int256_unsigned_type_node))
+    return unsignedp
+           ? int256_unsigned_type_node
+	   : int256_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;
 #if HOST_BITS_PER_WIDE_INT >= 64
+  if (type1 == intOI_type_node || type1 == unsigned_intOI_type_node)
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -4855,12 +4861,18 @@  gimple_signed_or_unsigned_type (bool unsignedp, tree type)
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
+  if (int256_integer_type_node && TYPE_OK (int256_integer_type_node))
+    return (unsignedp
+	    ? int256_unsigned_type_node
+	    : int256_integer_type_node);
   if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
     return (unsignedp
 	    ? int128_unsigned_type_node
 	    : int128_integer_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
+  if (TYPE_OK (intOI_type_node))
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 280d883..3d43181 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -811,6 +811,9 @@  lto_type_for_size (unsigned precision, int unsignedp)
   if (precision <= TYPE_PRECISION (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 
+  if (precision <= TYPE_PRECISION (intOI_type_node))
+    return unsignedp ? unsigned_intOI_type_node : intOI_type_node;
+
   return NULL_TREE;
 }
 
@@ -856,6 +859,8 @@  lto_type_for_mode (enum machine_mode mode, int unsigned_p)
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (mode == TYPE_MODE (intTI_type_node))
     return unsigned_p ? unsigned_intTI_type_node : intTI_type_node;
+  if (mode == TYPE_MODE (intOI_type_node))
+    return unsigned_p ? unsigned_intOI_type_node : intOI_type_node;
 #endif
 
   if (mode == TYPE_MODE (float_type_node))
diff --git a/gcc/machmode.def b/gcc/machmode.def
index 631015f..3c2e074 100644
--- a/gcc/machmode.def
+++ b/gcc/machmode.def
@@ -187,6 +187,7 @@  INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
+INT_MODE (OI, 32);
 
 /* No partial integer modes are defined by default.  */
 
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 9a549ff..f52e255 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5488,7 +5488,8 @@  static void
 gen_int_libfunc (optab optable, const char *opname, char suffix,
 		 enum machine_mode mode)
 {
-  int maxsize = 2 * BITS_PER_WORD;
+  /* TODO: Add OImode support in libgcc.  */
+  int maxsize = 4 * BITS_PER_WORD;
 
   if (GET_MODE_CLASS (mode) != MODE_INT)
     return;
diff --git a/gcc/tree.c b/gcc/tree.c
index 41790ec..adb5a9f 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9178,6 +9178,9 @@  make_or_reuse_type (unsigned size, int unsignedp)
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
+  if (size == 256 && int256_integer_type_node)
+    return (unsignedp ? int256_unsigned_type_node
+            : int256_integer_type_node);
   if (size == 128 && int128_integer_type_node)
     return (unsignedp ? int128_unsigned_type_node
             : int128_integer_type_node);
@@ -9300,6 +9303,15 @@  build_common_tree_nodes (bool signed_char, bool short_double)
 #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 OImode, but has an 256-bit
+       integer-scalar register, this target check needs to be adjusted. */
+    if (targetm.scalar_mode_supported_p (OImode))
+      {
+        int256_integer_type_node = make_signed_type (256);
+        int256_unsigned_type_node = make_unsigned_type (256);
+      }
+    /* 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))
@@ -9337,12 +9349,14 @@  build_common_tree_nodes (bool signed_char, bool short_double)
   intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
   intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 0);
   intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 0);
+  intOI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (OImode), 0);
 
   unsigned_intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 1);
   unsigned_intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 1);
   unsigned_intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 1);
   unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
   unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
+  unsigned_intOI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (OImode), 1);
 
   access_public_node = get_identifier ("public");
   access_protected_node = get_identifier ("protected");
diff --git a/gcc/tree.h b/gcc/tree.h
index be04465..6161810 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3725,12 +3725,14 @@  enum tree_index
   TI_INTSI_TYPE,
   TI_INTDI_TYPE,
   TI_INTTI_TYPE,
+  TI_INTOI_TYPE,
 
   TI_UINTQI_TYPE,
   TI_UINTHI_TYPE,
   TI_UINTSI_TYPE,
   TI_UINTDI_TYPE,
   TI_UINTTI_TYPE,
+  TI_UINTOI_TYPE,
 
   TI_UINT16_TYPE,
   TI_UINT32_TYPE,
@@ -3881,12 +3883,14 @@  extern GTY(()) tree global_trees[TI_MAX];
 #define intSI_type_node			global_trees[TI_INTSI_TYPE]
 #define intDI_type_node			global_trees[TI_INTDI_TYPE]
 #define intTI_type_node			global_trees[TI_INTTI_TYPE]
+#define intOI_type_node			global_trees[TI_INTOI_TYPE]
 
 #define unsigned_intQI_type_node	global_trees[TI_UINTQI_TYPE]
 #define unsigned_intHI_type_node	global_trees[TI_UINTHI_TYPE]
 #define unsigned_intSI_type_node	global_trees[TI_UINTSI_TYPE]
 #define unsigned_intDI_type_node	global_trees[TI_UINTDI_TYPE]
 #define unsigned_intTI_type_node	global_trees[TI_UINTTI_TYPE]
+#define unsigned_intOI_type_node	global_trees[TI_UINTOI_TYPE]
 
 #define uint16_type_node		global_trees[TI_UINT16_TYPE]
 #define uint32_type_node		global_trees[TI_UINT32_TYPE]
@@ -4070,6 +4074,8 @@  enum integer_type_kind
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
+  itk_int256,
+  itk_unsigned_int256,
   itk_int128,
   itk_unsigned_int128,
   itk_none
@@ -4092,6 +4098,8 @@  extern GTY(()) tree integer_types[itk_none];
 #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 int256_integer_type_node	integer_types[itk_int256]
+#define int256_unsigned_type_node	integer_types[itk_unsigned_int256]
 #define int128_integer_type_node	integer_types[itk_int128]
 #define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 27cc323..9b7d9e9 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -2059,14 +2059,15 @@  cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
   /* h */ { NL ("unsigned char"), NL ("unsigned char"),	D_PRINT_DEFAULT },
   /* i */ { NL ("int"),		NL ("int"),		D_PRINT_INT },
   /* j */ { NL ("unsigned int"), NL ("unsigned"),	D_PRINT_UNSIGNED },
-  /* k */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
+  /* k */ { NL ("unsigned __int256"), NL ("unsigned __int256"),
+	    D_PRINT_DEFAULT },
   /* l */ { NL ("long"),	NL ("long"),		D_PRINT_LONG },
   /* m */ { NL ("unsigned long"), NL ("unsigned long"),	D_PRINT_UNSIGNED_LONG },
   /* n */ { NL ("__int128"),	NL ("__int128"),	D_PRINT_DEFAULT },
   /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"),
 	    D_PRINT_DEFAULT },
   /* p */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
-  /* q */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
+  /* q */ { NL ("__int256"),	NL ("__int256"),	D_PRINT_DEFAULT },
   /* r */ { NULL, 0,		NULL, 0,		D_PRINT_DEFAULT },
   /* s */ { NL ("short"),	NL ("short"),		D_PRINT_DEFAULT },
   /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT },
@@ -2132,6 +2133,8 @@  cplus_demangle_type (struct d_info *di)
     case 'h': case 'i': case 'j':           case 'l': case 'm': case 'n':
     case 'o':                               case 's': case 't':
     case 'v': case 'w': case 'x': case 'y': case 'z':
+    case 'k': /* unsigned __int256 */
+    case 'q': /* __int256 */
       ret = d_make_builtin_type (di,
 				 &cplus_demangle_builtin_types[peek - 'a']);
       di->expansion += ret->u.s_builtin.type->len;
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-oimode.c.orig	2012-07-13 18:37:07.942507231 -0400
+++ a/gcc/testsuite/gcc.dg/torture/fp-int-convert-oimode.c	2012-07-13 18:39:40.934135061 -0400
@@ -0,0 +1,23 @@ 
+/* Test floating-point conversions.  OImode types.  */
+/* { dg-do run  { target noneyet-*-* } } */
+/* { dg-options "" } */
+
+#include <float.h>
+#include "fp-int-convert.h"
+
+typedef __int256 OItype;
+typedef unsigned __int256 UOItype;
+
+int
+main (void)
+{
+  TEST_I_F(OItype, UOItype, float, FLT_MANT_DIG);
+  TEST_I_F(OItype, UOItype, double, DBL_MANT_DIG);
+  /* Disable the long double tests when using IBM Extended Doubles.
+     They have variable precision, but constants calculated by gcc's
+     real.c assume fixed precision.  */
+#if DBL_MANT_DIG != LDBL_MANT_DIG  && LDBL_MANT_DIG != 106
+  TEST_I_F(OItype, UOItype, long double, LDBL_MANT_DIG);
+#endif
+  exit (0);
+}