Hello! This patch cleans and improves mask op patterns a bit. The patch uses insn mode attribute to control emission of word-mode operations and macroizes a couple of patterns.
No functional changes. 2016-11-23 Uros Bizjak <ubiz...@gmail.com> * gcc.target/config/i386.md (*movqi_internal): Calculate mode attribute of alternatives 7,8,9 depending on TARGET_AVX512DQ. <TYPE_MSKMOV>: Emit kmovw for MODE_HI insn mode attribute. (*k<logic><mode>): Calculate mode attribute depending on TARGET_AVX512DQ. Emit k<logic>w for MODE_HI insn mode attribute. (*andqi_1): Calculate mode attribute of alternative 3 depending on TARGET_AVX512DQ. Emit kandw for MODE_HI insn mode attribute. (kandn<mode>): Calculate mode attribute of alternative 2 depending on TARGET_AVX512DQ. Emit kandnw for MODE_HI insn mode attribute. (kxnor<mode>): Merge insn patterns using SWI1248_AVX512BW mode iterator. Calculate mode attribute of alternative 1 depending on TARGET_AVX512DQ. Emit kxnorw for MODE_HI insn mode attribute. (*one_cmplqi2_1): Calculate mode attribute of alternative 2 depending on TARGET_AVX512DQ. Emit knotw for MODE_HI insn mode attribute. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 242765) +++ config/i386/i386.md (working copy) @@ -970,6 +970,11 @@ (define_mode_iterator SWI1248_AVX512BWDQ [(QI "TARGET_AVX512DQ") HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")]) +;; All integer modes with AVX512BW, where HImode operation +;; can be used instead of QImode. +(define_mode_iterator SWI1248_AVX512BW + [QI HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")]) + ;; All integer modes without QImode. (define_mode_iterator SWI248x [HI SI DI]) @@ -2574,11 +2582,15 @@ (define_insn "*movqi_internal" [(set (match_operand:QI 0 "nonimmediate_operand" - "=q,q ,q ,r,r ,?r,m ,k,k,r ,m,k") + "=q,q ,q ,r,r ,?r,m ,k,k,r,m,k") (match_operand:QI 1 "general_operand" - "q ,qn,qm,q,rn,qm,qn,r ,k,k,k,m"))] + "q ,qn,qm,q,rn,qm,qn,r,k,k,k,m"))] "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { + static char buf[128]; + const char *ops; + const char *suffix; + switch (get_attr_type (insn)) { case TYPE_IMOVX: @@ -2588,24 +2600,33 @@ case TYPE_MSKMOV: switch (which_alternative) { - case 7: return TARGET_AVX512DQ ? "kmovb\t{%k1, %0|%0, %k1}" - : "kmovw\t{%k1, %0|%0, %k1}"; - case 8: return TARGET_AVX512DQ ? "kmovb\t{%1, %0|%0, %1}" - : "kmovw\t{%1, %0|%0, %1}"; - case 9: return TARGET_AVX512DQ ? "kmovb\t{%1, %k0|%k0, %1}" - : "kmovw\t{%1, %k0|%k0, %1}"; + case 7: + ops = "kmov%s\t{%%k1, %%0|%%0, %%k1}"; + break; + case 9: + ops = "kmov%s\t{%%1, %%k0|%%k0, %%1}"; + break; case 10: case 11: gcc_assert (TARGET_AVX512DQ); - return "kmovb\t{%1, %0|%0, %1}"; - default: gcc_unreachable (); + /* FALLTHRU */ + case 8: + ops = "kmov%s\t{%%1, %%0|%%0, %%1}"; + break; + default: + gcc_unreachable (); } + suffix = (get_attr_mode (insn) == MODE_HI) ? "w" : "b"; + + snprintf (buf, sizeof (buf), ops, suffix); + return buf; + default: if (get_attr_mode (insn) == MODE_SI) - return "mov{l}\t{%k1, %k0|%k0, %k1}"; + return "mov{l}\t{%k1, %k0|%k0, %k1}"; else - return "mov{b}\t{%1, %0|%0, %1}"; + return "mov{b}\t{%1, %0|%0, %1}"; } } [(set (attr "isa") @@ -2640,6 +2661,9 @@ (const_string "SI") (eq_attr "alternative" "6") (const_string "QI") + (and (eq_attr "alternative" "7,8,9") + (not (match_test "TARGET_AVX512DQ"))) + (const_string "HI") (eq_attr "type" "imovx") (const_string "SI") (and (eq_attr "type" "imov") @@ -8055,23 +8079,26 @@ (any_logic:SWI1248x (match_dup 1) (match_dup 2)))]) -(define_mode_iterator SWI1248_AVX512BW - [QI HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")]) - (define_insn "*k<logic><mode>" [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand" "=k") - (any_logic:SWI1248_AVX512BW (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand" "k") - (match_operand:SWI1248_AVX512BW 2 "mask_reg_operand" "k")))] + (any_logic:SWI1248_AVX512BW + (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand" "k") + (match_operand:SWI1248_AVX512BW 2 "mask_reg_operand" "k")))] "TARGET_AVX512F" { - if (!TARGET_AVX512DQ && <MODE>mode == QImode) + if (get_attr_mode (insn) == MODE_HI) return "k<logic>w\t{%2, %1, %0|%0, %1, %2}"; else return "k<logic><mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}"; } - [(set_attr "mode" "<MODE>") - (set_attr "type" "msklog") - (set_attr "prefix" "vex")]) + [(set_attr "type" "msklog") + (set_attr "prefix" "vex") + (set (attr "mode") + (cond [(and (match_test "<MODE>mode == QImode") + (not (match_test "TARGET_AVX512DQ"))) + (const_string "HI") + ] + (const_string "<MODE>")))]) ;; %%% This used to optimize known byte-wide and operations to memory, ;; and sometimes to QImode registers. If this is considered useful, @@ -8278,14 +8305,22 @@ case 2: return "and{l}\t{%k2, %k0|%k0, %k2}"; case 3: - return TARGET_AVX512DQ ? "kandb\t{%2, %1, %0|%0, %1, %2}" - : "kandw\t{%2, %1, %0|%0, %1, %2}"; + if (get_attr_mode (insn) == MODE_HI) + return "kandw\t{%2, %1, %0|%0, %1, %2}"; + else + return "kandb\t{%2, %1, %0|%0, %1, %2}"; default: gcc_unreachable (); } } [(set_attr "type" "alu,alu,alu,msklog") - (set_attr "mode" "QI,QI,SI,HI") + (set (attr "mode") + (cond [(eq_attr "alternative" "2") + (const_string "SI") + (and (eq_attr "alternative" "3") + (not (match_test "TARGET_AVX512DQ"))) + (const_string "HI")] + (const_string "QI"))) ;; Potential partial reg stall on alternative 2. (set (attr "preferred_for_speed") (cond [(eq_attr "alternative" "2") @@ -8319,10 +8354,10 @@ case 1: return "#"; case 2: - if (TARGET_AVX512DQ && <MODE>mode == QImode) - return "kandnb\t{%2, %1, %0|%0, %1, %2}"; + if (get_attr_mode (insn) == MODE_HI) + return "kandnw\t{%2, %1, %0|%0, %1, %2}"; else - return "kandnw\t{%2, %1, %0|%0, %1, %2}"; + return "kandn<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}"; default: gcc_unreachable (); } @@ -8331,7 +8366,13 @@ (set_attr "type" "bitmanip,*,msklog") (set_attr "prefix" "*,*,vex") (set_attr "btver2_decode" "direct,*,*") - (set_attr "mode" "<MODE>")]) + (set (attr "mode") + (cond [(and (eq_attr "alternative" "2") + (and (match_test "<MODE>mode == QImode") + (not (match_test "TARGET_AVX512DQ")))) + (const_string "HI") + ] + (const_string "<MODE>")))]) (define_split [(set (match_operand:SWI12 0 "general_reg_operand") @@ -8843,37 +8884,32 @@ (set_attr "mode" "<MODE>")]) (define_insn "kxnor<mode>" - [(set (match_operand:SWI12 0 "register_operand" "=r,!k") - (not:SWI12 - (xor:SWI12 - (match_operand:SWI12 1 "register_operand" "0,k") - (match_operand:SWI12 2 "register_operand" "r,k")))) + [(set (match_operand:SWI1248_AVX512BW 0 "register_operand" "=r,!k") + (not:SWI1248_AVX512BW + (xor:SWI1248_AVX512BW + (match_operand:SWI1248_AVX512BW 1 "register_operand" "0,k") + (match_operand:SWI1248_AVX512BW 2 "register_operand" "r,k")))) (clobber (reg:CC FLAGS_REG))] "TARGET_AVX512F" { - if (which_alternative == 1 && <MODE>mode == QImode && TARGET_AVX512DQ) - return "kxnorb\t{%2, %1, %0|%0, %1, %2}"; - return "kxnorw\t{%2, %1, %0|%0, %1, %2}"; + if (which_alternative == 0) + return "#"; + + if (get_attr_mode (insn) == MODE_HI) + return "kxnorw\t{%2, %1, %0|%0, %1, %2}"; + else + return "kxnor<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}"; } [(set_attr "type" "*,msklog") (set_attr "prefix" "*,vex") - (set_attr "mode" "<MODE>")]) + (set (attr "mode") + (cond [(and (eq_attr "alternative" "1") + (and (match_test "<MODE>mode == QImode") + (not (match_test "TARGET_AVX512DQ")))) + (const_string "HI") + ] + (const_string "<MODE>")))]) -(define_insn "kxnor<mode>" - [(set (match_operand:SWI48x 0 "register_operand" "=r,!k") - (not:SWI48x - (xor:SWI48x - (match_operand:SWI48x 1 "register_operand" "0,k") - (match_operand:SWI48x 2 "register_operand" "r,k")))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_AVX512BW" - "@ - # - kxnor<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "*,msklog") - (set_attr "prefix" "*,vex") - (set_attr "mode" "<MODE>")]) - (define_split [(set (match_operand:SWI1248x 0 "general_reg_operand") (not:SWI1248x @@ -9583,9 +9619,10 @@ case 1: return "not{l}\t%k0"; case 2: - if (TARGET_AVX512DQ) + if (get_attr_mode (insn) == MODE_HI) + return "knotw\t{%1, %0|%0, %1}"; + else return "knotb\t{%1, %0|%0, %1}"; - return "knotw\t{%1, %0|%0, %1}"; default: gcc_unreachable (); } @@ -9593,7 +9630,13 @@ [(set_attr "isa" "*,*,avx512f") (set_attr "type" "negnot,negnot,msklog") (set_attr "prefix" "*,*,vex") - (set_attr "mode" "QI,SI,QI") + (set (attr "mode") + (cond [(eq_attr "alternative" "1") + (const_string "SI") + (and (eq_attr "alternative" "2") + (not (match_test "TARGET_AVX512DQ"))) + (const_string "HI")] + (const_string "QI"))) ;; Potential partial reg stall on alternative 1. (set (attr "preferred_for_speed") (cond [(eq_attr "alternative" "1")