]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition...
authorXiao Zeng <zengxiao@eswincomputing.com>
Fri, 4 Aug 2023 21:23:56 +0000 (17:23 -0400)
committerJeff Law <jeffreyalaw@gmail.com>
Fri, 4 Aug 2023 21:25:30 +0000 (17:25 -0400)
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
more Zicond patterns.  Fix whitespace typo.
(riscv_rtx_costs): Remove accidental code duplication.

Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
gcc/config/riscv/riscv.cc

index 8b7256108157aa12234cc9a04ec95b99b1a3c410..7728cd34569103736e36d5c1819125aa7d7af16b 100644 (file)
@@ -2522,20 +2522,6 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
          *total = COSTS_N_INSNS (1);
          return true;
        }
-      else if (TARGET_ZICOND
-              && outer_code == SET
-              && ((GET_CODE (XEXP (x, 1)) == REG
-                   && XEXP (x, 2) == CONST0_RTX (GET_MODE (XEXP (x, 1))))
-                  || (GET_CODE (XEXP (x, 2)) == REG
-                      && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 2))))
-                  || (GET_CODE (XEXP (x, 1)) == REG
-                      && rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 0), 0)))
-                  || (GET_CODE (XEXP (x, 1)) == REG
-                      && rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0)))))
-       {
-         *total = COSTS_N_INSNS (1);
-         return true;
-       }
       else if (LABEL_REF_P (XEXP (x, 1)) && XEXP (x, 2) == pc_rtx)
        {
          if (equality_operator (XEXP (x, 0), mode)
@@ -3583,7 +3569,7 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
       /* The expander is a bit loose in its specification of the true
         arm of the conditional move.  That allows us to support more
         cases for extensions which are more general than SFB.  But
-       does mean we need to force CONS into a register at this point.  */
+        does mean we need to force CONS into a register at this point.  */
       cons = force_reg (GET_MODE (dest), cons);
       emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
                                                          cond, cons, alt)));
@@ -3628,6 +3614,40 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
          riscv_emit_binary (PLUS, dest, dest, cons);
          return true;
        }
+      /* imm, reg  */
+      else if (CONST_INT_P (cons) && cons != CONST0_RTX (mode) && REG_P (alt))
+       {
+         /* Optimize for register value of 0.  */
+         if (code == NE && rtx_equal_p (op0, alt) && op1 == CONST0_RTX (mode))
+           {
+             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;
+           }
+
+         riscv_emit_int_compare (&code, &op0, &op1, true);
+         rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+
+         rtx temp1 = gen_reg_rtx (mode);
+         rtx temp2 = gen_int_mode (-1 * INTVAL (cons), mode);
+
+         /* TEMP2 might not fit into a signed 12 bit immediate suitable
+            for an addi instruction.  If that's the case, force it into
+            a register.  */
+         if (!SMALL_OPERAND (INTVAL (temp2)))
+           temp2 = force_reg (mode, temp2);
+
+         riscv_emit_binary (PLUS, temp1, alt, temp2);
+         emit_insn (gen_rtx_SET (dest,
+                                 gen_rtx_IF_THEN_ELSE (mode, cond,
+                                                       CONST0_RTX (mode),
+                                                       temp1)));
+         riscv_emit_binary (PLUS, dest, dest, cons);
+         return true;
+       }
       /* reg, 0 or imm, 0  */
       else if ((REG_P (cons)
                || (CONST_INT_P (cons) && cons != CONST0_RTX (mode)))
@@ -3640,6 +3660,73 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
                                                              cons, alt)));
          return true;
        }
+      /* reg, imm  */
+      else if (REG_P (cons) && CONST_INT_P (alt) && alt != CONST0_RTX (mode))
+       {
+         /* Optimize for register value of 0.  */
+         if (code == EQ && rtx_equal_p (op0, cons) && op1 == CONST0_RTX (mode))
+           {
+             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;
+           }
+
+         riscv_emit_int_compare (&code, &op0, &op1, true);
+         rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+
+         rtx temp1 = gen_reg_rtx (mode);
+         rtx temp2 = gen_int_mode (-1 * INTVAL (alt), mode);
+
+         /* TEMP2 might not fit into a signed 12 bit immediate suitable
+            for an addi instruction.  If that's the case, force it into
+            a register.  */
+         if (!SMALL_OPERAND (INTVAL (temp2)))
+           temp2 = force_reg (mode, temp2);
+
+         riscv_emit_binary (PLUS, temp1, cons, temp2);
+         emit_insn (gen_rtx_SET (dest,
+                                 gen_rtx_IF_THEN_ELSE (mode, cond,
+                                                       temp1,
+                                                       CONST0_RTX (mode))));
+         riscv_emit_binary (PLUS, dest, dest, alt);
+         return true;
+       }
+      /* reg, reg  */
+      else if (REG_P (cons) && REG_P (alt))
+       {
+         if ((code == EQ && rtx_equal_p (cons, op0))
+              || (code == NE && rtx_equal_p (alt, op0)))
+           {
+             rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+             if (!rtx_equal_p (cons, op0))
+               std::swap (alt, cons);
+             alt = force_reg (mode, alt);
+             emit_insn (gen_rtx_SET (dest,
+                                     gen_rtx_IF_THEN_ELSE (mode, cond,
+                                                           cons, alt)));
+             return true;
+           }
+
+         rtx reg1 = gen_reg_rtx (mode);
+         rtx reg2 = gen_reg_rtx (mode);
+         riscv_emit_int_compare (&code, &op0, &op1, true);
+         rtx cond1 = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+         rtx cond2 = gen_rtx_fmt_ee (code == NE ? EQ : NE,
+                                     GET_MODE (op0), op0, op1);
+         emit_insn (gen_rtx_SET (reg2,
+                                 gen_rtx_IF_THEN_ELSE (mode, cond2,
+                                                       CONST0_RTX (mode),
+                                                       cons)));
+         emit_insn (gen_rtx_SET (reg1,
+                                 gen_rtx_IF_THEN_ELSE (mode, cond1,
+                                                       CONST0_RTX (mode),
+                                                       alt)));
+         riscv_emit_binary (IOR, dest, reg1, reg2);
+         return true;
+       }
     }
 
   return false;