https://gcc.gnu.org/g:8e6a558d4123185962a54de53b104310e248880d
commit r15-977-g8e6a558d4123185962a54de53b104310e248880d Author: Lingling Kong <lingling.k...@intel.com> Date: Mon Jun 3 11:05:41 2024 +0800 [APX NF] Support APX NF for left shift insns gcc/ChangeLog: * config/i386/i386.md (*ashl<mode>3_1<nf_name>): New define_insn. (*ashlhi3_1<nf_name>): Ditto. (*ashlqi3_1<nf_name>): Ditto. * config/i386/sse.md: New define_split. Diff: --- gcc/config/i386/i386.md | 96 +++++++++++++++++++++++++++++++++++-------------- gcc/config/i386/sse.md | 13 +++++++ 2 files changed, 83 insertions(+), 26 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 5653f5ce123..8063cb576f5 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -15013,17 +15013,22 @@ [(set_attr "type" "ishiftx") (set_attr "mode" "<MODE>")]) -(define_insn "*ashl<mode>3_1" +(define_insn "*ashl<mode>3_1<nf_name>" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,?k,r") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,l,rm,k,rm") - (match_operand:QI 2 "nonmemory_operand" "c<S>,M,r,<KS>,c<S>"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c<S>,M,r,<KS>,c<S>")))] + "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands, TARGET_APX_NDD) + && <nf_condition>" { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && <nf_applied>) + return "%{nf%} sal{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_ISHIFTX: case TYPE_MSKLOG: return "#"; @@ -15031,7 +15036,7 @@ case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{<imodesuffix>}\t%0, %0"; + return "<nf_prefix>add{<imodesuffix>}\t%0, %0"; default: if (operands[2] == const1_rtx @@ -15039,11 +15044,11 @@ /* For NDD form instructions related to TARGET_SHIFT1, the $1 immediate do not need to be omitted as assembler will map it to use shorter encoding. */ - && !use_ndd) + && !use_ndd && !<nf_applied>) return "sal{<imodesuffix>}\t%0"; else - return use_ndd ? "sal{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" - : "sal{<imodesuffix>}\t{%2, %0|%0, %2}"; + return use_ndd ? "<nf_prefix>sal{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" + : "<nf_prefix>sal{<imodesuffix>}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,bmi2,avx512bw,apx_ndd") @@ -15074,6 +15079,17 @@ (set_attr "mode" "<MODE>")]) ;; Convert shift to the shiftx pattern to avoid flags dependency. +;; For NF/NDD doesn't support shift count as r, it just support c<S>, +;; and it has no flag. +(define_split + [(set (match_operand:SWI48 0 "register_operand") + (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:QI 2 "register_operand")))] + "TARGET_BMI2 && reload_completed" + [(set (match_dup 0) + (ashift:SWI48 (match_dup 1) (match_dup 2)))] + "operands[2] = gen_lowpart (<MODE>mode, operands[2]);") + (define_split [(set (match_operand:SWI48 0 "register_operand") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -15160,32 +15176,37 @@ (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] "operands[2] = gen_lowpart (SImode, operands[2]);") -(define_insn "*ashlhi3_1" +(define_insn "*ashlhi3_1<nf_name>" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,Yp,?k,r") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l,k,rm") - (match_operand:QI 2 "nonmemory_operand" "cI,M,Ww,cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, HImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI,M,Ww,cI")))] + "ix86_binary_operator_ok (ASHIFT, HImode, operands, TARGET_APX_NDD) + && <nf_condition>" { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && <nf_applied>) + return "%{nf%} sal{w}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_MSKLOG: return "#"; case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; + return "<nf_prefix>add{w}\t%0, %0"; default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !<nf_applied>) return "sal{w}\t%0"; else - return use_ndd ? "sal{w}\t{%2, %1, %0|%0, %1, %2}" - : "sal{w}\t{%2, %0|%0, %2}"; + return use_ndd ? "<nf_prefix>sal{w}\t{%2, %1, %0|%0, %1, %2}" + : "<nf_prefix>sal{w}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,avx512f,apx_ndd") @@ -15213,31 +15234,36 @@ (const_string "*"))) (set_attr "mode" "HI,SI,HI,HI")]) -(define_insn "*ashlqi3_1" +(define_insn "*ashlqi3_1<nf_name>" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,Yp,?k,r") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l,k,rm") - (match_operand:QI 2 "nonmemory_operand" "cI,cI,M,Wb,cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI,cI,M,Wb,cI")))] + "ix86_binary_operator_ok (ASHIFT, QImode, operands, TARGET_APX_NDD) + && <nf_condition>" { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && <nf_applied>) + return "%{nf%} sal{b}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_MSKLOG: return "#"; case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); if (REG_P (operands[1]) && !ANY_QI_REGNO_P (REGNO (operands[1]))) - return "add{l}\t%k0, %k0"; + return "<nf_prefix>add{l}\t%k0, %k0"; else - return "add{b}\t%0, %0"; + return "<nf_prefix>add{b}\t%0, %0"; default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !<nf_applied>) { if (get_attr_mode (insn) == MODE_SI) return "sal{l}\t%k0"; @@ -15247,10 +15273,10 @@ else { if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%2, %k0|%k0, %2}"; + return "<nf_prefix>sal{l}\t{%2, %k0|%k0, %2}"; else - return use_ndd ? "sal{b}\t{%2, %1, %0|%0, %1, %2}" - : "sal{b}\t{%2, %0|%0, %2}"; + return use_ndd ? "<nf_prefix>sal{b}\t{%2, %1, %0|%0, %1, %2}" + : "<nf_prefix>sal{b}\t{%2, %0|%0, %2}"; } } } @@ -15353,6 +15379,24 @@ operands[2] = GEN_INT (1 << INTVAL (operands[2])); }) +(define_split + [(set (match_operand:SWI 0 "general_reg_operand") + (ashift:SWI (match_operand:SWI 1 "index_reg_operand") + (match_operand 2 "const_0_to_3_operand")))] + "reload_completed + && REGNO (operands[0]) != REGNO (operands[1]) + && !TARGET_APX_NDD" + [(set (match_dup 0) + (mult:<LEAMODE> (match_dup 1) (match_dup 2)))] +{ + if (<MODE>mode != <LEAMODE>mode) + { + operands[0] = gen_lowpart (<LEAMODE>mode, operands[0]); + operands[1] = gen_lowpart (<LEAMODE>mode, operands[1]); + } + operands[2] = GEN_INT (1 << INTVAL (operands[2])); +}) + ;; Convert ashift to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "general_reg_operand") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index ca560b639b8..4ad3917f5ce 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -2150,6 +2150,19 @@ (set_attr "prefix" "vex") (set_attr "mode" "<MODE>")]) +(define_split + [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") + (any_lshift:SWI1248_AVX512BW + (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand") + (match_operand 2 "const_int_operand")))] + "TARGET_AVX512F && reload_completed" + [(parallel + [(set (match_dup 0) + (any_lshift:SWI1248_AVX512BW + (match_dup 1) + (match_dup 2))) + (unspec [(const_int 0)] UNSPEC_MASKOP)])]) + (define_split [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") (any_lshift:SWI1248_AVX512BW