2021-09-23 Kito Cheng <kito.ch...@sifive.com>

gcc/ChangeLog:

        * config/riscv/riscv.c (riscv_extend_cost): Handle cost model
        for zba extension.
        (riscv_rtx_costs): Ditto.
---
 gcc/config/riscv/riscv.c | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 576960bb37c..cc58b7041ac 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -1702,6 +1702,10 @@ riscv_extend_cost (rtx op, bool unsigned_p)
     /* We can use ANDI.  */
     return COSTS_N_INSNS (1);
 
+  /* ZBA provide zext.w.  */
+  if (TARGET_ZBA && TARGET_64BIT && unsigned_p && GET_MODE (op) == SImode)
+    return COSTS_N_INSNS (1);
+
   if (!unsigned_p && GET_MODE (op) == SImode)
     /* We can use SEXT.W.  */
     return COSTS_N_INSNS (1);
@@ -1775,6 +1779,21 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
       return false;
 
     case AND:
+      /* slli.uw pattern for zba.  */
+      if (TARGET_ZBA && TARGET_64BIT && mode == DImode
+         && GET_CODE (XEXP (x, 0)) == ASHIFT)
+       {
+         rtx and_rhs = XEXP (x, 1);
+         rtx ashift_lhs = XEXP (XEXP (x, 0), 0);
+         rtx ashift_rhs = XEXP (XEXP (x, 0), 1);
+         if (REG_P (ashift_lhs)
+             && CONST_INT_P (ashift_rhs)
+             && CONST_INT_P (and_rhs)
+             && ((INTVAL (and_rhs) >> INTVAL (ashift_rhs)) == 0xffffffff))
+           *total = COSTS_N_INSNS (1);
+           return true;
+       }
+      gcc_fallthrough ();
     case IOR:
     case XOR:
       /* Double-word operations use two single-word operations.  */
@@ -1866,6 +1885,68 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
 
     case MINUS:
     case PLUS:
+      /* add.uw pattern for zba.  */
+      if (TARGET_ZBA
+         && (TARGET_64BIT && (mode == DImode))
+         && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+         && REG_P (XEXP (XEXP (x, 0), 0))
+         && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode)
+       {
+         *total = COSTS_N_INSNS (1);
+         return true;
+       }
+      /* shNadd pattern for zba.  */
+      if (TARGET_ZBA
+         && ((!TARGET_64BIT && (mode == SImode)) ||
+             (TARGET_64BIT && (mode == DImode)))
+         && (GET_CODE (XEXP (x, 0)) == ASHIFT)
+         && REG_P (XEXP (XEXP (x, 0), 0))
+         && CONST_INT_P (XEXP (XEXP (x, 0), 0))
+         && IN_RANGE (INTVAL (XEXP (XEXP (x, 0), 0)), 1, 3))
+       {
+         *total = COSTS_N_INSNS (1);
+         return true;
+       }
+      /* shNadd.uw pattern for zba.
+        [(set (match_operand:DI 0 "register_operand" "=r")
+              (plus:DI
+                (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+                                   (match_operand:QI 2 "immediate_operand" 
"I"))
+                        (match_operand 3 "immediate_operand" ""))
+                (match_operand:DI 4 "register_operand" "r")))]
+        "TARGET_64BIT && TARGET_ZBA
+         && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)
+         && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
+      */
+      if (TARGET_ZBA
+         && (TARGET_64BIT && (mode == DImode))
+         && (GET_CODE (XEXP (x, 0)) == AND)
+         && (REG_P (XEXP (x, 1))))
+       {
+         do {
+           rtx and_lhs = XEXP (XEXP (x, 0), 0);
+           rtx and_rhs = XEXP (XEXP (x, 0), 1);
+           if (GET_CODE (and_lhs) != ASHIFT)
+             break;
+           if (!CONST_INT_P (and_rhs))
+             break;
+
+           rtx ashift_lhs = XEXP (and_lhs, 0);
+           rtx ashift_rhs = XEXP (and_lhs, 1);
+
+           if (!CONST_INT_P (ashift_rhs)
+               || !IN_RANGE (INTVAL (ashift_rhs), 1, 3))
+             break;
+
+           if (CONST_INT_P (and_rhs)
+               && ((INTVAL (and_rhs) >> INTVAL (ashift_rhs)) == 0xffffffff))
+             {
+               *total = COSTS_N_INSNS (1);
+               return true;
+             }
+         } while (false);
+       }
+
       if (float_mode_p)
        *total = tune_param->fp_add[mode == DFmode];
       else
-- 
2.33.0

Reply via email to