From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lj1-x22e.google.com (mail-lj1-x22e.google.com [IPv6:2a00:1450:4864:20::22e]) by sourceware.org (Postfix) with ESMTPS id 3F16E384F6C8 for ; Wed, 23 Nov 2022 20:06:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3F16E384F6C8 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-lj1-x22e.google.com with SMTP id u2so22623622ljl.3 for ; Wed, 23 Nov 2022 12:06:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Lf92txxOz+50sy78UJ2sZZvPp9J6GSlJ+CvqpKN3I6s=; b=frqxTavW3FipTJqcwy8hY0tclP3mPDaHO15d3dCMavfZSx8W1QdNze5PUm5WS6Ewlx EYUJTqTEX8AYjwN/nrYKa2/XfGpGsdJuYCB1Dk9AecW55q/5CzLh6C9ZH6A6sShkzMxL PpXi7QZ04VzFobY3SDE8tDPk4HkFAjU33YrmuO8DinbXETBOePunpStOzmBybYlLQyjZ giRvGDFn7gB2KwO5/yzxlACxhTR0p5lzk5FVgK39KjokXAUX2TTBrqKJi32BBuZCXX6L PK1dG/loY4ZOmMhbTqboPrLDR0ZW6aFV9yTLbCRjDrdqMnNB4dAtwFaF3XmRQQ0zgq7b 4YFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Lf92txxOz+50sy78UJ2sZZvPp9J6GSlJ+CvqpKN3I6s=; b=D6HQIlXuyA45oHo6qnSUsHVjWynxiUDUwEaCeW3TDNReJO+BvNy1tEPO6h2NrQu2OS 0G8kbjw64p6Aq5bIqVVghq4OCDbTeGcy9JVuhuzl4fTBtuv1Bjm1CQXSDOEQe0zW5p/+ TT35reobw/uzClDvYuX1oSQP8w6eZLpIOPr0ueBZH7BJQHL2RkW5yKUklmZXQg3KLI9Z SYorWRn7qQPKsrvkc7TYaz6gc4cOh7JsMrsIpl+9coN7Avleksr85YTdrcEK82Cqsrcn iql4VWyKgfj3V7YXkUcisWo+I4V7C7Qn8vfCRv6FUyQRr0Q4MbOQ/JkAb+GpV2JxTxWi Qlmg== X-Gm-Message-State: ANoB5pnBKd0xCHeUiQGA3Z1oNGsSLKt8/a4/DnVGFXh/wg0mW/0wFP3r 1DtRIH15eFxUqyyaHN9Wp1Qo0WnAZC3ZGAScOqU= X-Google-Smtp-Source: AA0mqf5HzDx48OCp3OyN1xW4lEhsXBjyCDviSZyK/jKa4KCzQ7EQ2dvkGQ4I3HlAJTXNDPGMM8RRBX6NA65YPXGswko= X-Received: by 2002:a2e:9dcf:0:b0:279:70ee:571e with SMTP id x15-20020a2e9dcf000000b0027970ee571emr3021592ljj.249.1669234000776; Wed, 23 Nov 2022 12:06:40 -0800 (PST) MIME-Version: 1.0 References: <75fb4899-ceb2-e6a9-0dd4-577de9a8b976@linux.ibm.com> In-Reply-To: <75fb4899-ceb2-e6a9-0dd4-577de9a8b976@linux.ibm.com> From: Richard Biener Date: Wed, 23 Nov 2022 21:06:27 +0100 Message-ID: Subject: Re: [PATCH] Add a new conversion for conditional ternary set into ifcvt [PR106536] To: HAO CHEN GUI Cc: gcc-patches , Segher Boessenkool , David , "Kewen.Lin" , Peter Bergner Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,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 List-Id: On Wed, Nov 23, 2022 at 8:09 AM HAO CHEN GUI via Gcc-patches wrote: > > 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. Wouldn't we usually either add an optab or try to recog a canonical RTL form instead of adding a new target hook for things like this? > 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 */