From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from server.nextmovesoftware.com (server.nextmovesoftware.com [162.254.253.69]) by sourceware.org (Postfix) with ESMTPS id D14D73857C48 for ; Wed, 29 Sep 2021 15:25:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D14D73857C48 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=nextmovesoftware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nextmovesoftware.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nextmovesoftware.com; s=default; h=Content-Type:MIME-Version:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R/TR85c1g4uMm1Mj1A8X+9uR7tYlJsnMRZj9Iy/MnS8=; b=KCnxUSMFGnNLBhK+mhEMe5b6Ta xd5nPHk2e/Bd597KG3kYToABlawwV9W5L3Vs4Jq0s8UeEoDBlfuwNGKjig/dGkFuewsVXLqdjBPWU xSYdQmN1PZHLJspW3gGsOnyiciOx/LC1L6rdB7W8s4HXYWv3jQ4ptdUJUQ5FM1IrX481shq/gDSYK n6iWBSBQls7FISO/N4Qe0jT9OYTPTUVkvamXyR1I26Sl20CYWRvFAufZslDYh2MmAwb3TLqax2aDJ jly7qx3yTVmzsaiEUuKOgRUGzOgTYYDslU/iaZiPoyPP1fHw+Qe/u610EhBkZjqQSbF/o+qlzANE/ O9sqlmhA==; Received: from [185.62.158.67] (port=57108 helo=Dell) by server.nextmovesoftware.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1mVbSM-0007ro-4f; Wed, 29 Sep 2021 11:25:14 -0400 From: "Roger Sayle" To: "'Richard Sandiford'" Cc: "'GCC Patches'" Subject: [PATCH #2] Introduce smul_highpart and umul_highpart RTX for high-part multiplications Date: Wed, 29 Sep 2021 16:25:12 +0100 Message-ID: <022c01d7b546$33034730$9909d590$@nextmovesoftware.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_022D_01D7B54E.94CA2030" X-Mailer: Microsoft Outlook 16.0 Thread-Index: Ade1ROPJ5Daa9qHGQYmdQBrDt2ulWA== Content-Language: en-gb X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server.nextmovesoftware.com X-AntiAbuse: Original Domain - gcc.gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - nextmovesoftware.com X-Get-Message-Sender-Via: server.nextmovesoftware.com: authenticated_id: roger@nextmovesoftware.com X-Authenticated-Sender: server.nextmovesoftware.com: roger@nextmovesoftware.com X-Source: X-Source-Args: X-Source-Dir: X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Sep 2021 15:25:17 -0000 This is a multipart message in MIME format. ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Hi Richard, All excellent suggestions. The revised patch below implements all of your (and Andreas') recommendations. I'm happy to restrict GCC's = support for saturating arithmetic to integer types, even though I do know of one target (nvptx) that supports saturating floating point math, where = results are clamped to [0.0, 1.0], but I've not investigated how NaNs or signed zeros are handled. Good catch on my min/max typo. It convinced me to work harder to come up with some test cases for these simplifications, which I've managed to trigger on x86_64-pc-linux-gnu in the four new attached test cases. This patch has been tested on x86_64-pc-linux-gnu with "make bootstrap" and "make -k check" with no new failures. Ok for mainline? 2021-09-29 Roger Sayle Richard Sandiford gcc/ChangeLog * gcc/rtl.def (SMUL_HIGHPART, UMUL_HIGHPART): New RTX codes for representing signed and unsigned high-part multiplication resp. * gcc/simplify-rtx.c (simplify_binary_operation_1) [SMUL_HIGHPART, UMUL_HIGHPART]: Simplify high-part multiplications by zero. [SS_PLUS, US_PLUS, SS_MINUS, US_MINUS, SS_MULT, US_MULT, SS_DIV, US_DIV]: Similar simplifications for saturating arithmetic. (simplify_const_binary_operation) [SS_PLUS, US_PLUS, SS_MINUS, US_MINUS, SS_MULT, US_MULT, SMUL_HIGHPART, UMUL_HIGHPART]: Implement compile-time evaluation for constant operands. * gcc/dwarf2out.c (mem_loc_descriptor): Skip SMUL_HIGHPART and UMUL_HIGHPART. * doc/rtl.texi (smul_highpart, umul_highpart): Document RTX codes. * doc/md.texi (smul@var{m}3_highpart, umul@var{m3}_highpart): Mention the new smul_highpart and umul_highpart RTX codes. * doc/invoke.texi: Silence @xref "compilation" warnings. gcc/testsuite/ChangeLog * gcc.target/i386/sse2-mmx-paddsb-2.c: New test case. * gcc.target/i386/sse2-mmx-paddusb-2.c: New test case. * gcc.target/i386/sse2-mmx-subsb-2.c: New test case. * gcc.target/i386/sse2-mmx-subusb-2.c: New test case. Roger -- -----Original Message----- From: Richard Sandiford =20 Sent: 27 September 2021 16:44 To: Roger Sayle Cc: 'GCC Patches' Subject: Re: [PATCH] Introduce sh_mul and uh_mul RTX codes for high-part = multiplications "Roger Sayle" writes: > This patch introduces new RTX codes to allow the RTL passes and=20 > backends to consistently represent high-part multiplications. > Currently, the RTL used by different backends for expanding=20 > smul3_highpart and umul3_highpart varies greatly, with=20 > many but not all choosing to express this something like: > > (define_insn "smuldi3_highpart" > [(set (match_operand:DI 0 "nvptx_register_operand" "=3DR") > (truncate:DI > (lshiftrt:TI > (mult:TI (sign_extend:TI > (match_operand:DI 1 "nvptx_register_operand" "R")) > (sign_extend:TI > (match_operand:DI 2 "nvptx_register_operand" "R"))) > (const_int 64))))] > "" > "%.\\tmul.hi.s64\\t%0, %1, %2;") > > One complication with using this "widening multiplication"=20 > representation is that it requires an intermediate in a wider mode,=20 > making it difficult or impossible to encode a high-part multiplication = > of the widest supported integer mode. Yeah. It's also a problem when representing vector ops. > A second is that it can interfere with optimization; for example=20 > simplify-rtx.c contains the comment: > > case TRUNCATE: > /* Don't optimize (lshiftrt (mult ...)) as it would interfere > with the umulXi3_highpart patterns. */ > > Hopefully these problems are solved (or reduced) by introducing a new=20 > canonical form for high-part multiplications in RTL passes. > This also simplifies insn patterns when one operand is constant. > > Whilst implementing some constant folding simplifications and=20 > compile-time evaluation of these new RTX codes, I noticed that this=20 > functionality could also be added for the existing saturating=20 > arithmetic RTX codes. Then likewise when documenting these new RTX=20 > codes, I also took the opportunity to silence the @xref warnings in=20 > invoke.texi. > > This patch has been tested on x86_64-pc-linux-gnu with "make = bootstrap" > and "make -k check" with no new failures. Ok for mainline? > > > 2021-09-25 Roger Sayle > > gcc/ChangeLog > * gcc/rtl.def (SH_MULT, UH_MULT): New RTX codes for representing > signed and unsigned high-part multiplication respectively. > * gcc/simplify-rtx.c (simplify_binary_operation_1) [SH_MULT, > UH_MULT]: Simplify high-part multiplications by zero. > [SS_PLUS, US_PLUS, SS_MINUS, US_MINUS, SS_MULT, US_MULT, > SS_DIV, US_DIV]: Similar simplifications for saturating > arithmetic. > (simplify_const_binary_operation) [SS_PLUS, US_PLUS, SS_MINUS, > US_MINUS, SS_MULT, US_MULT, SH_MULT, UH_MULT]: Implement > compile-time evaluation for constant operands. > * gcc/dwarf2out.c (mem_loc_descriptor): Skip SH_MULT and UH_MULT. > * doc/rtl.texi (sh_mult, uhmult): Document new RTX codes. > * doc/md.texi (smul@var{m}3_highpart, umul@var{m3}_highpart): > Mention the new sh_mul and uh_mul RTX codes. > * doc/invoke.texi: Silence @xref "compilation" warnings. Look like a good idea to me. Only real comment is on the naming: if possible, I think we should try to avoid introducing yet more = differences between optab names and rtl codes. How about umul_highpart = for the unsigned code, to match both the optab and the existing = convention of adding =E2=80=9Cu=E2=80=9D directly to the front of = non-saturating operations? Things are more inconsistent for signed rtx codes: sometimes the = =E2=80=9Cs=E2=80=9D is present and sometimes it isn't. But since = =E2=80=9Csmin=E2=80=9D and =E2=80=9Csmax=E2=80=9D have it, I think we can justify having it here too. So I think we should use smul_highpart and umul_highpart. It's a bit more wordy than sh_mul, but still a lot shorter than the = status quo ;-) > diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index=20 > ebad5cb..b4b04b9 100644 > --- a/gcc/simplify-rtx.c > +++ b/gcc/simplify-rtx.c > @@ -4142,11 +4142,40 @@ simplify_context::simplify_binary_operation_1 = (rtx_code code, > case US_PLUS: > case SS_MINUS: > case US_MINUS: > + /* Simplify x + 0 to x, if possible. */ Nit: +/- > + if (trueop1 =3D=3D CONST0_RTX (mode) && !HONOR_SIGNED_ZEROS = (mode)) The HONOR_SIGNED_ZEROS check is redundant, since these ops don't support = modes with signed zero. Same for the other HONOR_* macros in the patch. E.g. I don't think we = should try to guess how infinities and saturation work together. > + return op0; > + return 0; > + > case SS_MULT: > case US_MULT: > + /* Simplify x * 0 to 0, if possible. */ > + if (trueop1 =3D=3D CONST0_RTX (mode) > + && !HONOR_NANS (mode) > + && !HONOR_SIGNED_ZEROS (mode) > + && !side_effects_p (op0)) > + return op1; > + > + /* Simplify x * 1 to x, if possible. */ > + if (trueop1 =3D=3D CONST1_RTX (mode) && !HONOR_SNANS (mode)) > + return op0; > + return 0; > + > + case SH_MULT: > + case UH_MULT: > + /* Simplify x * 0 to 0, if possible. */ > + if (trueop1 =3D=3D CONST0_RTX (mode) > + && !HONOR_NANS (mode) > + && !HONOR_SIGNED_ZEROS (mode) > + && !side_effects_p (op0)) > + return op1; > + return 0; > + > case SS_DIV: > case US_DIV: > - /* ??? There are simplifications that can be done. */ > + /* Simplify x / 1 to x, if possible. */ > + if (trueop1 =3D=3D CONST1_RTX (mode) && !HONOR_SNANS (mode)) > + return op0; > return 0; > =20 > case VEC_SERIES: > @@ -5011,6 +5040,63 @@ simplify_const_binary_operation (enum rtx_code = code, machine_mode mode, > } > break; > } > + > + case SS_PLUS: > + result =3D wi::add (pop0, pop1, SIGNED, &overflow); I think a goto label would be good here, so that later signed ops can = reuse this code instead of having to repeat it. Same idea for the unsigned case. > + if (overflow =3D=3D wi::OVF_OVERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); > + else if (overflow =3D=3D wi::OVF_UNDERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); Should be min_value. Same for the other underflow handlers. Like Andreas said, @pxref would be better where applicable. Thanks, Richard > + else if (overflow !=3D wi::OVF_NONE) > + return NULL_RTX; > + break; > + > + case US_PLUS: > + result =3D wi::add (pop0, pop1, UNSIGNED, &overflow); > + if (overflow !=3D wi::OVF_NONE) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = UNSIGNED); > + break; > + > + case SS_MINUS: > + result =3D wi::sub (pop0, pop1, SIGNED, &overflow); > + if (overflow =3D=3D wi::OVF_OVERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); > + else if (overflow =3D=3D wi::OVF_UNDERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); > + else if (overflow !=3D wi::OVF_NONE) > + return NULL_RTX; > + break; > + > + case US_MINUS: > + result =3D wi::sub (pop0, pop1, UNSIGNED, &overflow); > + if (overflow !=3D wi::OVF_NONE) > + result =3D wi::min_value (GET_MODE_PRECISION (int_mode), = UNSIGNED); > + break; > + > + case SS_MULT: > + result =3D wi::mul (pop0, pop1, SIGNED, &overflow); > + if (overflow =3D=3D wi::OVF_OVERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); > + else if (overflow =3D=3D wi::OVF_UNDERFLOW) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = SIGNED); > + else if (overflow !=3D wi::OVF_NONE) > + return NULL_RTX; > + break; > + > + case US_MULT: > + result =3D wi::mul (pop0, pop1, UNSIGNED, &overflow); > + if (overflow !=3D wi::OVF_NONE) > + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), = UNSIGNED); > + break; > + > + case SH_MULT: > + result =3D wi::mul_high (pop0, pop1, SIGNED); > + break; > + > + case UH_MULT: > + result =3D wi::mul_high (pop0, pop1, UNSIGNED); > + break; > + > default: > return NULL_RTX; > } ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; name="patchx3.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="patchx3.txt" diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi=0A= index 4acb941..7ed0c69 100644=0A= --- a/gcc/doc/invoke.texi=0A= +++ b/gcc/doc/invoke.texi=0A= @@ -3125,7 +3125,7 @@ errors if these functions are not inlined = everywhere they are called.=0A= @itemx -fno-modules-ts=0A= @opindex fmodules-ts=0A= @opindex fno-modules-ts=0A= -Enable support for C++20 modules (@xref{C++ Modules}). The=0A= +Enable support for C++20 modules (@pxref{C++ Modules}). The=0A= @option{-fno-modules-ts} is usually not needed, as that is the=0A= default. Even though this is a C++20 feature, it is not currently=0A= implicitly enabled by selecting that standard version.=0A= @@ -33553,7 +33553,7 @@ version selected, although in pre-C++20 = versions, it is of course an=0A= extension.=0A= =0A= No new source file suffixes are required or supported. If you wish to=0A= -use a non-standard suffix (@xref{Overall Options}), you also need=0A= +use a non-standard suffix (@pxref{Overall Options}), you also need=0A= to provide a @option{-x c++} option too.@footnote{Some users like to=0A= distinguish module interface files with a new suffix, such as naming=0A= the source @code{module.cppm}, which involves=0A= @@ -33615,8 +33615,8 @@ to be resolved at the end of compilation. = Without this, imported=0A= macros are only resolved when expanded or (re)defined. This option=0A= detects conflicting import definitions for all macros.=0A= =0A= -@xref{C++ Module Mapper} for details of the @option{-fmodule-mapper}=0A= -family of options.=0A= +For details of the @option{-fmodule-mapper} family of options,=0A= +@pxref{C++ Module Mapper}.=0A= =0A= @menu=0A= * C++ Module Mapper:: Module Mapper=0A= @@ -33833,8 +33833,8 @@ dialect used and imports of the = module.@footnote{The precise contents=0A= of this output may change.} The timestamp is the same value as that=0A= provided by the @code{__DATE__} & @code{__TIME__} macros, and may be=0A= explicitly specified with the environment variable=0A= -@code{SOURCE_DATE_EPOCH}. @xref{Environment Variables} for further=0A= -details.=0A= +@code{SOURCE_DATE_EPOCH}. For further details=0A= +@pxref{Environment Variables}.=0A= =0A= A set of related CMIs may be copied, provided the relative pathnames=0A= are preserved.=0A= diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi=0A= index 2b41cb7..ed35b8f 100644=0A= --- a/gcc/doc/md.texi=0A= +++ b/gcc/doc/md.texi=0A= @@ -5776,11 +5776,13 @@ multiplication.=0A= @item @samp{smul@var{m}3_highpart}=0A= Perform a signed multiplication of operands 1 and 2, which have mode=0A= @var{m}, and store the most significant half of the product in operand = 0.=0A= -The least significant half of the product is discarded.=0A= +The least significant half of the product is discarded. This may be=0A= +represented in RTL using a @code{smul_highpart} RTX expression.=0A= =0A= @cindex @code{umul@var{m}3_highpart} instruction pattern=0A= @item @samp{umul@var{m}3_highpart}=0A= -Similar, but the multiplication is unsigned.=0A= +Similar, but the multiplication is unsigned. This may be represented=0A= +in RTL using an @code{umul_highpart} RTX expression.=0A= =0A= @cindex @code{madd@var{m}@var{n}4} instruction pattern=0A= @item @samp{madd@var{m}@var{n}4}=0A= diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi=0A= index e1e76a9..2058997 100644=0A= --- a/gcc/doc/rtl.texi=0A= +++ b/gcc/doc/rtl.texi=0A= @@ -2524,7 +2524,19 @@ not be the same.=0A= For unsigned widening multiplication, use the same idiom, but with=0A= @code{zero_extend} instead of @code{sign_extend}.=0A= =0A= +@findex smul_highpart=0A= +@findex umul_highpart=0A= +@cindex high-part multiplication=0A= +@cindex multiplication high part=0A= +@item (smul_highpart:@var{m} @var{x} @var{y})=0A= +@itemx (umul_highpart:@var{m} @var{x} @var{y})=0A= +Represents the high-part multiplication of @var{x} and @var{y} carried=0A= +out in machine mode @var{m}. @code{smul_highpart} returns the high part=0A= +of a signed multiplication, @code{umul_highpart} returns the high part=0A= +of an unsigned multiplication.=0A= +=0A= @findex fma=0A= +@cindex fused multiply-add=0A= @item (fma:@var{m} @var{x} @var{y} @var{z})=0A= Represents the @code{fma}, @code{fmaf}, and @code{fmal} builtin=0A= functions, which compute @samp{@var{x} * @var{y} + @var{z}}=0A= diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c=0A= index 9876750..20f2c5d 100644=0A= --- a/gcc/dwarf2out.c=0A= +++ b/gcc/dwarf2out.c=0A= @@ -16809,6 +16809,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,=0A= case CONST_FIXED:=0A= case CLRSB:=0A= case CLOBBER:=0A= + case SMUL_HIGHPART:=0A= + case UMUL_HIGHPART:=0A= break;=0A= =0A= case CONST_STRING:=0A= diff --git a/gcc/rtl.def b/gcc/rtl.def=0A= index c80144b..5710a2e 100644=0A= --- a/gcc/rtl.def=0A= +++ b/gcc/rtl.def=0A= @@ -467,6 +467,11 @@ DEF_RTL_EXPR(SS_MULT, "ss_mult", "ee", = RTX_COMM_ARITH)=0A= /* Multiplication with unsigned saturation */=0A= DEF_RTL_EXPR(US_MULT, "us_mult", "ee", RTX_COMM_ARITH)=0A= =0A= +/* Signed high-part multiplication. */=0A= +DEF_RTL_EXPR(SMUL_HIGHPART, "smul_highpart", "ee", RTX_COMM_ARITH)=0A= +/* Unsigned high-part multiplication. */=0A= +DEF_RTL_EXPR(UMUL_HIGHPART, "umul_highpart", "ee", RTX_COMM_ARITH)=0A= +=0A= /* Operand 0 divided by operand 1. */=0A= DEF_RTL_EXPR(DIV, "div", "ee", RTX_BIN_ARITH)=0A= /* Division with signed saturation */=0A= diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c=0A= index ebad5cb..7e8e2c3 100644=0A= --- a/gcc/simplify-rtx.c=0A= +++ b/gcc/simplify-rtx.c=0A= @@ -4142,11 +4142,36 @@ simplify_context::simplify_binary_operation_1 = (rtx_code code,=0A= case US_PLUS:=0A= case SS_MINUS:=0A= case US_MINUS:=0A= + /* Simplify x +/- 0 to x, if possible. */=0A= + if (trueop1 =3D=3D CONST0_RTX (mode))=0A= + return op0;=0A= + return 0;=0A= +=0A= case SS_MULT:=0A= case US_MULT:=0A= + /* Simplify x * 0 to 0, if possible. */=0A= + if (trueop1 =3D=3D CONST0_RTX (mode)=0A= + && !side_effects_p (op0))=0A= + return op1;=0A= +=0A= + /* Simplify x * 1 to x, if possible. */=0A= + if (trueop1 =3D=3D CONST1_RTX (mode))=0A= + return op0;=0A= + return 0;=0A= +=0A= + case SMUL_HIGHPART:=0A= + case UMUL_HIGHPART:=0A= + /* Simplify x * 0 to 0, if possible. */=0A= + if (trueop1 =3D=3D CONST0_RTX (mode)=0A= + && !side_effects_p (op0))=0A= + return op1;=0A= + return 0;=0A= +=0A= case SS_DIV:=0A= case US_DIV:=0A= - /* ??? There are simplifications that can be done. */=0A= + /* Simplify x / 1 to x, if possible. */=0A= + if (trueop1 =3D=3D CONST1_RTX (mode))=0A= + return op0;=0A= return 0;=0A= =0A= case VEC_SERIES:=0A= @@ -5011,6 +5036,51 @@ simplify_const_binary_operation (enum rtx_code = code, machine_mode mode,=0A= }=0A= break;=0A= }=0A= +=0A= + case SS_PLUS:=0A= + result =3D wi::add (pop0, pop1, SIGNED, &overflow);=0A= + clamp_signed_saturation:=0A= + if (overflow =3D=3D wi::OVF_OVERFLOW)=0A= + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), SIGNED);=0A= + else if (overflow =3D=3D wi::OVF_UNDERFLOW)=0A= + result =3D wi::min_value (GET_MODE_PRECISION (int_mode), SIGNED);=0A= + else if (overflow !=3D wi::OVF_NONE)=0A= + return NULL_RTX;=0A= + break;=0A= +=0A= + case US_PLUS:=0A= + result =3D wi::add (pop0, pop1, UNSIGNED, &overflow);=0A= + clamp_unsigned_saturation: =0A= + if (overflow !=3D wi::OVF_NONE)=0A= + result =3D wi::max_value (GET_MODE_PRECISION (int_mode), UNSIGNED);=0A= + break;=0A= +=0A= + case SS_MINUS:=0A= + result =3D wi::sub (pop0, pop1, SIGNED, &overflow);=0A= + goto clamp_signed_saturation;=0A= +=0A= + case US_MINUS:=0A= + result =3D wi::sub (pop0, pop1, UNSIGNED, &overflow);=0A= + if (overflow !=3D wi::OVF_NONE)=0A= + result =3D wi::min_value (GET_MODE_PRECISION (int_mode), UNSIGNED);=0A= + break;=0A= +=0A= + case SS_MULT:=0A= + result =3D wi::mul (pop0, pop1, SIGNED, &overflow);=0A= + goto clamp_signed_saturation;=0A= +=0A= + case US_MULT:=0A= + result =3D wi::mul (pop0, pop1, UNSIGNED, &overflow);=0A= + goto clamp_unsigned_saturation;=0A= +=0A= + case SMUL_HIGHPART:=0A= + result =3D wi::mul_high (pop0, pop1, SIGNED);=0A= + break;=0A= +=0A= + case UMUL_HIGHPART:=0A= + result =3D wi::mul_high (pop0, pop1, UNSIGNED);=0A= + break;=0A= +=0A= default:=0A= return NULL_RTX;=0A= }=0A= ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; name="sse2-mmx-paddsb-2.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="sse2-mmx-paddsb-2.c" /* { dg-do compile } */=0A= /* { dg-options "-O2" } */=0A= =0A= typedef char v8qi __attribute__ ((vector_size (8)));=0A= =0A= char foo()=0A= {=0A= v8qi tx =3D { 1, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 2, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_paddsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char bar()=0A= {=0A= v8qi tx =3D { 100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_paddsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char baz()=0A= {=0A= v8qi tx =3D { -100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { -100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_paddsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */=0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */=0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-128," 1 } } */=0A= /* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */=0A= ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; name="sse2-mmx-paddusb-2.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="sse2-mmx-paddusb-2.c" /* { dg-do compile } */=0A= /* { dg-options "-O2" } */=0A= =0A= typedef char v8qi __attribute__ ((vector_size (8)));=0A= =0A= char foo()=0A= {=0A= v8qi tx =3D { 1, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 2, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_paddusb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char bar()=0A= {=0A= v8qi tx =3D { 200, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 200, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_paddusb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */=0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-1," 1 } } */=0A= /* { dg-final { scan-assembler-not "paddusb\[ \\t\]+%xmm\[0-9\]+" } } */=0A= =0A= ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; name="sse2-mmx-psubsb-2.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="sse2-mmx-psubsb-2.c" /* { dg-do compile } */=0A= /* { dg-options "-O2" } */=0A= =0A= typedef char v8qi __attribute__ ((vector_size (8)));=0A= =0A= char foo()=0A= {=0A= v8qi tx =3D { 5, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 2, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_psubsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char bar()=0A= {=0A= v8qi tx =3D { -100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_psubsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char baz()=0A= {=0A= v8qi tx =3D { 100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { -100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_psubsb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */=0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$-128," 1 } } */=0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$127," 1 } } */=0A= /* { dg-final { scan-assembler-not "paddsb\[ \\t\]+%xmm\[0-9\]+" } } */=0A= ------=_NextPart_000_022D_01D7B54E.94CA2030 Content-Type: text/plain; name="sse2-mmx-psubusb-2.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="sse2-mmx-psubusb-2.c" /* { dg-do compile } */=0A= /* { dg-options "-O2" } */=0A= =0A= typedef char v8qi __attribute__ ((vector_size (8)));=0A= =0A= char foo()=0A= {=0A= v8qi tx =3D { 5, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 2, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_psubusb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= char bar()=0A= {=0A= v8qi tx =3D { 100, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi ty =3D { 200, 0, 0, 0, 0, 0, 0, 0 };=0A= v8qi t =3D __builtin_ia32_psubusb(tx, ty);=0A= return t[0];=0A= }=0A= =0A= /* { dg-final { scan-assembler-times "movl\[ \\t\]+\\\$3," 1 } } */=0A= /* { dg-final { scan-assembler-times "xorl\[ \\t\]+" 1 } } */=0A= /* { dg-final { scan-assembler-not "psubusb\[ \\t\]+%xmm\[0-9\]+" } } */=0A= =0A= ------=_NextPart_000_022D_01D7B54E.94CA2030--