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

Commit 2e39046

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 c279948 commit 2e39046

File tree

7 files changed

+1494
-2
lines changed

7 files changed

+1494
-2
lines changed

gcc/config.gcc

Lines changed: 1 addition & 1 deletion
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

Lines changed: 122 additions & 0 deletions
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")))]
@@ -477,3 +526,76 @@
477526
l<SHORT:size>\t%0,%1"
478527
[(set_attr "type" "bitmanip")
479528
(set_attr "length" "4")])
529+
530+
;; By the time we reach this, gcc has changed
531+
;; `(a&0ff)<<8` into `(a<<8)&0xFF00`, despite the fact
532+
;; it's worse on RISC-V (need to set up the constant
533+
;; for the shift vs. andi/slli)
534+
;; Keep an easily recognizable subtree
535+
(define_insn_and_split "*extractB0toB1"
536+
[(set (match_operand:SI 0 "register_operand" "=r")
537+
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
538+
(const_int 8))
539+
(const_int 65280)))]
540+
"!TARGET_64BIT"
541+
"#"
542+
"!TARGET_64BIT"
543+
[(set (match_dup 0) (and:SI (match_dup 1) (const_int 255)))
544+
(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 8)))
545+
]
546+
""
547+
)
548+
549+
(define_insn_and_split "*extractB0toB2"
550+
[(set (match_operand:SI 0 "register_operand" "=r")
551+
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
552+
(const_int 16))
553+
(const_int 16711680)))]
554+
"!TARGET_64BIT"
555+
"#"
556+
"!TARGET_64BIT"
557+
[(set (match_dup 0) (and:SI (match_dup 1) (const_int 255)))
558+
(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))
559+
]
560+
""
561+
)
562+
563+
;; remove useless bswap after packh/packh/pack
564+
;; just permute the operands and remove the bswap
565+
(define_peephole2
566+
[(set (match_operand:SI 5 "register_operand")
567+
(ior:SI (and:SI (match_operand:SI 1 "register_operand")
568+
(const_int 255))
569+
(ashift:SI (and:SI (match_operand:SI 2 "register_operand")
570+
(const_int 255))
571+
(const_int 8))))
572+
(set (match_operand:SI 6 "register_operand")
573+
(ior:SI (and:SI (match_operand:SI 3 "register_operand")
574+
(const_int 255))
575+
(ashift:SI (and:SI (match_operand:SI 4 "register_operand")
576+
(const_int 255))
577+
(const_int 8))))
578+
(set (match_operand:SI 7 "register_operand")
579+
(ior:SI (and:SI (match_dup 6) (const_int 65280))
580+
(ashift:SI (match_dup 5) (const_int 16))))
581+
(set (match_operand:SI 0 "register_operand")
582+
(bswap:SI (match_dup 7)))]
583+
"TARGET_ZBP &&
584+
!TARGET_64BIT &&
585+
(REGNO (operands[5]) == REGNO (operands[0]) ||
586+
peep2_reg_dead_p (4, operands[5])) &&
587+
(REGNO (operands[6]) == REGNO (operands[0]) ||
588+
peep2_reg_dead_p (4, operands[6])) &&
589+
(REGNO (operands[7]) == REGNO (operands[0]) ||
590+
peep2_reg_dead_p (4, operands[7])) &&
591+
REGNO (operands[5]) != REGNO (operands[3]) &&
592+
REGNO (operands[5]) != REGNO (operands[4]) &&
593+
REGNO (operands[5]) != REGNO (operands[6])"
594+
[(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
595+
{
596+
emit_insn(gen_riscv_bitmanip_packhsi(operands[5], operands[2], operands[1]));
597+
emit_insn(gen_riscv_bitmanip_packhsi(operands[6], operands[4], operands[3]));
598+
emit_insn(gen_riscv_bitmanip_packsi(operands[0], operands[5], operands[6]));
599+
//printf("matched %d [packh/packh/pack/bswap = packh/packh/pack]\n", 0);
600+
DONE;
601+
})

0 commit comments

Comments
 (0)