diff mbox series

MIPS: Add pattern insqisi_extended and inshisi_extended

Message ID 20231230173639.2837936-1-syq@gcc.gnu.org
State New
Headers show
Series MIPS: Add pattern insqisi_extended and inshisi_extended | expand

Commit Message

YunQiang Su Dec. 30, 2023, 5:36 p.m. UTC
This match pattern allows combination (zero_extract:DI 8, 24, QI)
with an sign-extend to 32bit INS instruction on TARGET_64BIT.

For SI mode, if the sign-bit is modified by bitops, we will need a
sign-extend operation.  Since 32bit INS instruction can be sure that
result is sign-extended, and the QImode src register is safe for INS, too.

(insn 19 18 20 2 (set (zero_extract:DI (reg/v:DI 200 [ val ])
            (const_int 8 [0x8])
            (const_int 24 [0x18]))
        (subreg:DI (reg:QI 205) 0)) "../xx.c":7:29 -1
     (nil))
(insn 20 19 23 2 (set (reg/v:DI 200 [ val ])
        (sign_extend:DI (subreg:SI (reg/v:DI 200 [ val ]) 0))) "../xx.c":7:29 -1
     (nil))

Combine try to merge them to:

(insn 20 19 23 2 (set (reg/v:DI 200 [ val ])
        (sign_extend:DI (ior:SI (and:SI (subreg:SI (reg/v:DI 200 [ val ]) 0)
                    (const_int 16777215 [0xffffff]))
                (ashift:SI (subreg:SI (reg:QI 205 [ MEM[(const unsigned char *)buf_8(D) + 3B] ]) 0)
                    (const_int 24 [0x18]))))) "../xx.c":7:29 18 {*insv_extended}
     (expr_list:REG_DEAD (reg:QI 205 [ MEM[(const unsigned char *)buf_8(D) + 3B] ])
        (nil)))

And do similarly for 16/16 pair:
(insn 13 12 14 2 (set (zero_extract:DI (reg/v:DI 198 [ val ])
            (const_int 16 [0x10])
            (const_int 16 [0x10]))
        (subreg:DI (reg:HI 201 [ MEM[(const short unsigned int *)buf_6(D) + 2B] ]) 0)) "xx.c":5:30 286 {*insvdi}
     (expr_list:REG_DEAD (reg:HI 201 [ MEM[(const short unsigned int *)buf_6(D) + 2B] ])
        (nil)))
(insn 14 13 17 2 (set (reg/v:DI 198 [ val ])
        (sign_extend:DI (subreg:SI (reg/v:DI 198 [ val ]) 0))) "xx.c":5:30 241 {extendsidi2}
     (nil))
------------>
(insn 14 13 17 2 (set (reg/v:DI 198 [ val ])
        (sign_extend:DI (ior:SI (ashift:SI (subreg:SI (reg:HI 201 [ MEM[(const short unsigned int *)buf_6(D) + 2B] ]) 0)
                    (const_int 16 [0x10]))
                (zero_extend:SI (subreg:HI (reg/v:DI 198 [ val ]) 0))))) "xx.c":5:30 284 {*inshisi_extended}
     (expr_list:REG_DEAD (reg:HI 201 [ MEM[(const short unsigned int *)buf_6(D) + 2B] ])
        (nil)))

Let's accept these patterns, and set the cost to 1 instruction.

gcc

	PR rtl-optimization/104914
	* config/mips/mips.md (insqisi_extended): New patterns.
	(inshisi_extended): Ditto.
	* config/mips/mips.cc (mips_binary_cost): Set the cost of new
	  patters to COST_N_INSNS (1).
---
 gcc/config/mips/mips.cc | 43 +++++++++++++++++++++++++++++++++++++++++
 gcc/config/mips/mips.md | 22 +++++++++++++++++++++
 2 files changed, 65 insertions(+)
diff mbox series

Patch

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 9180dbbf843..225a9ee1fd4 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -4066,6 +4066,49 @@  mips_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
 {
   int cost;
 
+  rtx op0 = XEXP (x, 0);
+  rtx op1 = XEXP (x, 1);
+  rtx op00, op01, op10, op11;
+  if (GET_RTX_LENGTH (GET_CODE (op0)) > 0)
+    op00 = XEXP (op0, 0);
+  if (GET_RTX_LENGTH (GET_CODE (op0)) > 1)
+    op01 = XEXP (op0, 1);
+  if (GET_RTX_LENGTH (GET_CODE (op1)) > 0)
+    op10 = XEXP (op1, 0);
+  if (GET_RTX_LENGTH (GET_CODE (op1)) > 1)
+    op11 = XEXP (op1, 1);
+  /* On TARGET_64BIT, these 2 RTXs can be converted to INS instruction.
+     (ior:SI (and:SI (subreg:SI (reg/v:DI 200) 0)
+		(const_int 16777215 [0xffffff]))
+	     (ashift:SI (subreg:SI (reg:QI 205) 0)
+		(const_int 24 [0x18]))
+     )
+     (ior:SI (ashift:SI (subreg:SI (reg:HI 201) 0)
+		(const_int 16 [0x10]))
+	     (zero_extend:SI (subreg:HI (reg/v:DI 198) 0)))
+  */
+  if (TARGET_64BIT && ISA_HAS_EXT_INS
+      && GET_CODE (x) == IOR && GET_MODE (x) == SImode
+      && GET_MODE (op0) == SImode && GET_MODE (op1) == SImode
+      && ((GET_CODE (op0) == AND && GET_CODE (op1) == ASHIFT
+	     && SUBREG_P (op00) && GET_MODE (op00) == SImode
+		&& GET_MODE (SUBREG_REG (op00)) == DImode
+		&& SUBREG_BYTE (op00) == 0
+	     && GET_CODE (op01) == CONST_INT && INTVAL (op01) == 0xffffff
+	     && SUBREG_P (op10) && GET_MODE (op10) == SImode
+		&& GET_MODE (SUBREG_REG (op10)) == QImode
+		&& SUBREG_BYTE (op00) == 0
+	     && GET_CODE (op11) == CONST_INT && INTVAL (op11) == 0x18)
+	  || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND
+		&& SUBREG_P (op00) && GET_MODE (op00) == SImode
+		   && GET_MODE (SUBREG_REG (op00)) == HImode
+		   && SUBREG_BYTE (op00) == 0
+		&& GET_CODE (op01) == CONST_INT && INTVAL (op01) == 0x10
+		&& SUBREG_P (op10) && GET_MODE (op10) == HImode
+			&& GET_MODE (SUBREG_REG (op10)) == DImode
+			&& SUBREG_BYTE (op10) == 0)))
+    return COSTS_N_INSNS (1);
+
   if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
     cost = double_cost;
   else
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 0666310734e..a4c6d630aeb 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -4415,6 +4415,28 @@  (define_insn "*extzv_truncsi_exts"
   [(set_attr "type"     "arith")
    (set_attr "mode"     "SI")])
 
+(define_insn "*insqisi_extended"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+    (sign_extend:DI
+      (ior:SI (and:SI (subreg:SI (match_dup 0) 0)
+		(const_int 16777215))
+	      (ashift:SI
+		(subreg:SI (match_operand:QI 1 "register_operand" "d") 0)
+		(const_int 24)))))]
+  "TARGET_64BIT && !TARGET_MIPS16 && ISA_HAS_EXT_INS"
+  "ins\t%0,%1,24,8"
+  [(set_attr "mode" "SI")])
+
+(define_insn "*inshisi_extended"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+    (sign_extend:DI
+      (ior:SI
+	(ashift:SI (subreg:SI (match_operand:HI 1 "register_operand" "d") 0)
+	  (const_int 16))
+	(zero_extend:SI (subreg:HI (match_dup 0) 0)))))]
+  "TARGET_64BIT && !TARGET_MIPS16 && ISA_HAS_EXT_INS"
+  "ins\t%0,%1,16,16"
+  [(set_attr "mode" "SI")])
 
 (define_expand "insvmisalign<mode>"
   [(set (zero_extract:GPR (match_operand:BLK 0 "memory_operand")