https://gcc.gnu.org/g:7276d80fedab2d824bb0fcd0d7eca2b9138d963f
commit r17-3971-g7276d80fedab2d824bb0fcd0d7eca2b9138d963f Author: Andrew Stubbs <[email protected]> Date: Fri Jan 30 14:47:43 2026 +0000 amdgcn: Add vector ctz/clz insns 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. Diff: --- 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 d771e788e31d..b983d59343b5 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 edd5bf1f1d29..1dd14ec2a4cb 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -2733,6 +2733,19 @@ [(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 @@ } [(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 f95e7e555c9e..76eeb67cb0b7 100644 --- a/gcc/config/gcn/gcn.md +++ b/gcc/config/gcn/gcn.md @@ -287,17 +287,24 @@ ; 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 @@ (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")
