From patchwork Wed Sep 18 17:25:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Schulze Frielinghaus X-Patchwork-Id: 1986936 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=bDQPiJM+; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4X870s6rs5z1y1m for ; Thu, 19 Sep 2024 04:46:53 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AF14F3857022 for ; Wed, 18 Sep 2024 18:46:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AF14F3857022 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1726685211; bh=qxhmzYasmTjQFwPzCjugshFQ5pGI6JG8YzsrrOWqfdU=; h=From:To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From; b=bDQPiJM+YcEXQ28iDHJnm+7DUW0v4fd9zPYX2kxn5lImbjapknmoATKzzO8K/dZVs BwE5HA3SswBeGbCERkAbGgp2dhbEzsdBfppAbCAzBpL4n31u+d5K0X6BhMv7F0UeeF viNy8ZVIaqQ9qRluvmZ93uIV+UDZgYqF3RUoXcEw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 24BD63858C52; Wed, 18 Sep 2024 18:46:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 24BD63858C52 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=gcc.gnu.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 24BD63858C52 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726685181; cv=none; b=LNzlQRHMHNFT9zCdQWjOfZo+zaW5h42zkV5k4qVYKr2U3DVW/m3uP0xgAywJXCzLrFVLYyDfcepH+Kxz60VL/63PQ2zTuDOFNGm//tQFtsRX/AJI7NrYCCBtMwqpT0h+lE4keHgaho1fz2bL8ZS6yuimvQmItojftF6PNCXnRKk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726685181; c=relaxed/simple; bh=8H1ZS1YdRo83QtNKyCdzg3rr396YdB/QpP0t2v6pNLk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=eU3vZV555APyTdFuFnmieGy0zUTmwkJJh5e3oo6pCMuLW8td73EWL8+wyhIREjNF/fEYupPmoLH8luxHfuVOI2EU2GayEmi3coOzp+UA5ijUeg1rC5vQR6GQqrAXqDYC7xiLFRO6CUL2k2gLPRAbKKSs5pVW8PWmcWOQf1xncpw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 48IEZ705010904; Wed, 18 Sep 2024 17:25:28 GMT Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 41n3vdqbkp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2024 17:25:26 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 48IES49h024669; Wed, 18 Sep 2024 17:25:11 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 41nq1n4871-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2024 17:25:11 +0000 Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 48IHP7Xa42533268 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 18 Sep 2024 17:25:08 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D50392004E; Wed, 18 Sep 2024 17:25:07 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B51D120040; Wed, 18 Sep 2024 17:25:07 +0000 (GMT) Received: from a8345010.lnxne.boe (unknown [9.152.108.100]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTPS; Wed, 18 Sep 2024 17:25:07 +0000 (GMT) From: Stefan Schulze Frielinghaus To: krebbel@linux.ibm.com, gcc-patches@gcc.gnu.org Cc: Stefan Schulze Frielinghaus Subject: [PATCH] s390: Add expander for uaddc/usubc optabs Date: Wed, 18 Sep 2024 19:25:04 +0200 Message-ID: <20240918172504.3545237-1-stefansf@gcc.gnu.org> X-Mailer: git-send-email 2.45.2 MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: eG2J_ihPevFwVuEorMr62mzK-MlwO90y X-Proofpoint-GUID: eG2J_ihPevFwVuEorMr62mzK-MlwO90y X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1051,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-18_10,2024-09-18_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 spamscore=0 lowpriorityscore=0 suspectscore=0 bulkscore=0 clxscore=1034 mlxscore=0 malwarescore=0 mlxlogscore=547 priorityscore=1501 phishscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2408220000 definitions=main-2409180114 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NEUTRAL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on s390. Both expander are constrained to z196 because of the conditional moves. I guess this is reasonable nowadays. Would be great if you could have a second look that setting the carry/borrow bit (bit 18 of the PSW) is indeed correct. Brain twisted me at first ;-) -- 8< -- gcc/ChangeLog: * config/s390/s390.md (*add3_carry1_cc): Renamed to ... (add3_carry1_cc): this and in order to use the corresponding gen function, encode CC mode into pattern. (*sub3_borrow_cc): Renamed to ... (sub3_borrow_cc): this and in order to use the corresponding gen function, encode CC mode into pattern. (*add3_alc_carry1_cc): Renamed to ... (add3_alc_carry1_cc): this and in order to use the corresponding gen function, encode CC mode into pattern. (sub3_slb_borrow1_cc): New. (uaddc5): New. (usubc5): New. gcc/testsuite/ChangeLog: * gcc.target/s390/uaddc-1.c: New test. * gcc.target/s390/uaddc-2.c: New test. * gcc.target/s390/usubc-1.c: New test. * gcc.target/s390/usubc-2.c: New test. --- gcc/config/s390/s390.md | 103 +++++++++++++++++++----- gcc/testsuite/gcc.target/s390/uaddc-1.c | 80 ++++++++++++++++++ gcc/testsuite/gcc.target/s390/uaddc-2.c | 25 ++++++ gcc/testsuite/gcc.target/s390/usubc-1.c | 80 ++++++++++++++++++ gcc/testsuite/gcc.target/s390/usubc-2.c | 25 ++++++ 5 files changed, 295 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/uaddc-1.c create mode 100644 gcc/testsuite/gcc.target/s390/uaddc-2.c create mode 100644 gcc/testsuite/gcc.target/s390/usubc-1.c create mode 100644 gcc/testsuite/gcc.target/s390/usubc-2.c diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 4a225ae24f3..6fd3f943fe1 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -6001,14 +6001,14 @@ z10_super_E1,z10_super_E1,z10_super_E1")]) ; alr, alfi, slfi, al, aly, alrk, alhsik, algr, algfi, slgfi, alg, alsi, algsi, algrk, alghsik -(define_insn "*add3_carry1_cc" - [(set (reg CC_REGNUM) - (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d, 0, 0,d,0,0,0") - (match_operand:GPR 2 "general_operand" " d,d,Op,On,K,R,T,C")) - (match_dup 1))) - (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,d,d,d,d") +(define_insn "add3_carry1_cc" + [(set (reg:CCL1 CC_REGNUM) + (compare:CCL1 (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d, 0, 0,d,0,0,0") + (match_operand:GPR 2 "general_operand" " d,d,Op,On,K,R,T,C")) + (match_dup 1))) + (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,d,d,d,d") (plus:GPR (match_dup 1) (match_dup 2)))] - "s390_match_ccmode (insn, CCL1mode)" + "" "@ alr\t%0,%2 alrk\t%0,%1,%2 @@ -6541,14 +6541,14 @@ (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")]) ; slr, sl, sly, slgr, slg, slrk, slgrk -(define_insn "*sub3_borrow_cc" - [(set (reg CC_REGNUM) - (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0") - (match_operand:GPR 2 "general_operand" "d,d,R,T")) - (match_dup 1))) - (set (match_operand:GPR 0 "register_operand" "=d,d,d,d") +(define_insn "sub3_borrow_cc" + [(set (reg:CCL2 CC_REGNUM) + (compare:CCL2 (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0") + (match_operand:GPR 2 "general_operand" "d,d,R,T")) + (match_dup 1))) + (set (match_operand:GPR 0 "register_operand" "=d,d,d,d") (minus:GPR (match_dup 1) (match_dup 2)))] - "s390_match_ccmode (insn, CCL2mode)" + "" "@ slr\t%0,%2 slrk\t%0,%1,%2 @@ -6754,22 +6754,50 @@ ; add(di|si)cc instruction pattern(s). ; +(define_expand "uaddc5" + [(match_operand:GPR 0 "register_operand") + (match_operand:GPR 1 "nonimmediate_operand") + (match_operand:GPR 2 "nonimmediate_operand") + (match_operand:GPR 3 "nonimmediate_operand") + (match_operand:GPR 4 "general_operand")] + "TARGET_Z196 && (mode != DImode || TARGET_64BIT)" +{ + rtx cond = gen_rtx_LTU (mode, gen_rtx_REG (CCL1mode, CC_REGNUM), const0_rtx); + if (operands[4] == const0_rtx) + emit_insn (gen_add3_carry1_cc (operands[0], operands[2], operands[3])); + else + { + rtx tmp; + if (CONSTANT_P (operands[4])) + { + tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + } + else + tmp = operands[4]; + s390_emit_compare (LTU, tmp, const0_rtx); + emit_insn (gen_add3_alc_carry1_cc (operands[0], operands[2], operands[3], cond)); + } + emit_insn (gen_movcc (operands[1], cond, const1_rtx, const0_rtx)); + DONE; +}) + ; the following 4 patterns are used when the result of an add with ; carry is checked for an overflow condition ; op1 + op2 + c < op1 ; alcr, alc, alcgr, alcg -(define_insn "*add3_alc_carry1_cc" - [(set (reg CC_REGNUM) - (compare +(define_insn "add3_alc_carry1_cc" + [(set (reg:CCL1 CC_REGNUM) + (compare:CCL1 (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "") (match_operand:GPR 1 "nonimmediate_operand" "%0,0")) (match_operand:GPR 2 "general_operand" "d,T")) (match_dup 1))) (set (match_operand:GPR 0 "register_operand" "=d,d") (plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))] - "s390_match_ccmode (insn, CCL1mode)" + "" "@ alcr\t%0,%2 alc\t%0,%2" @@ -6854,6 +6882,28 @@ alc\t%0,%2" [(set_attr "op_type" "RRE,RXY")]) +(define_expand "usubc5" + [(match_operand:GPR 0 "register_operand") + (match_operand:GPR 1 "nonimmediate_operand") + (match_operand:GPR 2 "nonimmediate_operand") + (match_operand:GPR 3 "nonimmediate_operand") + (match_operand:GPR 4 "general_operand")] + "TARGET_Z196 && (mode != DImode || TARGET_64BIT)" +{ + rtx cond = gen_rtx_GTU (mode, gen_rtx_REG (CCL2mode, CC_REGNUM), const0_rtx); + if (operands[4] == const0_rtx) + emit_insn (gen_sub3_borrow_cc (operands[0], operands[2], operands[3])); + else + { + rtx tmp = gen_reg_rtx (mode); + emit_insn (gen_xor3 (tmp, operands[4], const1_rtx)); + s390_emit_compare (GTU, tmp, const0_rtx); + emit_insn (gen_sub3_slb_borrow1_cc (operands[0], operands[2], operands[3], cond)); + } + emit_insn (gen_movcc (operands[1], cond, const1_rtx, const0_rtx)); + DONE; +}) + ; slbr, slb, slbgr, slbg (define_insn "*sub3_slb_cc" [(set (reg CC_REGNUM) @@ -6885,6 +6935,23 @@ [(set_attr "op_type" "RRE,RXY") (set_attr "z10prop" "z10_c,*")]) +; slbr, slb, slbgr, slbg +(define_insn "sub3_slb_borrow1_cc" + [(set (reg:CCL2 CC_REGNUM) + (compare:CCL2 + (minus:GPR (minus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0") + (match_operand:GPR 2 "general_operand" "d,T")) + (match_operand:GPR 3 "s390_slb_comparison" "")) + (match_dup 1))) + (set (match_operand:GPR 0 "register_operand" "=d,d") + (minus:GPR (minus:GPR (match_dup 1) (match_dup 2)) (match_dup 3)))] + "" + "@ + slbr\t%0,%2 + slb\t%0,%2" + [(set_attr "op_type" "RRE,RXY") + (set_attr "z10prop" "z10_c,*")]) + (define_expand "addcc" [(match_operand:GPR 0 "register_operand" "") (match_operand 1 "comparison_operator" "") diff --git a/gcc/testsuite/gcc.target/s390/uaddc-1.c b/gcc/testsuite/gcc.target/s390/uaddc-1.c new file mode 100644 index 00000000000..dfad5915690 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/uaddc-1.c @@ -0,0 +1,80 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mzarch -save-temps -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "\\.UADDC \\(" 2 "optimized" { target lp64 } } } */ +/* { dg-final { scan-tree-dump-times "\\.UADDC \\(" 1 "optimized" { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "\\talcr\\t" 1 } } */ +/* { dg-final { scan-assembler-times "\\talcgr\\t" 1 { target lp64 } } } */ + +#include + +unsigned int __attribute__ ((noipa)) +uaddc (unsigned int x, unsigned int y, _Bool carry_in, _Bool *carry_out) +{ + unsigned int r; + _Bool c1 = __builtin_add_overflow (x, y, &r); + _Bool c2 = __builtin_add_overflow (r, carry_in, &r); + *carry_out = c1 | c2; + return r; +} + +#ifdef __s390x__ +unsigned long __attribute__ ((noipa)) +uaddcl (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out) +{ + unsigned long r; + _Bool c1 = __builtin_add_overflow (x, y, &r); + _Bool c2 = __builtin_add_overflow (r, carry_in, &r); + *carry_out = c1 | c2; + return r; +} +#endif + +void +test_int (void) +{ + _Bool c; + unsigned int r; + + r = uaddc (0xf0000000u, 0x0fffffffu, 0, &c); + assert (r == 0xffffffffu && !c); + + r = uaddc (0xf0000000u, 0x0fffffffu, 1, &c); + assert (r == 0 && c); + + r = uaddc (0xf0000001u, 0x0fffffffu, 0, &c); + assert (r == 0 && c); + + r = uaddc (0xf0000001u, 0x0fffffffu, 1, &c); + assert (r == 1 && c); +} + +#ifdef __s390x__ +void +test_long (void) +{ + _Bool c; + unsigned long r; + + r = uaddcl (0xf000000000000000u, 0x0fffffffffffffffu, 0, &c); + assert (r == 0xffffffffffffffffu && !c); + + r = uaddcl (0xf000000000000000u, 0x0fffffffffffffffu, 1, &c); + assert (r == 0 && c); + + r = uaddcl (0xf000000000000001u, 0x0fffffffffffffffu, 0, &c); + assert (r == 0 && c); + + r = uaddcl (0xf000000000000001u, 0x0fffffffffffffffu, 1, &c); + assert (r == 1 && c); +} +#endif + +int +main (void) +{ + test_int (); +#ifdef __s390x__ + test_long (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/s390/uaddc-2.c b/gcc/testsuite/gcc.target/s390/uaddc-2.c new file mode 100644 index 00000000000..61bcc6dee59 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/uaddc-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mzarch -save-temps -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "\\.UADDC \\(" 6 "optimized" } } */ +/* { dg-final { scan-assembler-times "\\talcr\\t" 6 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "\\talcr\\t" 3 { target lp64 } } } */ +/* { dg-final { scan-assembler-times "\\talcgr\\t" 3 { target lp64 } } } */ + +#define TEST(T, V, OP) \ + unsigned T \ + uaddc_##T##_##V (unsigned T x, unsigned T y, _Bool carry_in, _Bool *carry_out) \ + { \ + unsigned T r; \ + _Bool c1 = __builtin_add_overflow (x, y, &r); \ + _Bool c2 = __builtin_add_overflow (r, carry_in, &r); \ + *carry_out = c1 OP c2; \ + return r; \ + } + +TEST(int, 1, |) +TEST(int, 2, ||) +TEST(int, 3, ^) + +TEST(long, 1, |) +TEST(long, 2, ||) +TEST(long, 3, ^) diff --git a/gcc/testsuite/gcc.target/s390/usubc-1.c b/gcc/testsuite/gcc.target/s390/usubc-1.c new file mode 100644 index 00000000000..f4bee1e1534 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/usubc-1.c @@ -0,0 +1,80 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mzarch -save-temps -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "\\.USUBC \\(" 2 "optimized" { target lp64 } } } */ +/* { dg-final { scan-tree-dump-times "\\.USUBC \\(" 1 "optimized" { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "\\tslbr\\t" 1 } } */ +/* { dg-final { scan-assembler-times "\\tslbgr\\t" 1 { target lp64 } } } */ + +#include + +unsigned int __attribute__ ((noipa)) +usubc (unsigned int x, unsigned int y, _Bool borrow_in, _Bool *borrow_out) +{ + unsigned int r; + _Bool b1 = __builtin_sub_overflow (x, y, &r); + _Bool b2 = __builtin_sub_overflow (r, borrow_in, &r); + *borrow_out = b1 | b2; + return r; +} + +#ifdef __s390x__ +unsigned long __attribute__ ((noipa)) +usubcl (unsigned long x, unsigned long y, _Bool borrow_in, _Bool *borrow_out) +{ + unsigned long r; + _Bool b1 = __builtin_sub_overflow (x, y, &r); + _Bool b2 = __builtin_sub_overflow (r, borrow_in, &r); + *borrow_out = b1 | b2; + return r; +} +#endif + +void +test_int (void) +{ + _Bool b; + unsigned int r; + + r = usubc (0xfu, 0xfu, 0, &b); + assert (r == 0 && !b); + + r = usubc (0xfu, 0xfu, 1, &b); + assert (r == 0xffffffffu && b); + + r = usubc (0xfu, 0xffu, 0, &b); + assert (r == 0xffffff10u && b); + + r = usubc (0xfu, 0xffu, 1, &b); + assert (r == 0xffffff0fu && b); +} + +#ifdef __s390x__ +void +test_long (void) +{ + _Bool b; + unsigned long r; + + r = usubcl (0xfu, 0xfu, 0, &b); + assert (r == 0 && !b); + + r = usubcl (0xfu, 0xfu, 1, &b); + assert (r == 0xffffffffffffffffu && b); + + r = usubcl (0xfu, 0xffu, 0, &b); + assert (r == 0xffffffffffffff10u && b); + + r = usubcl (0xfu, 0xffu, 1, &b); + assert (r == 0xffffffffffffff0fu && b); +} +#endif + +int +main (void) +{ + test_int (); +#ifdef __s390x__ + test_long (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/s390/usubc-2.c b/gcc/testsuite/gcc.target/s390/usubc-2.c new file mode 100644 index 00000000000..b67907ed663 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/usubc-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mzarch -save-temps -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "\\.USUBC \\(" 6 "optimized" } } */ +/* { dg-final { scan-assembler-times "\\tslbr\\t" 6 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times "\\tslbr\\t" 3 { target lp64 } } } */ +/* { dg-final { scan-assembler-times "\\tslbgr\\t" 3 { target lp64 } } } */ + +#define TEST(T, V, OP) \ + unsigned T \ + uaddc_##T##_##V (unsigned T x, unsigned T y, _Bool carry_in, _Bool *carry_out) \ + { \ + unsigned T r; \ + _Bool c1 = __builtin_sub_overflow (x, y, &r); \ + _Bool c2 = __builtin_sub_overflow (r, carry_in, &r); \ + *carry_out = c1 OP c2; \ + return r; \ + } + +TEST(int, 1, |) +TEST(int, 2, ||) +TEST(int, 3, ^) + +TEST(long, 1, |) +TEST(long, 2, ||) +TEST(long, 3, ^)