From patchwork Tue Nov 29 09:42:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Krebbel X-Patchwork-Id: 700366 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tSdrw36B2z9t2C for ; Tue, 29 Nov 2016 20:43:11 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="utYsdpOk"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:in-reply-to:references:message-id; q=dns; s= default; b=FdUD2lGw+ZqaVHxm61F3TJfv+BhFuVbut1gQUykqBV9IUs5OKCfbx x3uVnxty7warGzObmY4/lAsgJGN+Q/5iyTcnhmpJrYnrtFGYZempz9cTtJ+WugFy KojnMXAYk9k4H382OmCFpmhLNvXwjDvg7v9H7zFJQxYmzqQdkr2lCI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:in-reply-to:references:message-id; s=default; bh=znqLNcjl/pnYnZhD9v33FG6m1Ds=; b=utYsdpOkQvLBD6Cq0MDSM4bfhzwd IOLjzbWxguOTilDc0VoDCs+2ImzSr7LdpAi9cnlL6lexi7W03BQn4BJT+ccNEAhD GCIsUCADOzFcONnN6cURwVVd96Am40wySdgoxZnhDOEkj1H/UYPrMmza//3z95/T p7+nVxH3z6EsiDY= Received: (qmail 18752 invoked by alias); 29 Nov 2016 09:43:01 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 18667 invoked by uid 89); 29 Nov 2016 09:42:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=similiar, Similiar, THEN, 5136 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 29 Nov 2016 09:42:56 +0000 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id uAT9ctAR137687 for ; Tue, 29 Nov 2016 04:42:54 -0500 Received: from e06smtp09.uk.ibm.com (e06smtp09.uk.ibm.com [195.75.94.105]) by mx0b-001b2d01.pphosted.com with ESMTP id 2712rwh7yb-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 29 Nov 2016 04:42:54 -0500 Received: from localhost by e06smtp09.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 29 Nov 2016 09:42:52 -0000 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp09.uk.ibm.com (192.168.101.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 29 Nov 2016 09:42:51 -0000 Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id A72282190063 for ; Tue, 29 Nov 2016 09:42:02 +0000 (GMT) Received: from d06av26.portsmouth.uk.ibm.com (d06av26.portsmouth.uk.ibm.com [9.149.105.62]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id uAT9gon215532358 for ; Tue, 29 Nov 2016 09:42:51 GMT Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D5C07AE056 for ; Tue, 29 Nov 2016 08:41:07 +0000 (GMT) Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B9331AE061 for ; Tue, 29 Nov 2016 08:41:07 +0000 (GMT) Received: from maggie.boeblingen.de.ibm.com (unknown [9.152.212.134]) by d06av26.portsmouth.uk.ibm.com (Postfix) with ESMTPS for ; Tue, 29 Nov 2016 08:41:07 +0000 (GMT) From: Andreas Krebbel To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/4] S/390: Merge compare of compare results Date: Tue, 29 Nov 2016 10:42:45 +0100 In-Reply-To: <20161129094247.19012-1-krebbel@linux.vnet.ibm.com> References: <20161129094247.19012-1-krebbel@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16112909-0036-0000-0000-0000026C6E65 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16112909-0037-0000-0000-000013713E50 Message-Id: <20161129094247.19012-3-krebbel@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-11-29_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1609300000 definitions=main-1611290165 X-IsSubscribed: yes With this patch EQ and NE compares on CC mode reader patterns are folded. This allows using the result of the vec_all_* and vec_any_* builtins directly in a conditional jump instruction as in the attached testcase. gcc/ChangeLog: 2016-11-29 Andreas Krebbel * config/s390/s390-protos.h (s390_reverse_condition): New prototype. * config/s390/s390.c (s390_canonicalize_comparison): Fold compares of CC mode values. (s390_reverse_condition): New function. * config/s390/s390.h (REVERSE_CC_MODE, REVERSE_CONDITION): Define target macros. gcc/testsuite/ChangeLog: 2016-11-29 Andreas Krebbel * gcc.target/s390/zvector/vec-cmp-2.c: New test. --- gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 42 +++++ gcc/config/s390/s390.h | 12 ++ gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c | 203 ++++++++++++++++++++++ 4 files changed, 258 insertions(+) create mode 100644 gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 7ae98d4..000a677 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -119,6 +119,7 @@ extern void s390_expand_atomic (machine_mode, enum rtx_code, extern void s390_expand_tbegin (rtx, rtx, rtx, bool); extern void s390_expand_vec_compare (rtx, enum rtx_code, rtx, rtx); extern void s390_expand_vec_compare_cc (rtx, enum rtx_code, rtx, rtx, bool); +extern enum rtx_code s390_reverse_condition (machine_mode, enum rtx_code); extern void s390_expand_vcond (rtx, rtx, rtx, enum rtx_code, rtx, rtx); extern void s390_expand_vec_init (rtx, rtx); extern rtx s390_return_addr_rtx (int, rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 445c147..dab4f43 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -1722,6 +1722,31 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1, } tmp = *op0; *op0 = *op1; *op1 = tmp; } + + /* A comparison result is compared against zero. Replace it with + the (perhaps inverted) original comparison. + This probably should be done by simplify_relational_operation. */ + if ((*code == EQ || *code == NE) + && *op1 == const0_rtx + && COMPARISON_P (*op0) + && CC_REG_P (XEXP (*op0, 0))) + { + enum rtx_code new_code; + + if (*code == EQ) + new_code = reversed_comparison_code_parts (GET_CODE (*op0), + XEXP (*op0, 0), + XEXP (*op1, 0), NULL); + else + new_code = GET_CODE (*op0); + + if (new_code != UNKNOWN) + { + *code = new_code; + *op1 = XEXP (*op0, 1); + *op0 = XEXP (*op0, 0); + } + } } /* Helper function for s390_emit_compare. If possible emit a 64 bit @@ -6343,6 +6368,23 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code code, tmp_reg, target)); } +/* Invert the comparison CODE applied to a CC mode. This is only safe + if we know whether there result was created by a floating point + compare or not. For the CCV modes this is encoded as part of the + mode. */ +enum rtx_code +s390_reverse_condition (machine_mode mode, enum rtx_code code) +{ + /* Reversal of FP compares takes care -- an ordered compare + becomes an unordered compare and vice versa. */ + if (mode == CCVFALLmode || mode == CCVFANYmode) + return reverse_condition_maybe_unordered (code); + else if (mode == CCVIALLmode || mode == CCVIANYmode) + return reverse_condition (code); + else + gcc_unreachable (); +} + /* Generate a vector comparison expression loading either elements of THEN or ELS into TARGET depending on the comparison COND of CMP_OP1 and CMP_OP2. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 6be4d34..1d6d7b2 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -513,6 +513,18 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv); #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ s390_cannot_change_mode_class ((FROM), (TO), (CLASS)) +/* We can reverse a CC mode safely if we know whether it comes from a + floating point compare or not. With the vector modes it is encoded + as part of the mode. + FIXME: It might make sense to do this for other cc modes as well. */ +#define REVERSIBLE_CC_MODE(MODE) \ + ((MODE) == CCVIALLmode || (MODE) == CCVIANYmode \ + || (MODE) == CCVFALLmode || (MODE) == CCVFANYmode) + +/* Given a condition code and a mode, return the inverse condition. */ +#define REVERSE_CONDITION(CODE, MODE) s390_reverse_condition (MODE, CODE) + + /* Register classes. */ /* We use the following register classes: diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c b/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c new file mode 100644 index 0000000..0711f9c --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-2.c @@ -0,0 +1,203 @@ +/* Similiar to vec-cmp-1.c but requires that + s390_canonicalize_comparison is able to merge the the two nested + compares. */ + +/* { dg-do compile { target { s390*-*-* } } } */ +/* { dg-options "-O3 -mzarch -march=z13 -mzvector -fno-asynchronous-unwind-tables" } */ + +#include + +extern void foo (void); + +int __attribute__((noinline,noclone)) +all_eq_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_eq (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_ne_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_ne (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */ + +int __attribute__((noinline,noclone)) +all_gt_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_gt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_lt_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_lt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_ge_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_ge (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_le_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_all_le (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +any_eq_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_eq (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_ne_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_ne (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */ + +int __attribute__((noinline,noclone)) +any_gt_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_gt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_lt_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_lt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_ge_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_ge (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_le_double (vector double a, vector double b) +{ + if (__builtin_expect (vec_any_le (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +all_eq_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_eq (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_ne_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_ne (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */ + +int __attribute__((noinline,noclone)) +all_gt_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_gt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_lt_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_lt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjne 1 } } */ + +int __attribute__((noinline,noclone)) +all_ge_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_ge (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjle 1 } } */ + +int __attribute__((noinline,noclone)) +all_le_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_all_le (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times all_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjle 1 } } */ + +int __attribute__((noinline,noclone)) +any_eq_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_eq (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_ne_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_ne (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */ + +int __attribute__((noinline,noclone)) +any_gt_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_gt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_lt_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_lt (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tjnle 1 } } */ + +int __attribute__((noinline,noclone)) +any_ge_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_ge (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tje 1 } } */ + +int __attribute__((noinline,noclone)) +any_le_int (vector int a, vector int b) +{ + if (__builtin_expect (vec_any_le (a, b), 1)) + foo (); +} +/* { dg-final { scan-assembler-times any_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tje 1 } } */ +