There were scalar ctz/clz instructions, but the vector counterparts were
missing.
gcc/ChangeLog:
* config/gcn/gcn-opts.h (TARGET_RDNA3_PLUS): New.
* config/gcn/gcn-valu.md (<expander><mode>2<exec>): New.
(<expander><mode>2): New.
(<expander><mode>2_natural): New.
* config/gcn/gcn.md (rnda): Add n3 and 3p values.
(enabled): Handle rdna n3 and 3p.
(mnemonic): Add clz and ctz.
(rdna_mnemonic): New code attribute.
---
gcc/config/gcn/gcn-opts.h | 1 +
gcc/config/gcn/gcn-valu.md | 74 ++++++++++++++++++++++++++++++++++++++
gcc/config/gcn/gcn.md | 19 ++++++++--
3 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/gcc/config/gcn/gcn-opts.h b/gcc/config/gcn/gcn-opts.h
index d771e788e31..b983d59343b 100644
--- a/gcc/config/gcn/gcn-opts.h
+++ b/gcc/config/gcn/gcn-opts.h
@@ -47,6 +47,7 @@ extern enum gcn_isa {
#define TARGET_RDNA2 (gcn_isa == ISA_RDNA2)
#define TARGET_RDNA2_PLUS (gcn_isa >= ISA_RDNA2 && gcn_isa < ISA_CDNA1)
#define TARGET_RDNA3 (gcn_isa == ISA_RDNA3)
+#define TARGET_RDNA3_PLUS (gcn_isa >= ISA_RDNA3 && gcn_isa < ISA_CDNA1)
#define TARGET_PACKED_WORK_ITEMS (TARGET_CDNA2_PLUS || TARGET_RDNA3)
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index edd5bf1f1d2..1dd14ec2a4c 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -2733,6 +2733,19 @@ (define_insn "<expander><mode>2<exec>"
[(set_attr "type" "vop1")
(set_attr "length" "8")])
+(define_insn "<expander><mode>2<exec>"
+ [(set (match_operand:V_SI 0 "gcn_valu_dst_operand")
+ (countzeros:V_SI
+ (match_operand:V_SI 1 "gcn_valu_src0_operand")))]
+ ""
+ {@ [cons: =0,1 ;attrs: length,rdna]
+ [v,vSv;4,n3] v_<mnemonic>0\t%0, %1
+ [v,B ;8,n3] ^
+ [v,vSv;4,3p] v_<rdna_mnemonic>0\t%0, %1
+ [v,B ;8,3p] ^
+ }
+ [(set_attr "type" "vop1")])
+
(define_insn "<expander><mode>3<exec>"
[(set (match_operand:V_INT_1REG 0 "gcn_valu_dst_operand" "= v,RD")
(bitop:V_INT_1REG
@@ -2995,6 +3008,67 @@ (define_insn_and_split "<expander><mode>3_exec"
}
[(set_attr "type" "mult")])
+;; }}}
+;; {{{ ALU VnDImode
+
+(define_expand "<expander><mode>2"
+ [(match_operand:V_DI 0 "register_operand")
+ (countzeros:V_DI)
+ (match_operand:V_DI 1 "gcn_alu_operand")]
+ ""
+ {
+ rtx tmp = gen_reg_rtx (<VnSI>mode);
+ emit_insn (gen_<expander><mode>2_natural (tmp, operands[1]));
+ emit_insn (gen_zero_extend<vnsi><mode>2 (operands[0], tmp));
+ DONE;
+ })
+
+;; The ctz/clz named patterns require operand[0] to match operand[1], for
+;; vectors only. This pattern provides a counterpart for the scalar insn,
+;; but cannot be the named pattern without an output conversion.
+(define_insn_and_split "<expander><mode>2_natural"
+ [(set (match_operand:<VnSI> 0 "register_operand" "=&v")
+ (truncate:<VnSI>
+ (countzeros:V_DI
+ (match_operand:V_DI 1 "gcn_alu_operand" "v"))))
+ (clobber (match_scratch:<VnSI> 2 "=&v"))
+ (clobber (match_scratch:DI 3 "=&cV"))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ enum {clz = 0, ctz = 1} op = <expander>;
+
+ /* "far/near" is "lo/hi" for clz, and "hi/lo" for ctz. */
+ rtx src_far = gcn_operand_part (<MODE>mode, operands[1], op);
+ rtx src_near = gcn_operand_part (<MODE>mode, operands[1], !op);
+ rtx res_far = operands[op ? 0 : 2];
+ rtx res_near = operands[op ? 2 : 0];
+ rtx vcc = operands[3];
+
+ /* Count the parts. */
+ emit_insn (gen_<expander><vnsi>2 (res_far, src_far));
+ emit_insn (gen_<expander><vnsi>2 (res_near, src_near));
+
+ /* Clamp the far-part to 32, to allow for the -1 result on all zeros. */
+ emit_insn (gen_umin<vnsi>3 (res_far, res_far,
+ gcn_vec_constant (<VnSI>mode, 32)));
+
+ /* Add 32 to the clamped far-part; we won't use this unless near-part is
+ all zeroes. */
+ emit_insn (gen_add<vnsi>3 (res_far, res_far,
+ gcn_vec_constant (<VnSI>mode, 32)));
+
+ /* Select which result is correct. */
+ emit_insn (gen_vec_cmp<vnsi>di (vcc, gen_rtx_NE (VOIDmode, 0, 0),
+ gcn_vec_constant (<VnSI>mode, 0),
+ src_near));
+ emit_insn (gen_vcond_mask_<vnsi>di (operands[0], res_near, res_far, vcc));
+ DONE;
+ }
+ [(set_attr "type" "vmult")])
+
;; }}}
;; {{{ Int unops
diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index f95e7e555c9..76eeb67cb0b 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -287,17 +287,24 @@ (define_attr "length" ""
; Disable alternatives that only apply to specific ISA variants.
(define_attr "cdna" "any,cdna2" (const_string "any"))
-(define_attr "rdna" "any,no,yes" (const_string "any"))
+(define_attr "rdna" "any,no,yes,n3,3p" (const_string "any"))
(define_attr "xnack" "na,off,on" (const_string "na"))
(define_attr "enabled" ""
- (cond [(and (eq_attr "rdna" "no")
+ (cond [
+ (and (eq_attr "rdna" "no")
(ne (symbol_ref "TARGET_RDNA2_PLUS") (const_int 0)))
(const_int 0)
(and (eq_attr "rdna" "yes")
(eq (symbol_ref "TARGET_RDNA2_PLUS") (const_int 0)))
(const_int 0)
+ (and (eq_attr "rdna" "n3")
+ (ne (symbol_ref "TARGET_RDNA3_PLUS") (const_int 0)))
+ (const_int 0)
+ (and (eq_attr "rdna" "3p")
+ (eq (symbol_ref "TARGET_RDNA3_PLUS") (const_int 0)))
+ (const_int 0)
(and (eq_attr "cdna" "cdna2")
(eq (symbol_ref "TARGET_CDNA2_PLUS") (const_int 0)))
(const_int 0)
@@ -371,7 +378,13 @@ (define_code_attr mnemonic
(umin "min%u")
(umax "max%u")
(not "not%B")
- (popcount "bcnt_u32%b")])
+ (popcount "bcnt_u32%b")
+ (clz "ffbh%u")
+ (ctz "ffbl%b")])
+
+(define_code_attr rdna_mnemonic
+ [(clz "clz_i32%u")
+ (ctz "ctz_i32%b")])
(define_code_attr bare_mnemonic
[(plus "add")
--
2.54.0