From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id D3C583858D35 for ; Fri, 16 Jun 2023 17:06:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D3C583858D35 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id C9B4C21DCE; Fri, 16 Jun 2023 17:06:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1686935197; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FuG5FDrqq2V1lzekSqUUO6vVLYyVZ2tnTqDn8ge52jg=; b=EEIMUiB80YqN/hKkHojU+YTyKxtzr6njmRLWU0k9qRl5B96kxxWcZxGQvyl9Mxlb+cPPMP vsJfRIKF8AyV65wyaPYh3tlLnGBNjXPkFRZod3mHEPqekY6Wq9OC8GCOM0Zf/6ZCoeHZZ0 SUQ5mRfx5DG/inSxILr/Nwv3e7UGYxU= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1686935197; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FuG5FDrqq2V1lzekSqUUO6vVLYyVZ2tnTqDn8ge52jg=; b=+ztpKvZ0Tko2Jjn/88rjaybvRppzz0BCQuokKVKiCSQnKgbQx+i8kUe09CksqMwBX0r6ch cY8JOW0u5I5NirBg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id B84F01330B; Fri, 16 Jun 2023 17:06:37 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 6Yj7LJ2WjGROKQAAMHmgww (envelope-from ); Fri, 16 Jun 2023 17:06:37 +0000 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable From: Richard Biener Mime-Version: 1.0 (1.0) Subject: Re: [PATCH] builtins: Add support for clang compatible __builtin_{add,sub}c{,l,ll} [PR79173] Date: Fri, 16 Jun 2023 19:06:27 +0200 Message-Id: References: Cc: gcc-patches@gcc.gnu.org In-Reply-To: To: Jakub Jelinek X-Mailer: iPhone Mail (20F66) X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: > Am 16.06.2023 um 16:34 schrieb Jakub Jelinek : >=20 > =EF=BB=BFHi! >=20 > While the design of these builtins in clang is questionable, > rather than being say > unsigned __builtin_addc (unsigned, unsigned, bool, bool *) > so that it is clear they add two [0, 0xffffffff] range numbers > plus one [0, 1] range carry in and give [0, 0xffffffff] range > return plus [0, 1] range carry out, they actually instead > add 3 [0, 0xffffffff] values together but the carry out > isn't then the expected [0, 2] value because > 0xffffffffULL + 0xffffffff + 0xffffffff is 0x2fffffffd, > but just [0, 1] whether there was any overflow at all. >=20 > It is something used in the wild and shorter to write than the > corresponding > #define __builtin_addc(a,b,carry_in,carry_out) \ > ({ unsigned _s; \ > unsigned _c1 =3D __builtin_uadd_overflow (a, b, &_s); \ > unsigned _c2 =3D __builtin_uadd_overflow (_s, carry_in, &_s); \ > *(carry_out) =3D (_c1 | _c2); \ > _s; }) > and so a canned builtin for something people could often use. > It isn't that hard to maintain on the GCC side, as we just lower > it to two .ADD_OVERFLOW calls early, and the already committed > pottern recognization code can then make .UADDC/.USUBC calls out of > that if the carry in is in [0, 1] range and the corresponding > optab is supported by the target. >=20 > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Ok Richard=20 > 2023-06-16 Jakub Jelinek >=20 > PR middle-end/79173 > * builtin-types.def (BT_FN_UINT_UINT_UINT_UINT_UINTPTR, > BT_FN_ULONG_ULONG_ULONG_ULONG_ULONGPTR, > BT_FN_ULONGLONG_ULONGLONG_ULONGLONG_ULONGLONG_ULONGLONGPTR): New > types. > * builtins.def (BUILT_IN_ADDC, BUILT_IN_ADDCL, BUILT_IN_ADDCLL, > BUILT_IN_SUBC, BUILT_IN_SUBCL, BUILT_IN_SUBCLL): New builtins. > * builtins.cc (fold_builtin_addc_subc): New function. > (fold_builtin_varargs): Handle BUILT_IN_{ADD,SUB}C{,L,LL}. > * doc/extend.texi (__builtin_addc, __builtin_subc): Document. >=20 > * gcc.target/i386/pr79173-11.c: New test. > * gcc.dg/builtin-addc-1.c: New test. >=20 > --- gcc/builtin-types.def.jj 2023-06-16 12:01:09.622759288 +0200 > +++ gcc/builtin-types.def 2023-06-16 12:04:20.277086893 +0200 > @@ -842,10 +842,17 @@ DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_S > BT_PTR, BT_PTR, BT_INT, BT_SIZE, BT_SIZE) > DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINT, > BT_UINT, BT_UINT, BT_UINT, BT_UINT, BT_UINT) > +DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINTPTR, > + BT_UINT, BT_UINT, BT_UINT, BT_UINT, BT_PTR_UINT) > DEF_FUNCTION_TYPE_4 (BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT, > BT_UINT, BT_FLOAT, BT_FLOAT, BT_FLOAT, BT_FLOAT) > DEF_FUNCTION_TYPE_4 (BT_FN_ULONG_ULONG_ULONG_UINT_UINT, > BT_ULONG, BT_ULONG, BT_ULONG, BT_UINT, BT_UINT) > +DEF_FUNCTION_TYPE_4 (BT_FN_ULONG_ULONG_ULONG_ULONG_ULONGPTR, > + BT_ULONG, BT_ULONG, BT_ULONG, BT_ULONG, BT_PTR_ULONG) > +DEF_FUNCTION_TYPE_4 (BT_FN_ULONGLONG_ULONGLONG_ULONGLONG_ULONGLONG_ULONGL= ONGPTR, > + BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG, > + BT_PTR_ULONGLONG) > DEF_FUNCTION_TYPE_4 (BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, > BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE, BT_SIZE) > DEF_FUNCTION_TYPE_4 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG, > --- gcc/builtins.def.jj 2023-06-16 12:01:09.622759288 +0200 > +++ gcc/builtins.def 2023-06-16 12:04:20.278086879 +0200 > @@ -934,6 +934,12 @@ DEF_GCC_BUILTIN (BUILT_IN_USUBLL_ > DEF_GCC_BUILTIN (BUILT_IN_UMUL_OVERFLOW, "umul_overflow", BT_FN_BOO= L_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_UMULL_OVERFLOW, "umull_overflow", BT_FN_B= OOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_UMULLL_OVERFLOW, "umulll_overflow", BT_FN= _BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_ADDC, "addc", BT_FN_UINT_UINT_UINT_UINT_= UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_ADDCL, "addcl", BT_FN_ULONG_ULONG_ULONG_= ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_ADDCLL, "addcll", BT_FN_ULONGLONG_ULONGL= ONG_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_SUBC, "subc", BT_FN_UINT_UINT_UINT_UINT_= UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_SUBCL, "subcl", BT_FN_ULONG_ULONG_ULONG_= ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_SUBCLL, "subcll", BT_FN_ULONGLONG_ULONGL= ONG_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST) >=20 > /* Category: miscellaneous builtins. */ > DEF_LIB_BUILTIN (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_TMPURE_N= ORETURN_NOTHROW_LEAF_COLD_LIST) > --- gcc/builtins.cc.jj 2023-06-13 18:23:37.141794072 +0200 > +++ gcc/builtins.cc 2023-06-16 13:11:25.094406298 +0200 > @@ -9555,6 +9555,51 @@ fold_builtin_arith_overflow (location_t > return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres)= ; > } >=20 > +/* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions > + that return both result of arithmetics and overflowed boolean > + flag in a complex integer result. */ > + > +static tree > +fold_builtin_addc_subc (location_t loc, enum built_in_function fcode, > + tree *args) > +{ > + enum internal_fn ifn; > + > + switch (fcode) > + { > + case BUILT_IN_ADDC: > + case BUILT_IN_ADDCL: > + case BUILT_IN_ADDCLL: > + ifn =3D IFN_ADD_OVERFLOW; > + break; > + case BUILT_IN_SUBC: > + case BUILT_IN_SUBCL: > + case BUILT_IN_SUBCLL: > + ifn =3D IFN_SUB_OVERFLOW; > + break; > + default: > + gcc_unreachable (); > + } > + > + tree type =3D TREE_TYPE (args[0]); > + tree ctype =3D build_complex_type (type); > + tree call =3D build_call_expr_internal_loc (loc, ifn, ctype, 2, > + args[0], args[1]); > + tree tgt =3D save_expr (call); > + tree intres =3D build1_loc (loc, REALPART_EXPR, type, tgt); > + tree ovfres =3D build1_loc (loc, IMAGPART_EXPR, type, tgt); > + call =3D build_call_expr_internal_loc (loc, ifn, ctype, 2, > + intres, args[2]); > + tgt =3D save_expr (call); > + intres =3D build1_loc (loc, REALPART_EXPR, type, tgt); > + tree ovfres2 =3D build1_loc (loc, IMAGPART_EXPR, type, tgt); > + ovfres =3D build2_loc (loc, BIT_IOR_EXPR, type, ovfres, ovfres2); > + tree mem_arg3 =3D build_fold_indirect_ref_loc (loc, args[3]); > + tree store > + =3D fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg3, ovfr= es); > + return build2_loc (loc, COMPOUND_EXPR, type, store, intres); > +} > + > /* Fold a call to __builtin_FILE to a constant string. */ >=20 > static inline tree > @@ -10843,6 +10888,14 @@ fold_builtin_varargs (location_t loc, tr > ret =3D fold_builtin_fpclassify (loc, args, nargs); > break; >=20 > + case BUILT_IN_ADDC: > + case BUILT_IN_ADDCL: > + case BUILT_IN_ADDCLL: > + case BUILT_IN_SUBC: > + case BUILT_IN_SUBCL: > + case BUILT_IN_SUBCLL: > + return fold_builtin_addc_subc (loc, fcode, args); > + > default: > break; > } > --- gcc/doc/extend.texi.jj 2023-06-16 12:01:15.015683954 +0200 > +++ gcc/doc/extend.texi 2023-06-16 12:40:10.179841300 +0200 > @@ -12839,6 +12839,50 @@ after addition, conditional jump on carr >=20 > @enddefbuiltin >=20 > +@defbuiltin{unsigned int __builtin_addc (unsigned int a, unsigned int b, u= nsigned int carry_in, unsigned int *carry_out)} > +@defbuiltinx{unsigned long int __builtin_addcl (unsigned long int a, unsi= gned long int b, unsigned int carry_in, unsigned long int *carry_out)} > +@defbuiltinx{unsigned long long int __builtin_addcll (unsigned long long i= nt a, unsigned long long int b, unsigned long long int carry_in, unsigned lo= ng long int *carry_out)} > + > +These built-in functions are equivalent to: > +@smallexample > + (@{ __typeof__ (@var{a}) s; \ > + __typeof__ (@var{a}) c1 =3D __builtin_add_overflow (@var{a}, @var{b= }, &s); \ > + __typeof__ (@var{a}) c2 =3D __builtin_add_overflow (s, @var{carry_i= n}, &s); \ > + *(@var{carry_out}) =3D c1 | c2; \ > + s; @}) > +@end smallexample > + > +i.e.@: they add 3 unsigned values, set what the last argument > +points to to 1 if any of the two additions overflowed (otherwise 0) > +and return the sum of those 3 unsigned values. Note, while all > +the first 3 arguments can have arbitrary values, better code will be > +emitted if one of them (preferrably the third one) has only values > +0 or 1 (i.e.@: carry-in). > + > +@enddefbuiltin > + > +@defbuiltin{unsigned int __builtin_subc (unsigned int a, unsigned int b, u= nsigned int carry_in, unsigned int *carry_out)} > +@defbuiltinx{unsigned long int __builtin_subcl (unsigned long int a, unsi= gned long int b, unsigned int carry_in, unsigned long int *carry_out)} > +@defbuiltinx{unsigned long long int __builtin_subcll (unsigned long long i= nt a, unsigned long long int b, unsigned long long int carry_in, unsigned lo= ng long int *carry_out)} > + > +These built-in functions are equivalent to: > +@smallexample > + (@{ __typeof__ (@var{a}) s; \ > + __typeof__ (@var{a}) c1 =3D __builtin_sub_overflow (@var{a}, @var{b= }, &s); \ > + __typeof__ (@var{a}) c2 =3D __builtin_sub_overflow (s, @var{carry_i= n}, &s); \ > + *(@var{carry_out}) =3D c1 | c2; \ > + s; @}) > +@end smallexample > + > +i.e.@: they subtract 2 unsigned values from the first unsigned value, > +set what the last argument points to to 1 if any of the two subtractions > +overflowed (otherwise 0) and return the result of the subtractions. > +Note, while all the first 3 arguments can have arbitrary values, better c= ode > +will be emitted if one of them (preferrably the third one) has only value= s > +0 or 1 (i.e.@: carry-in). > + > +@enddefbuiltin > + > @node x86 specific memory model extensions for transactional memory > @section x86-Specific Memory Model Extensions for Transactional Memory >=20 > --- gcc/testsuite/gcc.target/i386/pr79173-11.c.jj 2023-06-16 12:46:12.6= 59735680 +0200 > +++ gcc/testsuite/gcc.target/i386/pr79173-11.c 2023-06-16 12:46:41.8643= 23951 +0200 > @@ -0,0 +1,39 @@ > +/* PR middle-end/79173 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fno-stack-protector -masm=3Datt" } */ > +/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 {= target lp64 } } } */ > +/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 {= target lp64 } } } */ > +/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1= { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\= \\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*= \\\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*= \\\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]= *\\\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\= \\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*= \\\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*= \\\)" 1 { target ia32 } } } */ > +/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]= *\\\)" 1 { target ia32 } } } */ > + > +void > +foo (unsigned long *p, unsigned long *q) > +{ > + unsigned long c; > + p[0] =3D __builtin_addcl (p[0], q[0], 0, &c); > + p[1] =3D __builtin_addcl (p[1], q[1], c, &c); > + p[2] =3D __builtin_addcl (p[2], q[2], c, &c); > + p[3] =3D __builtin_addcl (p[3], q[3], c, &c); > +} > + > +void > +bar (unsigned long *p, unsigned long *q) > +{ > + unsigned long c; > + p[0] =3D __builtin_subcl (p[0], q[0], 0, &c); > + p[1] =3D __builtin_subcl (p[1], q[1], c, &c); > + p[2] =3D __builtin_subcl (p[2], q[2], c, &c); > + p[3] =3D __builtin_subcl (p[3], q[3], c, &c); > +} > --- gcc/testsuite/gcc.dg/builtin-addc-1.c.jj 2023-06-16 12:47:57.247261= 195 +0200 > +++ gcc/testsuite/gcc.dg/builtin-addc-1.c 2023-06-16 13:03:19.269260147= +0200 > @@ -0,0 +1,101 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -g" } */ > + > +int > +main () > +{ > + unsigned int c; > + unsigned long cl; > + unsigned long long cll; > + if (__builtin_addc (1, 42, 0, &c) !=3D 43 || c !=3D 0) > + __builtin_abort (); > + if (__builtin_addc (1, 42, 15, &c) !=3D 58 || c !=3D 0) > + __builtin_abort (); > + if (__builtin_addc (-2U, -3U, -4U, &c) !=3D -9U || c !=3D 1) > + __builtin_abort (); > + if (__builtin_addc (-2U, 1, 0, &c) !=3D -1U || c !=3D 0) > + __builtin_abort (); > + if (__builtin_addc (-2U, 1, 1, &c) !=3D 0 || c !=3D 1) > + __builtin_abort (); > + if (__builtin_addc (-2U, 2, 0, &c) !=3D 0 || c !=3D 1) > + __builtin_abort (); > + if (__builtin_addc (-2U, 0, 2, &c) !=3D 0 || c !=3D 1) > + __builtin_abort (); > + if (__builtin_addcl (1L, 42L, 0L, &cl) !=3D 43 || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_addcl (1L, 42L, 15L, &cl) !=3D 58 || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_addcl (-2UL, -3UL, -4UL, &cl) !=3D -9UL || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_addcl (-2UL, 1L, 0L, &cl) !=3D -1UL || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_addcl (-2UL, 1L, 1L, &cl) !=3D 0 || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_addcl (-2UL, 2L, 0L, &cl) !=3D 0 || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_addcl (-2UL, 0L, 2L, &cl) !=3D 0 || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_addcll (1LL, 42LL, 0LL, &cll) !=3D 43 || cll !=3D 0LL) > + __builtin_abort (); > + if (__builtin_addcll (1LL, 42LL, 15LL, &cll) !=3D 58 || cll !=3D 0LL) > + __builtin_abort (); > + if (__builtin_addcll (-2ULL, -3ULL, -4ULL, &cll) !=3D -9ULL || cll !=3D= 1LL) > + __builtin_abort (); > + if (__builtin_addcll (-2ULL, 1LL, 0LL, &cll) !=3D -1ULL || cll !=3D 0LL= ) > + __builtin_abort (); > + if (__builtin_addcll (-2ULL, 1LL, 1LL, &cll) !=3D 0 || cll !=3D 1LL) > + __builtin_abort (); > + if (__builtin_addcll (-2ULL, 2LL, 0LL, &cll) !=3D 0 || cll !=3D 1LL) > + __builtin_abort (); > + if (__builtin_addcll (-2ULL, 0LL, 2LL, &cll) !=3D 0 || cll !=3D 1LL) > + __builtin_abort (); > + if (__builtin_subc (42, 42, 0, &c) !=3D 0 || c !=3D 0) > + __builtin_abort (); > + if (__builtin_subc (42, 42, 1, &c) !=3D -1U || c !=3D 1) > + __builtin_abort (); > + if (__builtin_subc (1, -3U, -4U, &c) !=3D 8 || c !=3D 1) > + __builtin_abort (); > + if (__builtin_subc (-2U, 1, 0, &c) !=3D -3U || c !=3D 0) > + __builtin_abort (); > + if (__builtin_subc (-2U, -1U, 0, &c) !=3D -1U || c !=3D 1) > + __builtin_abort (); > + if (__builtin_subc (-2U, -2U, 0, &c) !=3D 0 || c !=3D 0) > + __builtin_abort (); > + if (__builtin_subc (-2U, -2U, 1, &c) !=3D -1U || c !=3D 1) > + __builtin_abort (); > + if (__builtin_subc (-2U, 1, -2U, &c) !=3D -1U || c !=3D 1) > + __builtin_abort (); > + if (__builtin_subcl (42L, 42L, 0L, &cl) !=3D 0L || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_subcl (42L, 42L, 1L, &cl) !=3D -1UL || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_subcl (1L, -3UL, -4UL, &cl) !=3D 8L || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_subcl (-2UL, 1L, 0L, &cl) !=3D -3UL || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_subcl (-2UL, -1UL, 0L, &cl) !=3D -1UL || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_subcl (-2UL, -2UL, 0L, &cl) !=3D 0L || cl !=3D 0L) > + __builtin_abort (); > + if (__builtin_subcl (-2UL, -2UL, 1L, &cl) !=3D -1UL || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_subcl (-2UL, 1L, -2UL, &cl) !=3D -1UL || cl !=3D 1L) > + __builtin_abort (); > + if (__builtin_subcll (42LL, 42LL, 0LL, &cll) !=3D 0LL || cll !=3D 0LL) > + __builtin_abort (); > + if (__builtin_subcll (42LL, 42LL, 1LL, &cll) !=3D -1ULL || cll !=3D 1LL= ) > + __builtin_abort (); > + if (__builtin_subcll (1LL, -3ULL, -4ULL, &cll) !=3D 8LL || cll !=3D 1LL= ) > + __builtin_abort (); > + if (__builtin_subcll (-2ULL, 1LL, 0LL, &cll) !=3D -3ULL || cll !=3D 0LL= ) > + __builtin_abort (); > + if (__builtin_subcll (-2ULL, -1ULL, 0LL, &cll) !=3D -1ULL || cll !=3D 1= LL) > + __builtin_abort (); > + if (__builtin_subcll (-2ULL, -2ULL, 0LL, &cll) !=3D 0LL || cll !=3D 0LL= ) > + __builtin_abort (); > + if (__builtin_subcll (-2ULL, -2ULL, 1LL, &cll) !=3D -1ULL || cll !=3D 1= LL) > + __builtin_abort (); > + if (__builtin_subcll (-2ULL, 1LL, -2ULL, &cll) !=3D -1ULL || cll !=3D 1= LL) > + __builtin_abort (); > + return 0; > +} >=20 > Jakub >=20