Patchwork __int256

login
register
mail settings
Submitter Mike Stump
Date July 13, 2012, 1:59 a.m.
Message ID <F6BB9A78-51C3-43BF-8A2C-13D1E5415760@comcast.net>
Download mbox | patch
Permalink /patch/170766/
State New
Headers show

Comments

Mike Stump - July 13, 2012, 1:59 a.m.
This patch adds __int256 to the front-ends.  We follow the __int128 code fairly closely...

So, an outstanding question would be, how do I get the mangle codes allocated for the type?  I just choose two unused codes, for now.  All in all, the patch was pretty straight forward.

We have another patch underway to do N-bit constant ints, where N is defined by the port.  This patch is in the process of being reviewed now, and Kenny should be able to submit it shortly.

I tried hard to find all the __int128 bits, but, if there are any I missed, love to have a pointer to them.

So, I think we have to resolve which mangle codes to use in some before this goes in, aside from that, Ok?
Richard Guenther - July 13, 2012, 7:33 a.m.
On Fri, Jul 13, 2012 at 3:59 AM, Mike Stump <mikestump@comcast.net> wrote:
> This patch adds __int256 to the front-ends.  We follow the __int128 code fairly closely...
>
> So, an outstanding question would be, how do I get the mangle codes allocated for the type?  I just choose two unused codes, for now.  All in all, the patch was pretty straight forward.
>
> We have another patch underway to do N-bit constant ints, where N is defined by the port.  This patch is in the process of being reviewed now, and Kenny should be able to submit it shortly.
>
> I tried hard to find all the __int128 bits, but, if there are any I missed, love to have a pointer to them.
>
> So, I think we have to resolve which mangle codes to use in some before this goes in, aside from that, Ok?

How do you handle the fact that we cannot represent all constants of __int256
or larger with an INTEGER_CST?  I think this introduces latent wrong-code
bugs almost everywhere in the compiler.

Richard.

>
>
Mike Stump - July 13, 2012, 8:34 a.m.
On Jul 13, 2012, at 12:33 AM, Richard Guenther wrote:
> On Fri, Jul 13, 2012 at 3:59 AM, Mike Stump <mikestump@comcast.net> wrote:
>> This patch adds __int256 to the front-ends.

>> We have another patch underway to do N-bit constant ints, where N is defined by the port.  This patch is in the process of being reviewed now, and Kenny should be able to submit it shortly.
> 
> How do you handle the fact that we cannot represent all constants of __int256
> or larger with an INTEGER_CST?  I think this introduces latent wrong-code
> bugs almost everywhere in the compiler.

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 have put the patch through the C test suite, and it doesn't show any failures.

Do you have any examples of bugs that are _introduced_ by my patch?  I'd be happy to fix any that arise.
Richard Guenther - July 13, 2012, 8:57 a.m.
On Fri, Jul 13, 2012 at 10:34 AM, Mike Stump <mikestump@comcast.net> wrote:
> On Jul 13, 2012, at 12:33 AM, Richard Guenther wrote:
>> On Fri, Jul 13, 2012 at 3:59 AM, Mike Stump <mikestump@comcast.net> wrote:
>>> This patch adds __int256 to the front-ends.
>
>>> We have another patch underway to do N-bit constant ints, where N is defined by the port.  This patch is in the process of being reviewed now, and Kenny should be able to submit it shortly.
>>
>> How do you handle the fact that we cannot represent all constants of __int256
>> or larger with an INTEGER_CST?  I think this introduces latent wrong-code
>> bugs almost everywhere in the compiler.
>
> 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 have put the patch through the C test suite, and it doesn't show any failures.
>
> Do you have any examples of bugs that are _introduced_ by my patch?  I'd be happy to fix any that arise.

No.  Just you expose the users to those bugs by exposing __int256 ;)  Docs
should have a pretty big fat warning on it.

Richard.
Joseph S. Myers - July 13, 2012, 1:39 p.m.
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, and the libgcc support, before we consider the support for the type 
from the front ends using keywords as opposed to mode attributes.

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.  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.  
See my comments (several messages on 1 July 2011) about 40-bit integer 
support; 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.

__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.

> 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.
Georg-Johann Lay - July 13, 2012, 4:20 p.m.
Mike Stump wrote:
> This patch adds __int256 to the front-ends.  We follow the __int128 code
> fairly closely...
> 
> So, an outstanding question would be, how do I get the mangle codes
> allocated for the type?  I just choose two unused codes, for now.  All in
> all, the patch was pretty straight forward.
> 
> We have another patch underway to do N-bit constant ints, where N is defined
> by the port.  This patch is in the process of being reviewed now, and Kenny
> should be able to submit it shortly.

The avr port defines __int24 and __uint24.
Is that compatible with a generic __int24?

Johann

> I tried hard to find all the __int128 bits, but, if there are any I missed,
> love to have a pointer to them.
> 
> So, I think we have to resolve which mangle codes to use in some before this
> goes in, aside from that, Ok?
Mike Stump - July 13, 2012, 5:36 p.m.
On Jul 13, 2012, at 1:57 AM, Richard Guenther wrote:
>> I have put the patch through the C test suite, and it doesn't show any failures.
>> 
>> Do you have any examples of bugs that are _introduced_ by my patch?  I'd be happy to fix any that arise.
> 
> No.  Just you expose the users to those bugs by exposing __int256 ;)  Docs
> should have a pretty big fat warning on it.

Ah, ok, thanks.  Now, the problem, OImode I believe is _already_ exposed to the user:

int __attribute__((mode(SI))) a;
int __attribute__((mode(OI))) b;

This just changes the exposure slightly to be higher visibility and a prettier interface in my opinion.  Also, notice, that exposure I believe is limited to ports that do this:

my_scalar_mode_supported_p (enum machine_mode mode)
{
  switch (mode)
    {
    case OImode:
      return true;
    default:
      return default_scalar_mode_supported_p (mode);
    }
}

_exclusively_.  As, in my code, it does this:

+    if (targetm.scalar_mode_supported_p (OImode))
+      {
+        int256_integer_type_node = make_signed_type (256);
+        int256_unsigned_type_node = make_unsigned_type (256);
+      }


and this:

+           case RID_INT256:
+             if (int256_integer_type_node == NULL_TREE)
+               {
+                 error_at (loc, "%<__int256%> is not supported for this target");
+                 return specs;
+               }

and this:

+  if (explicit_int256)
+    {
+      if (int256_integer_type_node == NULL_TREE)
+       {
+         error ("%<__int256%> is not supported by this target");
+         explicit_int256 = false;
+       }

so, I'm having a really hard time with the notion that this actually creates any new problems for anyone, even those that support OImode already.  I just checked all in tree gcc targets, and none claim OImode support.  Do you have any example of a testcase that shows a regression?  Any that shows a regression on any in tree port?  I can easily test, as I have compilers that don't have any OI support, compilers that have OI support, and compilers that have __int256 support.

As for documenting bugs, generally we don't do that.  Our intention is to actually spend time to fix all bugs, so, documenting them I don't feel is necessary.
Nathan Froyd - July 13, 2012, 6:21 p.m.
On Fri, Jul 13, 2012 at 10:36:35AM -0700, Mike Stump wrote:
> I just checked all in tree gcc targets, and none claim OImode support.

./s390/s390-modes.def:23:INT_MODE (OI, 32);
./spu/spu-modes.def:29:INT_MODE (OI, 32);
./ia64/ia64-modes.def:68:INT_MODE (OI, 32);
./i386/i386-modes.def:88:INT_MODE (OI, 32);
./arm/arm-modes.def:82:INT_MODE (OI, 32);

At least for ARM, OImode gets used for Neon intrinsics.  Can't speak for
the other ports, though.

-Nathan
Steven Bosscher - July 13, 2012, 6:28 p.m.
On Fri, Jul 13, 2012 at 8:21 PM, Nathan Froyd <froydnj@mozilla.com> wrote:
> On Fri, Jul 13, 2012 at 10:36:35AM -0700, Mike Stump wrote:
>> I just checked all in tree gcc targets, and none claim OImode support.
>
> ./s390/s390-modes.def:23:INT_MODE (OI, 32);
> ./spu/spu-modes.def:29:INT_MODE (OI, 32);
> ./ia64/ia64-modes.def:68:INT_MODE (OI, 32);
> ./i386/i386-modes.def:88:INT_MODE (OI, 32);
> ./arm/arm-modes.def:82:INT_MODE (OI, 32);
>
> At least for ARM, OImode gets used for Neon intrinsics.  Can't speak for
> the other ports, though.

On x86_64-unknown-linux-gnu:

$ cat t.c
int __attribute__((__mode__(DI))) di;
int __attribute__((__mode__(TI))) ti;
int __attribute__((__mode__(OI))) oi;

$ ./xgcc -B. t.c
t.c:3:1: error: unable to emulate ‘OI’
 int __attribute__((__mode__(OI))) oi;
 ^

This is trunk r189365.

Ciao!
Steven
Joseph S. Myers - July 13, 2012, 8:24 p.m.
On Fri, 13 Jul 2012, Georg-Johann Lay wrote:

> The avr port defines __int24 and __uint24.
> Is that compatible with a generic __int24?

In my view, given suitable generic support ports like that should move to 
__intN keywords (usable with "unsigned", so "unsigned __intN" would be the 
unsigned version of that type) and other type names such as __uint24 or 
__uint128_t should be considered deprecated backwards-compatibility 
typedefs (or if necessary macros) provided by the back ends.

It would be good to have a reasonably thorough generic set of testcases 
for the various special-width integer types, used on whichever targets 
support those widths.  If you have a 24-bit type now it might be good to 
extend the floating-point / integer conversion tests I mentioned to cover 
it....
Mike Stump - July 13, 2012, 11:01 p.m.
On Jul 13, 2012, at 9:20 AM, Georg-Johann Lay wrote:
>> We have another patch underway to do N-bit constant ints, where N is defined
>> by the port.  This patch is in the process of being reviewed now, and Kenny
>> should be able to submit it shortly.
> 
> The avr port defines __int24 and __uint24.
> Is that compatible with a generic __int24?

A 24-bit int is smaller than a HOST_WIDE_INT (right!), so the everything related to 24-bit constants is handled by existing CONST_INT code.  Our patch doesn't change 24-bit constants.

I've never seen a generic __int24, so I don't know what you mean, and I don't know what you mean by compatible.  In the language standard, compatible is a very specific term, and it relates to the front-end code.  I'm not altering or changing any front end semantics for any type, other than __int256, so the answer post my patch, is the same answer as previous to my patch.

I hope that might answer your question, if not, expound on the question a little and I can try again.
Mike Stump - July 13, 2012, 11:17 p.m.
On Jul 13, 2012, at 11:21 AM, Nathan Froyd wrote:
> On Fri, Jul 13, 2012 at 10:36:35AM -0700, Mike Stump wrote:
>> I just checked all in tree gcc targets, and none claim OImode support.
> 
> ./s390/s390-modes.def:23:INT_MODE (OI, 32);
> ./spu/spu-modes.def:29:INT_MODE (OI, 32);
> ./ia64/ia64-modes.def:68:INT_MODE (OI, 32);
> ./i386/i386-modes.def:88:INT_MODE (OI, 32);
> ./arm/arm-modes.def:82:INT_MODE (OI, 32);

Now, go back and check the target to see if they return true for:

@deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
Define this to return nonzero if the port is prepared to handle
insns involving scalar mode @var{mode}.  For a scalar mode to be
considered supported, all the basic arithmetic and comparisons
must work.

The default version of this hook returns true for any mode
required to handle the basic C types (as defined by the port).
Included here are the double-word arithmetic supported by the
code in @file{optabs.c}.
@end deftypefn

I'll wait.  You'll notice that my patch uses that answer to determine if support for __int256 is enabled.
Mike Stump - July 14, 2012, 3:21 a.m.
On Jul 13, 2012, at 11:28 AM, Steven Bosscher wrote:
> On Fri, Jul 13, 2012 at 8:21 PM, Nathan Froyd <froydnj@mozilla.com> wrote:
>> On Fri, Jul 13, 2012 at 10:36:35AM -0700, Mike Stump wrote:
>>> I just checked all in tree gcc targets, and none claim OImode support.
>> 
>> ./s390/s390-modes.def:23:INT_MODE (OI, 32);
>> ./spu/spu-modes.def:29:INT_MODE (OI, 32);
>> ./ia64/ia64-modes.def:68:INT_MODE (OI, 32);
>> ./i386/i386-modes.def:88:INT_MODE (OI, 32);
>> ./arm/arm-modes.def:82:INT_MODE (OI, 32);
>> 
>> At least for ARM, OImode gets used for Neon intrinsics.  Can't speak for
>> the other ports, though.
> 
> On x86_64-unknown-linux-gnu:
> 
> $ cat t.c
> int __attribute__((__mode__(DI))) di;
> int __attribute__((__mode__(TI))) ti;
> int __attribute__((__mode__(OI))) oi;
> 
> $ ./xgcc -B. t.c
> t.c:3:1: error: unable to emulate ‘OI’
> int __attribute__((__mode__(OI))) oi;
> ^
> 
> This is trunk r189365.

Yup, exactly as I expected.  The arm folks I suspect will discover the same.
Richard Earnshaw - July 14, 2012, 12:43 p.m.
On 14/07/12 04:21, Mike Stump wrote:
> On Jul 13, 2012, at 11:28 AM, Steven Bosscher wrote:
>> On Fri, Jul 13, 2012 at 8:21 PM, Nathan Froyd <froydnj@mozilla.com> wrote:
>>> On Fri, Jul 13, 2012 at 10:36:35AM -0700, Mike Stump wrote:
>>>> I just checked all in tree gcc targets, and none claim OImode support.
>>>
>>> ./s390/s390-modes.def:23:INT_MODE (OI, 32);
>>> ./spu/spu-modes.def:29:INT_MODE (OI, 32);
>>> ./ia64/ia64-modes.def:68:INT_MODE (OI, 32);
>>> ./i386/i386-modes.def:88:INT_MODE (OI, 32);
>>> ./arm/arm-modes.def:82:INT_MODE (OI, 32);
>>>
>>> At least for ARM, OImode gets used for Neon intrinsics.  Can't speak for
>>> the other ports, though.
>>
>> On x86_64-unknown-linux-gnu:
>>
>> $ cat t.c
>> int __attribute__((__mode__(DI))) di;
>> int __attribute__((__mode__(TI))) ti;
>> int __attribute__((__mode__(OI))) oi;
>>
>> $ ./xgcc -B. t.c
>> t.c:3:1: error: unable to emulate ‘OI’
>> int __attribute__((__mode__(OI))) oi;
>> ^
>>
>> This is trunk r189365.
> 
> Yup, exactly as I expected.  The arm folks I suspect will discover the same.
> 

OImode on ARM only exists to support vector copying operations and the
other guff that the compiler can't handle internally without it.

It is /not/ intended to be available as a type to the user, in
particular, it is not intended to be available for arithmetic.  The same
is also true of TI mode and any other xImode larger than DImode.

R.

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..0fcdf33 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",
@@ -4962,6 +5000,11 @@  c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  if (targetm.scalar_mode_supported_p (OImode))
+    lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+					   TYPE_DECL,
+					   get_identifier ("__int256_t"),
+					   intOI_type_node));
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
@@ -4981,6 +5024,11 @@  c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  if (targetm.scalar_mode_supported_p (OImode))
+    lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+					   TYPE_DECL,
+					   get_identifier ("__uint256_t"),
+					   unsigned_intOI_type_node));
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
@@ -10844,6 +10892,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/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/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;