From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id BA826382E801; Thu, 4 Mar 2021 14:08:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org BA826382E801 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 124E5Bw7100714; Thu, 4 Mar 2021 09:08:10 -0500 Received: from ppma03fra.de.ibm.com (6b.4a.5195.ip4.static.sl-reverse.com [149.81.74.107]) by mx0a-001b2d01.pphosted.com with ESMTP id 3730w68beh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 04 Mar 2021 09:08:10 -0500 Received: from pps.filterd (ppma03fra.de.ibm.com [127.0.0.1]) by ppma03fra.de.ibm.com (8.16.0.42/8.16.0.42) with SMTP id 124E88Wv011615; Thu, 4 Mar 2021 14:08:08 GMT Received: from b06avi18878370.portsmouth.uk.ibm.com (b06avi18878370.portsmouth.uk.ibm.com [9.149.26.194]) by ppma03fra.de.ibm.com with ESMTP id 371a8esb4j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 04 Mar 2021 14:08:08 +0000 Received: from d06av26.portsmouth.uk.ibm.com (d06av26.portsmouth.uk.ibm.com [9.149.105.62]) by b06avi18878370.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 124E7otl31392136 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 4 Mar 2021 14:07:50 GMT Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F34FEAE055; Thu, 4 Mar 2021 14:08:04 +0000 (GMT) Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A8E6AAE051; Thu, 4 Mar 2021 14:08:04 +0000 (GMT) Received: from vm.lan (unknown [9.145.31.74]) by d06av26.portsmouth.uk.ibm.com (Postfix) with ESMTP; Thu, 4 Mar 2021 14:08:04 +0000 (GMT) From: Ilya Leoshkevich To: Andreas Krebbel Cc: gcc-patches@gcc.gnu.org, Ilya Leoshkevich Subject: [PATCH v3] IBM Z: Fix usage of "f" constraint with long doubles Date: Thu, 4 Mar 2021 15:08:02 +0100 Message-Id: <20210304140802.145010-1-iii@linux.ibm.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369, 18.0.761 definitions=2021-03-04_03:2021-03-03, 2021-03-04 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 priorityscore=1501 spamscore=0 lowpriorityscore=0 mlxscore=0 impostorscore=0 adultscore=0 clxscore=1015 bulkscore=0 suspectscore=0 mlxlogscore=999 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2103040067 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Thu, 04 Mar 2021 14:08:14 -0000 v1: https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563799.html v1 -> v2: - Handle constraint modifiers, use AR constraint instead of R, add testcases for & and %. v2: https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564380.html v2 -> v3: - The main prereq is now committed: https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566237.html - Dropped long-double-asm-abi.c test, because its prereq is not approved (yet): https://gcc.gnu.org/pipermail/gcc-patches/2021-March/566218.html - Removed superfluous constraint pointer increment. After switching the s390 backend to store long doubles in vector registers, "f" constraint broke when used with the former: long doubles correspond to TFmode, which in combination with "f" corresponds to hard regs %v0-%v15, however, asm users expect a %f0-%f15 pair. Fix by using TARGET_MD_ASM_ADJUST hook to convert TFmode values to FPRX2mode and back. gcc/ChangeLog: 2020-12-14 Ilya Leoshkevich * config/s390/s390.c (f_constraint_p): New function. (s390_md_asm_adjust): Implement TARGET_MD_ASM_ADJUST. (TARGET_MD_ASM_ADJUST): Likewise. * config/s390/vector.md (fprx2_to_tf): Rename from *fprx2_to_tf, add memory alternative. (tf_to_fprx2): New pattern. gcc/testsuite/ChangeLog: 2020-12-14 Ilya Leoshkevich * gcc.target/s390/vector/long-double-asm-commutative.c: New test. * gcc.target/s390/vector/long-double-asm-earlyclobber.c: New test. * gcc.target/s390/vector/long-double-asm-in-out.c: New test. * gcc.target/s390/vector/long-double-asm-inout.c: New test. * gcc.target/s390/vector/long-double-asm-matching.c: New test. * gcc.target/s390/vector/long-double-asm-regmem.c: New test. * gcc.target/s390/vector/long-double-volatile-from-i64.c: New test. --- gcc/config/s390/s390.c | 86 +++++++++++++++++++ .../s390/vector/long-double-asm-commutative.c | 16 ++++ .../vector/long-double-asm-earlyclobber.c | 17 ++++ .../s390/vector/long-double-asm-in-out.c | 14 +++ .../s390/vector/long-double-asm-inout.c | 14 +++ .../s390/vector/long-double-asm-matching.c | 13 +++ .../s390/vector/long-double-asm-regmem.c | 8 ++ .../vector/long-double-volatile-from-i64.c | 22 +++++ 8 files changed, 190 insertions(+) create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-commutative.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-earlyclobber.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-in-out.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-inout.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-matching.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-asm-regmem.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/long-double-volatile-from-i64.c diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f3d0d1ba596..68dc3c58c1b 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -16698,6 +16698,89 @@ s390_shift_truncation_mask (machine_mode mode) return mode == DImode || mode == SImode ? 63 : 0; } +/* Return TRUE iff CONSTRAINT is an "f" constraint, possibly with additional + modifiers. */ + +static bool +f_constraint_p (const char *constraint) +{ + for (size_t i = 0, c_len = strlen (constraint); i < c_len; + i += CONSTRAINT_LEN (constraint[i], constraint + i)) + { + if (constraint[i] == 'f') + return true; + } + return false; +} + +/* Implement TARGET_MD_ASM_ADJUST hook in order to fix up "f" + constraints when long doubles are stored in vector registers. */ + +static rtx_insn * +s390_md_asm_adjust (vec &outputs, vec &inputs, + vec &input_modes, + vec &constraints, vec & /*clobbers*/, + HARD_REG_SET & /*clobbered_regs*/) +{ + if (!TARGET_VXE) + /* Long doubles are stored in FPR pairs - nothing to do. */ + return NULL; + + rtx_insn *after_md_seq = NULL, *after_md_end = NULL; + + unsigned ninputs = inputs.length (); + unsigned noutputs = outputs.length (); + for (unsigned i = 0; i < noutputs; i++) + { + if (GET_MODE (outputs[i]) != TFmode) + /* Not a long double - nothing to do. */ + continue; + const char *constraint = constraints[i]; + bool allows_mem, allows_reg, is_inout; + bool ok = parse_output_constraint (&constraint, i, ninputs, noutputs, + &allows_mem, &allows_reg, &is_inout); + gcc_assert (ok); + if (!f_constraint_p (constraint)) + /* Long double with a constraint other than "=f" - nothing to do. */ + continue; + gcc_assert (allows_reg); + gcc_assert (!is_inout); + /* Copy output value from a FPR pair into a vector register. */ + rtx fprx2 = gen_reg_rtx (FPRX2mode); + push_to_sequence2 (after_md_seq, after_md_end); + emit_insn (gen_fprx2_to_tf (outputs[i], fprx2)); + after_md_seq = get_insns (); + after_md_end = get_last_insn (); + end_sequence (); + outputs[i] = fprx2; + } + + for (unsigned i = 0; i < ninputs; i++) + { + if (GET_MODE (inputs[i]) != TFmode) + /* Not a long double - nothing to do. */ + continue; + const char *constraint = constraints[noutputs + i]; + bool allows_mem, allows_reg; + bool ok = parse_input_constraint (&constraint, i, ninputs, noutputs, 0, + constraints.address (), &allows_mem, + &allows_reg); + gcc_assert (ok); + if (!f_constraint_p (constraint)) + /* Long double with a constraint other than "f" (or "=f" for inout + operands) - nothing to do. */ + continue; + gcc_assert (allows_reg); + /* Copy input value from a vector register into a FPR pair. */ + rtx fprx2 = gen_reg_rtx (FPRX2mode); + emit_insn (gen_tf_to_fprx2 (fprx2, inputs[i])); + inputs[i] = fprx2; + input_modes[i] = FPRX2mode; + } + + return after_md_seq; +} + /* Initialize GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -17005,6 +17088,9 @@ s390_shift_truncation_mask (machine_mode mode) #undef TARGET_MAX_ANCHOR_OFFSET #define TARGET_MAX_ANCHOR_OFFSET 0xfff +#undef TARGET_MD_ASM_ADJUST +#define TARGET_MD_ASM_ADJUST s390_md_asm_adjust + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-s390.h" diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-commutative.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-commutative.c new file mode 100644 index 00000000000..59d807c54b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-commutative.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +int +main (void) +{ + long double res, x = 40., y = 2.; + asm("lxr\t%0,%1\n" + "\taxbr\t%0,%2" + : "=&f"(res) + : "%f"(x), "f"(y)); + assert (res == 42.); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-earlyclobber.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-earlyclobber.c new file mode 100644 index 00000000000..5dd027596de --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-earlyclobber.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +int +main (void) +{ + long double res, x = 0x1.0000000000001p+0L, + exp = 1.00000000000000011102230246251564788e+0L; + asm("lzxr\t%0\n" + "\tsqxbr\t%0,%1" + : "=&f"(res) + : "f"(x)); + assert (res == exp); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-in-out.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-in-out.c new file mode 100644 index 00000000000..27d447f6898 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-in-out.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +int +main (void) +{ + long double res, x = 0x1.0000000000001p+0L, + exp = 1.00000000000000011102230246251564788e+0L; + asm("sqxbr\t%0,%1" : "=f"(res) : "f"(x)); + assert (res == exp); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-inout.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-inout.c new file mode 100644 index 00000000000..e0b6ac518aa --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-inout.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +int +main (void) +{ + long double res = 0x1.0000000000001p+0L, + exp = 1.00000000000000011102230246251564788e+0L; + asm("sqxbr\t%0,%0" : "+f"(res)); + assert (res == exp); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-matching.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-matching.c new file mode 100644 index 00000000000..c8b8c3d1c6e --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-matching.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +int +main (void) +{ + long double res, x = 40., y = 2.; + asm("axbr\t%0,%2" : "=f"(res) : "0"(x), "f"(y)); + assert (res == 42.); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-asm-regmem.c b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-regmem.c new file mode 100644 index 00000000000..314f658b025 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-asm-regmem.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch" } */ + +void +foo (long double x) +{ + asm("# %0" : "+fm"(x)); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-volatile-from-i64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-volatile-from-i64.c new file mode 100644 index 00000000000..f4489841c28 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/long-double-volatile-from-i64.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */ +/* { dg-do run { target { s390_z14_hw } } } */ +#include +#include + +__attribute__ ((noipa)) static long double +long_double_volatile_from_i64 (int64_t x) +{ + static volatile long double y; + y = x; + return y; +} + +/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */ + +int +main (void) +{ + assert (long_double_volatile_from_i64 (42) == 42.L); + assert (long_double_volatile_from_i64 (-42) == -42.L); +} -- 2.29.2