From patchwork Wed Nov 23 07:08:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: HAO CHEN GUI X-Patchwork-Id: 1708155 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) 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=Z2jeQlz0; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NHC0x6Nhpz23nx for ; Wed, 23 Nov 2022 18:09:20 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 43F4E384D9A5 for ; Wed, 23 Nov 2022 07:09:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 43F4E384D9A5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669187358; bh=J1CyhVuNQL56sFi6lCPE5GYlv3QR/9G3VF5B2ithYhM=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=Z2jeQlz0uTMBgsQzwb1XmYG11V4ydx+eyL5yNsQ2yzbmlIUDdIdMq5ZErU8qXLxiJ yYGGcWr8wc9vWrkWqUL6u00znA6IwxSCtXdgPjFSraPUnYRtvydrSx69y3sjMKIpz/ LzQKHfrjAVtAwELdaXLdafOV9RWU6nffmpgV6B3Q= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id 6FC6438582BC for ; Wed, 23 Nov 2022 07:08:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6FC6438582BC Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2AN6LoTR010250; Wed, 23 Nov 2022 07:08:53 GMT Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3m10w5kt8g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Nov 2022 07:08:53 +0000 Received: from m0098421.ppops.net (m0098421.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 2AN75e2i018149; Wed, 23 Nov 2022 07:08:53 GMT Received: from ppma03fra.de.ibm.com (6b.4a.5195.ip4.static.sl-reverse.com [149.81.74.107]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3m10w5kt7y-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Nov 2022 07:08:53 +0000 Received: from pps.filterd (ppma03fra.de.ibm.com [127.0.0.1]) by ppma03fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 2AN75WJx004383; Wed, 23 Nov 2022 07:08:51 GMT Received: from b06avi18626390.portsmouth.uk.ibm.com (b06avi18626390.portsmouth.uk.ibm.com [9.149.26.192]) by ppma03fra.de.ibm.com with ESMTP id 3kxps93um3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Nov 2022 07:08:51 +0000 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06avi18626390.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 2AN72XLc44499262 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 23 Nov 2022 07:02:33 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0B7D34C040; Wed, 23 Nov 2022 07:08:48 +0000 (GMT) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 727AB4C044; Wed, 23 Nov 2022 07:08:46 +0000 (GMT) Received: from [9.200.144.161] (unknown [9.200.144.161]) by d06av22.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 23 Nov 2022 07:08:46 +0000 (GMT) Message-ID: <75fb4899-ceb2-e6a9-0dd4-577de9a8b976@linux.ibm.com> Date: Wed, 23 Nov 2022 15:08:44 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.5.0 To: gcc-patches Cc: Segher Boessenkool , David , "Kewen.Lin" , Peter Bergner Subject: [PATCH] Add a new conversion for conditional ternary set into ifcvt [PR106536] X-TM-AS-GCONF: 00 X-Proofpoint-GUID: xAfFvarIuOJe9_hEDKjWMFITHt2SF-fY X-Proofpoint-ORIG-GUID: dSnXgGhH8BUmqW-hRfOzB2Ua1482Iufs X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.895,Hydra:6.0.545,FMLib:17.11.122.1 definitions=2022-11-23_02,2022-11-18_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 bulkscore=0 adultscore=0 mlxscore=0 lowpriorityscore=0 suspectscore=0 impostorscore=0 priorityscore=1501 spamscore=0 phishscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2210170000 definitions=main-2211230048 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: HAO CHEN GUI via Gcc-patches From: HAO CHEN GUI Reply-To: HAO CHEN GUI Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, There is a new insn on my target, which has a nested if_then_else and set -1, 0 and 1 according to a comparison. [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (if_then_else:SI (lt (match_operand:CC 1 "cc_reg_operand" "y") (const_int 0)) (const_int -1) (if_then_else (gt (match_dup 1) (const_int 0)) (const_int 1) (const_int 0))))] In ifcvt pass, it probably contains a comparison, a branch, a setcc and a constant set. 8: r122:CC=cmp(r120:DI#0,r121:DI#0) 9: pc={(r122:CC<0)?L29:pc} 14: r118:SI=r122:CC>0 29: L29: 5: r118:SI=0xffffffffffffffff This patch adds the new conversion into ifcvt and convert this kind of branch into a nested if-then-else insn if the target supports such pattern. HAVE_ternary_conditional_set indicates if the target has such nested if-then-else insn. It's set in genconfig. noce_try_ternary_cset will be executed to detect suitable pattern and convert it to the nested if-then-else insn if HAVE_ternary_conditional_set is set. The hook TARGET_NOCE_TERNARY_CSET_P detects target specific pattern and output conditions and setting integers for the nested if-then-else. Bootstrapped and tested on powerpc64-linux BE/LE and x86 with no regressions. Is this okay for trunk? Any recommendations? Thanks a lot. ChangeLog 2022-11-23 Haochen Gui gcc/ * doc/tm.texi: Regenerate. * doc/tm.texi.in (TARGET_NOCE_TERNARY_CSET_P): Document new hook. * genconfig.cc (have_ternary_cset_flag): New. (walk_insn_part): Detect nested if-then-else with const_int setting and set have_ternary_cset_flag. (HAVE_ternary_conditional_set): Define. * ifcvt.cc (noce_emit_ternary_cset): New function to emit nested if-then-else insns. (noce_try_ternary_cset): Detect ternary conditional set and emit the insn. (noce_process_if_block): Try to do ternary condition set convertion when a target supports ternary conditional set insn. * target.def (noce_ternary_cset_p): New hook. * targhooks.cc (default_noce_ternary_cset_p): New function. * targhooks.h (default_noce_ternary_cset_p): New declare. patch.diff diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 92bda1a7e14..9823eccbe68 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -7094,6 +7094,15 @@ the @code{POLY_VALUE_MIN}, @code{POLY_VALUE_MAX} and implementation returns the lowest possible value of @var{val}. @end deftypefn +@deftypefn {Target Hook} bool TARGET_NOCE_TERNARY_CSET_P (struct noce_if_info *@var{if_info}, rtx *@var{outer_cond}, rtx *@var{inner_cond}, int *@var{int1}, int *@var{int2}, int *@var{int3}) +This hook returns true if the if-then-else-join blocks describled in +@code{if_info} can be converted to a ternary conditional set implemented by +a nested if-then-else insn. The @code{int1}, @code{int2} and @code{int3} +are three possible results of the nested if-then-else insn. +@code{outer_cond} and @code{inner_cond} are the conditions for outer and +if-then-else. +@end deftypefn + @node Scheduling @section Adjusting the Instruction Scheduler diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 112462310b1..1d6f28cc50a 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -4631,6 +4631,8 @@ Define this macro if a non-short-circuit operation produced by @hook TARGET_ESTIMATED_POLY_VALUE +@hook TARGET_NOCE_TERNARY_CSET_P + @node Scheduling @section Adjusting the Instruction Scheduler diff --git a/gcc/genconfig.cc b/gcc/genconfig.cc index b7c6b48eec6..902c832cf5a 100644 --- a/gcc/genconfig.cc +++ b/gcc/genconfig.cc @@ -33,6 +33,7 @@ static int max_recog_operands; /* Largest operand number seen. */ static int max_dup_operands; /* Largest number of match_dup in any insn. */ static int max_clobbers_per_insn; static int have_cmove_flag; +static int have_ternary_cset_flag; static int have_cond_exec_flag; static int have_lo_sum_flag; static int have_rotate_flag; @@ -136,6 +137,12 @@ walk_insn_part (rtx part, int recog_p, int non_pc_set_src) && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) have_cmove_flag = 1; + else if (recog_p && non_pc_set_src + && GET_CODE (XEXP (part, 1)) == CONST_INT + && GET_CODE (XEXP (part, 2)) == IF_THEN_ELSE + && GET_CODE (XEXP (XEXP (part, 2), 1)) == CONST_INT + && GET_CODE (XEXP (XEXP (part, 2), 2)) == CONST_INT) + have_ternary_cset_flag = 1; break; case COND_EXEC: @@ -328,6 +335,11 @@ main (int argc, const char **argv) else printf ("#define HAVE_conditional_move 0\n"); + if (have_ternary_cset_flag) + printf ("#define HAVE_ternary_conditional_set 1\n"); + else + printf ("#define HAVE_ternary_conditional_set 0\n"); + if (have_cond_exec_flag) printf ("#define HAVE_conditional_execution 1\n"); else diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index eb8efb89a89..774dff21719 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -1830,6 +1830,42 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, return NULL_RTX; } +/* Emit a nested if-then-else insn. */ + +static rtx +noce_emit_ternary_cset (rtx x, rtx outer_cond, rtx inner_cond, + int a, int b, int c) +{ + rtx target; + machine_mode mode; + machine_mode orig_mode = GET_MODE (x); + + FOR_EACH_MODE_FROM (mode, orig_mode) + { + rtx inner_if_then_else = gen_rtx_IF_THEN_ELSE (mode, inner_cond, + GEN_INT (b), GEN_INT (c)); + rtx outer_if_then_else = gen_rtx_IF_THEN_ELSE (mode, outer_cond, + GEN_INT (a), + inner_if_then_else); + target = (mode == orig_mode) ? x : gen_reg_rtx (mode); + rtx set = gen_rtx_SET (target, outer_if_then_else); + start_sequence (); + rtx_insn *insn = emit_insn (set); + + if (recog_memoized (insn) >= 0) + { + rtx_insn *seq = get_insns (); + end_sequence (); + emit_insn (seq); + + return target; + } + } + + end_sequence (); + return NULL_RTX; +} + /* Try only simple constants and registers here. More complex cases are handled in noce_try_cmove_arith after noce_try_store_flag_arith has had a go at it. */ @@ -2987,6 +3023,43 @@ noce_try_bitop (struct noce_if_info *if_info) return TRUE; } +/* Try to find pattern "a < b ? -1 : (a > b ? 1 : 0);" and convert it to + a nested if-then-else insn. */ + +static int +noce_try_ternary_cset (struct noce_if_info *if_info) +{ + rtx outer_cond = NULL_RTX, inner_cond = NULL_RTX; + int int1 = 0, int2 = 0, int3 = 0; + + if (targetm.noce_ternary_cset_p (if_info, &outer_cond, &inner_cond, + &int1, &int2, &int3)) + { + start_sequence (); + rtx target = noce_emit_ternary_cset (if_info->x, outer_cond, inner_cond, + int1, int2, int3); + if (target) + { + rtx_insn *ifcvt_seq; + + if (target != if_info->x) + noce_emit_move_insn (if_info->x, target); + + ifcvt_seq = end_ifcvt_sequence (if_info); + if (!ifcvt_seq) + return false; + + emit_insn_before_setloc (ifcvt_seq, if_info->jump, + INSN_LOCATION (if_info->insn_a)); + if_info->transform_name = "noce_try_ternary_cset"; + return true; + } + + end_sequence (); + } + + return false; +} /* Similar to get_condition, only the resulting condition must be valid at JUMP, instead of at EARLIEST. @@ -3963,6 +4036,9 @@ noce_process_if_block (struct noce_if_info *if_info) if (HAVE_conditional_move && noce_try_cmove (if_info)) goto success; + if (HAVE_ternary_conditional_set + && noce_try_ternary_cset (if_info)) + goto success; if (! targetm.have_conditional_execution ()) { if (noce_try_addcc (if_info)) diff --git a/gcc/target.def b/gcc/target.def index 2a7fa68f83d..1b983bf852e 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3907,6 +3907,20 @@ candidate as a replacement for the if-convertible sequence described in\n\ bool, (rtx_insn *seq, struct noce_if_info *if_info), default_noce_conversion_profitable_p) +/* Return true if the if-then-else-join blocks can be converted to a nested\n\ +if-then-else insn. */ +DEFHOOK +(noce_ternary_cset_p, + "This hook returns true if the if-then-else-join blocks describled in\n\ +@code{if_info} can be converted to a ternary conditional set implemented by\n\ +a nested if-then-else insn. The @code{int1}, @code{int2} and @code{int3}\n\ +are three possible results of the nested if-then-else insn.\n\ +@code{outer_cond} and @code{inner_cond} are the conditions for outer and\n\ +if-then-else.", +bool, (struct noce_if_info *if_info, rtx *outer_cond, rtx *inner_cond, + int *int1, int *int2, int *int3), +default_noce_ternary_cset_p) + /* Return true if new_addr should be preferred over the existing address used by memref in insn. */ DEFHOOK diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index b15ae19bcb6..179324e3f0b 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -2673,4 +2673,17 @@ default_gcov_type_size (void) return TYPE_PRECISION (long_long_integer_type_node) > 32 ? 64 : 32; } +/* The default implementation of TARGET_NOCE_TERNARY_CSET_P. */ + +bool +default_noce_ternary_cset_p (struct noce_if_info *if_info ATTRIBUTE_UNUSED, + rtx *outer_cond ATTRIBUTE_UNUSED, + rtx *inner_cond ATTRIBUTE_UNUSED, + int *int1 ATTRIBUTE_UNUSED, + int *int2 ATTRIBUTE_UNUSED, + int *int3 ATTRIBUTE_UNUSED) +{ + return false; +} + #include "gt-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index ecce55ebe79..a58bc8ef6a6 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -296,5 +296,7 @@ extern rtx default_memtag_extract_tag (rtx, rtx); extern rtx default_memtag_untagged_pointer (rtx, rtx); extern HOST_WIDE_INT default_gcov_type_size (void); +extern bool default_noce_ternary_cset_p (struct noce_if_info *, rtx *, rtx *, + int *, int *, int *); #endif /* GCC_TARGHOOKS_H */