From 65d4b32dee2508f5bcdd999a132332cd46cf8a4d Mon Sep 17 00:00:00 2001 From: YunQiang Su <syq@gcc.gnu.org> Date: Sat, 30 Dec 2023 00:17:52 +0800 Subject: [PATCH] MIPS: Add pattern insqisi_extended and inshisi_extended 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. gcc/testsuite * gcc.target/mips/pr104914.c: New test. --- gcc/config/mips/mips.md | 24 +++++++++++++++++++++++ gcc/testsuite/gcc.target/mips/pr104914.c | 25 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 gcc/testsuite/gcc.target/mips/pr104914.c diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index e1762ce105bd..17dfcbd67223 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4419,6 +4419,30 @@ [(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") + (set_attr "perf_ratio" "1")]) + +(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") + (set_attr "perf_ratio" "1")]) (define_expand "insvmisalign<mode>" [(set (zero_extract:GPR (match_operand:BLK 0 "memory_operand") diff --git a/gcc/testsuite/gcc.target/mips/pr104914.c b/gcc/testsuite/gcc.target/mips/pr104914.c new file mode 100644 index 000000000000..5dd10e84c176 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr104914.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-mabi=64" } */ + +extern void abort (void); +extern void exit (int); + +NOMIPS16 int test (const unsigned char *buf) +{ + int val; + ((unsigned char*)&val)[0] = *buf++; + ((unsigned char*)&val)[1] = *buf++; + ((unsigned char*)&val)[2] = *buf++; + ((unsigned char*)&val)[3] = *buf++; + if(val > 0) + return 1; + else + return 0; +} + +int main () +{ + if (test("\xff\xff\xff\xff") != 0) + abort(); + exit(0); +} -- GitLab