public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jeff Law <jeffreyalaw@gmail.com>
To: Xiao Zeng <zengxiao@eswincomputing.com>
Cc: gcc-patches@gcc.gnu.org, research_trasio@irq.a4lg.com,
	kito.cheng@gmail.com, zhengyu@eswincomputing.com,
	eri-sw-toolchain@eswincomputing.com
Subject: Re: [PATCH V2] [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
Date: Tue, 1 Aug 2023 00:06:45 -0600	[thread overview]
Message-ID: <856935c9-9252-f6c5-a950-4b43a8c156fa@gmail.com> (raw)
In-Reply-To: <20230729091308.29792-1-zengxiao@eswincomputing.com>



On 7/29/23 03:13, Xiao Zeng wrote:
> This patch recognizes Zicond patterns when the select pattern
> with condition eq or neq to 0 (using eq as an example), namely:
> 
> 1 rd = (rs2 == 0) ? non-imm : 0
> 2 rd = (rs2 == 0) ? non-imm : non-imm
> 3 rd = (rs2 == 0) ? reg : non-imm
> 4 rd = (rs2 == 0) ? reg : reg
> 
> gcc/ChangeLog:
> 
>          * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize
>          Zicond patterns
>          * config/riscv/riscv.md: Recognize Zicond patterns through mov<mode>cc
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test.
>          * gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test.
>          * gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test.
>          * gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test.
> ---
>   gcc/config/riscv/riscv.cc                     | 144 ++++++++++++++++++
>   gcc/config/riscv/riscv.md                     |   4 +-
>   .../zicond-primitiveSemantics_return_0_imm.c  |  65 ++++++++
>   ...zicond-primitiveSemantics_return_imm_imm.c |  73 +++++++++
>   ...zicond-primitiveSemantics_return_imm_reg.c |  65 ++++++++
>   ...zicond-primitiveSemantics_return_reg_reg.c |  65 ++++++++
>   6 files changed, 414 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
>   create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
>   create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
>   create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
> 
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 941ea25e1f2..6ac39f63dd7 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -3516,6 +3516,150 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
>   							  cond, cons, alt)));
>         return true;
>       }
> +  else if (TARGET_ZICOND
> +           && (code == EQ || code == NE)
> +           && GET_MODE_CLASS (mode) == MODE_INT)
> +    {
> +      need_eq_ne_p = true;
> +      /* 0 + imm  */
> +      if (GET_CODE (cons) == CONST_INT && cons == const0_rtx
> +          && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
A couple nits.  Rather than test the GET_CODE (object) == CONST_INT, 
instead use CONST_INT_P (object).

Rather than using const0_rtx, use CONST0_RTX (mode).  That makes it more 
general.



> +        {
> +          riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
Might as well use "true" rather than "need_eq_ne_p" here and for the 
other calls in your new code.

> +      /* imm + imm  */
> +      else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
> +               && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
So same comments on using CONST_INT_P and CONST0_RTX
> +        {
> +          riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> +          rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +          rtx reg = gen_reg_rtx (mode);
> +          rtx temp = GEN_INT (INTVAL (alt) - INTVAL (cons));
> +          emit_insn (gen_rtx_SET (reg, temp));
Use force_reg here rather than directly emitting the insn to initialize 
"reg".  What you're doing works when the difference is small but will 
not work when the difference does not fit into a signed 12bit value.

> +      /* imm + reg  */
> +      else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
> +               && GET_CODE (alt) == REG)
Same comments about CONST_INT_P and CONST0_RTX.  And instead of using 
GET_CODE (object) == REG, use REG_P (object).


> +        {
> +          /* Optimize for register value of 0.  */
> +          if (op0 == alt && op1 == const0_rtx)
> +            {
> +              rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +              cons = force_reg (mode, cons);
> +              emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond,
> +                                                                  cons, alt)));
> +              return true;
> +            }
Isn't this only valid for NE?  Also use CONST0_RTX in that test.


> +          /* Handle the special situation of: -2048 == INTVAL (alt)
> +             to avoid failure due to an unrecognized insn. Let the costing
> +             model determine if the conditional move sequence is better
> +             than the branching sequence.  */
> +          if (-2048 == INTVAL (cons))
So instead of checking for explicit values, we have SMALL_OPERAND to do 
it for us.  Also note that for !SMALL_OPERAND we can just force the 
value into a register using "force_reg" and all the right things will 
happen.

So just add something like this to your original code:

   if (!SMALL_OPERAND (INTVAL (cons))
     cons = force_reg (mode, cons);

That will result in CONS being either a simple integer constant (when it 
is suitable for addi) or a register (all other cases).  At that point 
you can use it in an arithmetic instruction.



> +      /* imm + 0  */
> +      else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
> +               && GET_CODE (alt) == CONST_INT && alt == const0_rtx)
> +        {
> +          riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> +          rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +          cons = force_reg (mode, cons);
> +          emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond,
> +                                                              cons, alt)));
> +          return true;
> +        }
> +      /* reg + imm  */
> +      else if (GET_CODE (cons) == REG
> +               && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
> +        {
> +          /* Optimize for register value of 0.  */
> +          if (op0 == cons && op1 == const0_rtx)
> +            {
> +              rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +              alt = force_reg (mode, alt);
> +              emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond,
> +                                                                  cons, alt)));
> +              return true;
> +            }
So in this case isn't it only valid for EQ?

> +          if (-2048 == INTVAL (alt))
Similar comment as above.  When ALT doesn't fit into a SMALL_OPERAND_P, 
just force it into a register.

> +      /* reg + reg  */
> +      else if (GET_CODE (cons) == REG && GET_CODE (alt) == REG)
> +        {
> +          /* Optimize for op0 == cons && op1 == const0_rtx.  */
> +          if (op0 == cons && op1 == const0_rtx)
> +            {
> +              rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +              emit_insn (gen_rtx_SET (dest,
> +                                      gen_rtx_IF_THEN_ELSE (mode, cond,
> +                                                            CONST0_RTX (mode),
> +                                                            alt)));
> +              return true;
> +            }
> +          /* Optimize for op0 == alt && op1 == const0_rtx.  */
> +          if (op0 == alt && op1 == const0_rtx)
> +            {
> +              rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> +              emit_insn (gen_rtx_SET (dest,
> +                                      gen_rtx_IF_THEN_ELSE (mode, cond, cons,
> +                                                            CONST0_RTX (mode))));
> +              return true;
> +            }
I suspect we need some testing of the code in the two sequences above. 
I'd bet one is only valid for EQ and the other for NE.

It's improving considerably.

WRT costing.  I'm still seeing some weirdness in how conditional moves 
are being costed from the if-converter.  I think your patch that set the 
cost to COSTS_N_INSNS (0) was just working around a deeper bug in the 
costing code.  I'm still trying to figure out the best way to clean that up.


jeff

  reply	other threads:[~2023-08-01  6:06 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-29  9:13 Xiao Zeng
2023-08-01  6:06 ` Jeff Law [this message]
2023-08-02  1:39   ` Xiao Zeng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=856935c9-9252-f6c5-a950-4b43a8c156fa@gmail.com \
    --to=jeffreyalaw@gmail.com \
    --cc=eri-sw-toolchain@eswincomputing.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=kito.cheng@gmail.com \
    --cc=research_trasio@irq.a4lg.com \
    --cc=zengxiao@eswincomputing.com \
    --cc=zhengyu@eswincomputing.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).