Skip to content
This repository was archived by the owner on May 7, 2024. It is now read-only.

Commit 0c74449

Browse files
committed
Add automatic generation of pack*
This adds automatic generation of pack* instructions (pack, packu, packh) beyond zero-extension. This is implemented via a custom pass that a) reorganize chains of '[ix]or' to exhibit regular patterns; b) matches common pattern of pack/packu/packh and replace them by the appropriate instruction
1 parent ed5fe97 commit 0c74449

File tree

7 files changed

+1494
-2
lines changed

7 files changed

+1494
-2
lines changed

gcc/config.gcc

+1-1
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ pru-*-*)
525525
;;
526526
riscv*)
527527
cpu_type=riscv
528-
extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o"
528+
extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-gen-pack.o"
529529
extra_headers="rvintrin.h"
530530
d_target_objs="riscv-d.o"
531531
;;

gcc/config/riscv/bitmanip.md

+122
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,55 @@
8383

8484
;;; ??? pack
8585

86+
(define_insn "riscv_bitmanip_packsi"
87+
[(set (match_operand:SI 0 "register_operand" "=r")
88+
(ior:SI (and:SI (match_operand:SI 1 "register_operand" "r") (const_int 65280))
89+
(ashift:SI (match_operand:SI 2 "register_operand" "r") (const_int 16))))]
90+
"TARGET_ZBP"
91+
{ return TARGET_64BIT ? "packw\t%0,%1,%2" : "pack\t%0,%1,%2"; }
92+
[(set_attr "type" "bitmanip")
93+
(set_attr "length" "4")])
94+
95+
(define_insn "riscv_bitmanip_packdi"
96+
[(set (match_operand:DI 0 "register_operand" "=r")
97+
(ior:DI (and:SI (match_operand:DI 1 "register_operand" "r") (const_int 65280))
98+
(ashift:DI (match_operand:DI 2 "register_operand" "r") (const_int 32))))]
99+
"TARGET_ZBP && TARGET_64BIT"
100+
"pack\t%0,%1,%2"
101+
[(set_attr "type" "bitmanip")
102+
(set_attr "length" "4")])
103+
104+
(define_insn "riscv_bitmanip_packusi"
105+
[(set (match_operand:SI 0 "register_operand" "=r")
106+
(ior:SI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") (const_int 16))
107+
(and:SI (match_operand:SI 2 "register_operand" "r") (const_int 65280))))]
108+
"TARGET_ZBP"
109+
{ return TARGET_64BIT ? "packuw\t%0,%1,%2" : "packu\t%0,%1,%2"; }
110+
[(set_attr "type" "bitmanip")
111+
(set_attr "length" "4")])
112+
113+
(define_insn "riscv_bitmanip_packudi"
114+
[(set (match_operand:DI 0 "register_operand" "=r")
115+
(ior:DI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") (const_int 32))
116+
(and:DI (match_operand:SI 2 "register_operand" "r") (const_int 65280))))]
117+
"TARGET_ZBP && TARGET_64BIT"
118+
"packu\t%0,%1,%2"
119+
[(set_attr "type" "bitmanip")
120+
(set_attr "length" "4")])
121+
122+
(define_insn "riscv_bitmanip_packh<mode>"
123+
[(set (match_operand:X 0 "register_operand" "=r")
124+
(ior:X (and:X (match_operand:X 1 "register_operand" "r")
125+
(const_int 255))
126+
(ashift:X (and:X (match_operand:X 2 "register_operand" "r")
127+
(const_int 255))
128+
(const_int 8))))]
129+
"TARGET_ZBP"
130+
"packh\t%0,%1,%2"
131+
[(set_attr "type" "packh")
132+
(set_attr "length" "4")]
133+
)
134+
86135
(define_insn "*zero_extendhi<GPR:mode>2_bitmanip"
87136
[(set (match_operand:GPR 0 "register_operand" "=r,r")
88137
(zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
@@ -480,3 +529,76 @@
480529
l<SHORT:size>\t%0,%1"
481530
[(set_attr "type" "bitmanip")
482531
(set_attr "length" "4")])
532+
533+
;; By the time we reach this, gcc has changed
534+
;; `(a&0ff)<<8` into `(a<<8)&0xFF00`, despite the fact
535+
;; it's worse on RISC-V (need to set up the constant
536+
;; for the shift vs. andi/slli)
537+
;; Keep an easily recognizable subtree
538+
(define_insn_and_split "*extractB0toB1"
539+
[(set (match_operand:SI 0 "register_operand" "=r")
540+
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
541+
(const_int 8))
542+
(const_int 65280)))]
543+
"!TARGET_64BIT"
544+
"#"
545+
"!TARGET_64BIT"
546+
[(set (match_dup 0) (and:SI (match_dup 1) (const_int 255)))
547+
(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 8)))
548+
]
549+
""
550+
)
551+
552+
(define_insn_and_split "*extractB0toB2"
553+
[(set (match_operand:SI 0 "register_operand" "=r")
554+
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
555+
(const_int 16))
556+
(const_int 16711680)))]
557+
"!TARGET_64BIT"
558+
"#"
559+
"!TARGET_64BIT"
560+
[(set (match_dup 0) (and:SI (match_dup 1) (const_int 255)))
561+
(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))
562+
]
563+
""
564+
)
565+
566+
;; remove useless bswap after packh/packh/pack
567+
;; just permute the operands and remove the bswap
568+
(define_peephole2
569+
[(set (match_operand:SI 5 "register_operand")
570+
(ior:SI (and:SI (match_operand:SI 1 "register_operand")
571+
(const_int 255))
572+
(ashift:SI (and:SI (match_operand:SI 2 "register_operand")
573+
(const_int 255))
574+
(const_int 8))))
575+
(set (match_operand:SI 6 "register_operand")
576+
(ior:SI (and:SI (match_operand:SI 3 "register_operand")
577+
(const_int 255))
578+
(ashift:SI (and:SI (match_operand:SI 4 "register_operand")
579+
(const_int 255))
580+
(const_int 8))))
581+
(set (match_operand:SI 7 "register_operand")
582+
(ior:SI (and:SI (match_dup 6) (const_int 65280))
583+
(ashift:SI (match_dup 5) (const_int 16))))
584+
(set (match_operand:SI 0 "register_operand")
585+
(bswap:SI (match_dup 7)))]
586+
"TARGET_ZBP &&
587+
!TARGET_64BIT &&
588+
(REGNO (operands[5]) == REGNO (operands[0]) ||
589+
peep2_reg_dead_p (4, operands[5])) &&
590+
(REGNO (operands[6]) == REGNO (operands[0]) ||
591+
peep2_reg_dead_p (4, operands[6])) &&
592+
(REGNO (operands[7]) == REGNO (operands[0]) ||
593+
peep2_reg_dead_p (4, operands[7])) &&
594+
REGNO (operands[5]) != REGNO (operands[3]) &&
595+
REGNO (operands[5]) != REGNO (operands[4]) &&
596+
REGNO (operands[5]) != REGNO (operands[6])"
597+
[(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
598+
{
599+
emit_insn(gen_riscv_bitmanip_packhsi(operands[5], operands[2], operands[1]));
600+
emit_insn(gen_riscv_bitmanip_packhsi(operands[6], operands[4], operands[3]));
601+
emit_insn(gen_riscv_bitmanip_packsi(operands[0], operands[5], operands[6]));
602+
//printf("matched %d [packh/packh/pack/bswap = packh/packh/pack]\n", 0);
603+
DONE;
604+
})

0 commit comments

Comments
 (0)