public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] [RISC-V] Handle more cases in riscv_expand_conditional_move
@ 2023-08-07 15:06 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-08-07 15:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: Xiao Zeng, Raphael Zinsly

[-- Attachment #1: Type: text/plain, Size: 989 bytes --]


As I've mentioned in the main zicond thread, Ventana has had patches 
that support more cases by first emitting a suitable scc instruction 
essentially as a canonicalization step of the condition for zicond.

For example if we have

(set (target) (if_then_else (op (reg1) (reg2))
                             (true_value)
                             (false_value)))

The two register comparison isn't handled by zicond directly.  But we 
can generate something like this instead

(set (temp) (op (reg1) (reg2)))
(set (target) (if_then_else (op (temp) (const_int 0))
                             (true_value)
                             (false_value)

Then let the remaining code from Xiao handle the true_value/false_value 
to make sure it's zicond compatible.

This is primarily Raphael's work.  My involvement has been mostly to 
move it from its original location (in the .md file) into the expander 
function and fix minor problems with the FP case.


Committed to the trunk,

Jeff

[-- Attachment #2: P --]
[-- Type: text/plain, Size: 5323 bytes --]

commit 8ae83274d8cc60547e8c92a41a4f4716b045f57a
Author: Raphael Zinsly <rzinsly@ventanamicro.com>
Date:   Mon Aug 7 10:26:24 2023 -0400

    [committed] [RISC-V] Handle more cases in riscv_expand_conditional_move
    
    As I've mentioned in the main zicond thread, Ventana has had patches
    that support more cases by first emitting a suitable scc instruction
    essentially as a canonicalization step of the condition for zicond.
    
    For example if we have
    
    (set (target) (if_then_else (op (reg1) (reg2))
                                (true_value)
                                (false_value)))
    
    The two register comparison isn't handled by zicond directly.  But we
    can generate something like this instead
    
    (set (temp) (op (reg1) (reg2)))
    (set (target) (if_then_else (op (temp) (const_int 0))
                                (true_value)
                                (false_value)
    
    Then let the remaining code from Xiao handle the true_value/false_value
    to make sure it's zicond compatible.
    
    This is primarily Raphael's work.  My involvement has been mostly to
    move it from its original location (in the .md file) into the expander
    function and fix minor problems with the FP case.
    
    gcc/
            * config/riscv/riscv.cc (riscv_expand_int_scc): Add invert_ptr
            as an argument and pass it to riscv_emit_int_order_test.
            (riscv_expand_conditional_move): Handle cases where the condition
            is not EQ/NE or the second argument to the conditional is not
            (const_int 0).
            * config/riscv/riscv-protos.h (riscv_expand_int_scc): Update prototype.
    
            Co-authored-by: Jeff Law <jlaw@ventanamicro.com>

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 324991e2619..53b87cb28d3 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -103,7 +103,7 @@ extern const char *riscv_output_move (rtx, rtx);
 extern const char *riscv_output_return ();
 
 #ifdef RTX_CODE
-extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
+extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
 extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
 extern rtx riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7728cd34569..279304afc19 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3499,7 +3499,7 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
 /* CODE-compare OP0 and OP1.  Store the result in TARGET.  */
 
 void
-riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
+riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *invert_ptr)
 {
   riscv_extend_comparands (code, &op0, &op1);
   op0 = force_reg (word_mode, op0);
@@ -3510,7 +3510,7 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
       riscv_emit_binary (code, target, zie, const0_rtx);
     }
   else
-    riscv_emit_int_order_test (code, 0, target, op0, op1);
+    riscv_emit_int_order_test (code, invert_ptr, target, op0, op1);
 }
 
 /* Like riscv_expand_int_scc, but for floating-point comparisons.  */
@@ -3576,7 +3576,6 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
       return true;
     }
   else if (TARGET_ZICOND
-	   && (code == EQ || code == NE)
 	   && GET_MODE_CLASS (mode) == MODE_INT)
     {
       /* The comparison must be comparing WORD_MODE objects.   We must
@@ -3586,6 +3585,45 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
       if (GET_MODE (op0) != word_mode || GET_MODE (op1) != word_mode)
 	return false;
 
+      /* Canonicalize the comparison.  It must be an equality comparison
+	 against 0.  If it isn't, then emit an SCC instruction so that
+	 we can then use an equality comparison against zero.  */
+      if (!equality_operator (op, VOIDmode) || op1 != CONST0_RTX (mode))
+	{
+	  enum rtx_code new_code = NE;
+	  bool *invert_ptr = 0;
+	  bool invert = false;
+
+	  if (code == LE || code == GE)
+	    invert_ptr = &invert;
+
+	  /* Emit an scc like instruction into a temporary
+	     so that we can use an EQ/NE comparison.  */
+	  rtx tmp = gen_reg_rtx (mode);
+
+	  /* We can support both FP and integer conditional moves.  */
+	  if (INTEGRAL_MODE_P (GET_MODE (XEXP (op, 0))))
+	    riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
+	  else if (FLOAT_MODE_P (GET_MODE (XEXP (op, 0)))
+		   && fp_scc_comparison (op, GET_MODE (op)))
+	    riscv_expand_float_scc (tmp, code, op0, op1);
+	  else
+	    return false;
+
+	  /* If riscv_expand_int_scc inverts the condition, then it will
+	     flip the value of INVERT.  We need to know where so that
+	     we can adjust it for our needs.  */
+	  if (invert)
+	    new_code = EQ;
+
+	  op = gen_rtx_fmt_ee (new_code, mode, tmp, const0_rtx);
+
+	  /* We've generated a new comparison.  Update the local variables.  */
+	  code = GET_CODE (op);
+	  op0 = XEXP (op, 0);
+	  op1 = XEXP (op, 1);
+	}
+
       /* 0, reg or 0, imm */
       if (cons == CONST0_RTX (mode)
 	  && (REG_P (alt)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-07 15:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-07 15:06 [committed] [RISC-V] Handle more cases in riscv_expand_conditional_move Jeff Law

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).