diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 93ecde4b4a86a65ceebcc7def70775b9842d7171..d4bbd33ce0790a22152771ad51f6ca6627af50ad 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -1494,7 +1494,7 @@ ix86_binary_operator_ok (enum rtx_code code, machine_mode mode, void ix86_expand_unary_operator (enum rtx_code code, machine_mode mode, - rtx operands[]) + rtx operands[], bool use_ndd) { bool matching_memory = false; rtx src, dst, op, clob; @@ -1513,7 +1513,7 @@ ix86_expand_unary_operator (enum rtx_code code, machine_mode mode, } /* When source operand is memory, destination must match. */ - if (MEM_P (src) && !matching_memory) + if (!use_ndd && MEM_P (src) && !matching_memory) src = force_reg (mode, src); /* Emit the instruction. */ diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 481527872e8155785c58256099e7b54657f4232d..fa9524097296851317d8455dcbe454a033be0b64 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -127,7 +127,7 @@ extern bool ix86_vec_interleave_v2df_operator_ok (rtx operands[3], bool high); extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn); extern bool ix86_agi_dependent (rtx_insn *set_insn, rtx_insn *use_insn); extern void ix86_expand_unary_operator (enum rtx_code, machine_mode, - rtx[]); + rtx[], bool = false); extern rtx ix86_build_const_vector (machine_mode, bool, rtx); extern rtx ix86_build_signbit_mask (machine_mode, bool, bool); extern HOST_WIDE_INT ix86_convert_const_vector_to_integer (rtx, @@ -147,7 +147,8 @@ extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode, rtx[]); extern void ix86_expand_copysign (rtx []); extern void ix86_expand_xorsign (rtx []); -extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[2]); +extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[2], + bool = false); extern bool ix86_match_ccmode (rtx, machine_mode); extern bool ix86_match_ptest_ccmode (rtx); extern void ix86_expand_branch (enum rtx_code, rtx, rtx, rtx); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 8aa33aef7e17f79dd8376752e427353528753b65..4b6bad37c8fc8c90b030e685dd4c1eef7c2c64bf 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -16209,11 +16209,12 @@ ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn) bool ix86_unary_operator_ok (enum rtx_code, machine_mode, - rtx operands[2]) + rtx operands[2], + bool use_ndd) { /* If one of operands is memory, source and destination must match. */ if ((MEM_P (operands[0]) - || MEM_P (operands[1])) + || (!use_ndd && MEM_P (operands[1]))) && ! rtx_equal_p (operands[0], operands[1])) return false; return true; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 90981e733bd6f19a895afb9024c277b92dc4a8b3..e97c1784e9ad28b8a2f4e817f13d8140b0e70a87 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -13287,13 +13287,14 @@ [(set (match_operand:SDWIM 0 "nonimmediate_operand") (neg:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand")))] "" - "ix86_expand_unary_operator (NEG, <MODE>mode, operands); DONE;") + "ix86_expand_unary_operator (NEG, <MODE>mode, operands, + TARGET_APX_NDD); DONE;") (define_insn_and_split "*neg<dwi>2_doubleword" - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro") - (neg:<DWI> (match_operand:<DWI> 1 "nonimmediate_operand" "0"))) + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,&r") + (neg:<DWI> (match_operand:<DWI> 1 "nonimmediate_operand" "0,ro"))) (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, <DWI>mode, operands)" + "ix86_unary_operator_ok (NEG, <DWI>mode, operands, TARGET_APX_NDD)" "#" "&& reload_completed" [(parallel @@ -13310,7 +13311,8 @@ [(set (match_dup 2) (neg:DWIH (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] - "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[2]);") + "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[2]);" + [(set_attr "isa" "*,apx_ndd")]) ;; Convert: ;; mov %esi, %edx @@ -13399,22 +13401,29 @@ (clobber (reg:CC FLAGS_REG))])]) (define_insn "*neg<mode>_1" - [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") - (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))) + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,r") + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,rm"))) (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, <MODE>mode, operands)" - "neg{<imodesuffix>}\t%0" + "ix86_unary_operator_ok (NEG, <MODE>mode, operands, TARGET_APX_NDD)" + "@ + neg{<imodesuffix>}\t%0 + neg{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "<MODE>")]) (define_insn "*negsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r") + [(set (match_operand:DI 0 "register_operand" "=r,r") (zero_extend:DI - (neg:SI (match_operand:SI 1 "register_operand" "0")))) + (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0,rm")))) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%k0" + "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands, + TARGET_APX_NDD)" + "@ + neg{l}\t%k0 + neg{l}\t{%k1, %k0|%k0, %k1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "SI")]) ;; Alternative 1 is needed to work around LRA limitation, see PR82524. @@ -13440,51 +13449,65 @@ (define_insn "*neg<mode>_2" [(set (reg FLAGS_REG) (compare - (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")) + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,rm")) (const_int 0))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,r") (neg:SWI (match_dup 1)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_unary_operator_ok (NEG, <MODE>mode, operands)" - "neg{<imodesuffix>}\t%0" + && ix86_unary_operator_ok (NEG, <MODE>mode, operands, + TARGET_APX_NDD)" + "@ + neg{<imodesuffix>}\t%0 + neg{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "<MODE>")]) (define_insn "*negsi_2_zext" [(set (reg FLAGS_REG) (compare - (neg:SI (match_operand:SI 1 "register_operand" "0")) + (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0,rm")) (const_int 0))) - (set (match_operand:DI 0 "register_operand" "=r") + (set (match_operand:DI 0 "register_operand" "=r,r") (zero_extend:DI (neg:SI (match_dup 1))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_unary_operator_ok (NEG, SImode, operands)" - "neg{l}\t%k0" + && ix86_unary_operator_ok (NEG, SImode, operands, + TARGET_APX_NDD)" + "@ + neg{l}\t%k0 + neg{l}\t{%1, %k0|%k0, %1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "SI")]) (define_insn "*neg<mode>_ccc_1" [(set (reg:CCC FLAGS_REG) (unspec:CCC - [(match_operand:SWI 1 "nonimmediate_operand" "0") + [(match_operand:SWI 1 "nonimmediate_operand" "0,rm") (const_int 0)] UNSPEC_CC_NE)) - (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,r") (neg:SWI (match_dup 1)))] "" - "neg{<imodesuffix>}\t%0" + "@ + neg{<imodesuffix>}\t%0 + neg{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "<MODE>")]) (define_insn "*neg<mode>_ccc_2" [(set (reg:CCC FLAGS_REG) (unspec:CCC - [(match_operand:SWI 1 "nonimmediate_operand" "0") + [(match_operand:SWI 1 "nonimmediate_operand" "0,rm") (const_int 0)] UNSPEC_CC_NE)) - (clobber (match_scratch:SWI 0 "=<r>"))] + (clobber (match_scratch:SWI 0 "=<r>,r"))] "" - "neg{<imodesuffix>}\t%0" + "@ + neg{<imodesuffix>}\t%0 + neg{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "negnot") + (set_attr "isa" "*,apx_ndd") (set_attr "mode" "<MODE>")]) (define_expand "x86_neg<mode>_ccc" diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd.c b/gcc/testsuite/gcc.target/i386/apx-ndd.c index 0c7952ef0184f7881a1998d449bf83f7144b3269..c351f71265e489accfd8ca2bf9b1ca1d70011f2f 100644 --- a/gcc/testsuite/gcc.target/i386/apx-ndd.c +++ b/gcc/testsuite/gcc.target/i386/apx-ndd.c @@ -27,8 +27,25 @@ foo2_##OP_NAME##_##TYPE (TYPE *a, TYPE b) \ { \ TYPE c = *a OP b; \ return c; \ +} + +#define F(TYPE, OP_NAME, OP) \ +TYPE \ +__attribute__ ((noipa)) \ +f_##OP_NAME##_##TYPE (TYPE *a) \ +{ \ + TYPE b = OP*a; \ + return b; \ } +#define F1(TYPE, OP_NAME, OP) \ +TYPE \ +__attribute__ ((noipa)) \ +f1_##OP_NAME##_##TYPE (TYPE a) \ +{ \ + TYPE b = OP a; \ + return b; \ +} FOO (char, add, +) FOO1 (char, add, +) FOO2 (char, add, +) @@ -50,8 +67,20 @@ FOO (int, sub, -) FOO1 (int, sub, -) FOO (long, sub, -) FOO1 (long, sub, -) + +F (char, neg, -) +F1 (char, neg, -) +F (short, neg, -) +F1 (short, neg, -) +F (int, neg, -) +F1 (int, neg, -) +F (long, neg, -) +F1 (long, neg, -) /* { dg-final { scan-assembler-times "add(?:b|l|w|q)\[^\n\r]*1, \\(%rdi\\), %(?:|r|e)a(?:x|l)" 4 } } */ /* { dg-final { scan-assembler-times "lea(?:l|q)\[^\n\r]\\(%r(?:d|s)i,%r(?:d|s)i\\), %(?:|r|e)ax" 4 } } */ /* { dg-final { scan-assembler-times "add(?:b|l|w|q)\[^\n\r]%(?:|r|e)si(?:|l), \\(%rdi\\), %(?:|r|e)a(?:x|l)" 4 } } */ /* { dg-final { scan-assembler-times "sub(?:b|l|w|q)\[^\n\r]*1, \\(%rdi\\), %(?:|r|e)a(?:x|l)" 4 } } */ /* { dg-final { scan-assembler-times "sub(?:b|l|w|q)\[^\n\r]%(?:|r|e)si(?:|l), %(?:|r|e)di, %(?:|r|e)a(?:x|l)" 4 } } */ +/* { dg-final { scan-assembler-times "negb\[^\n\r]\\(%rdi\\), %(?:|r|e)al" 1 } } */ +/* { dg-final { scan-assembler-times "neg(?:l|w|q)\[^\n\r]\\(%rdi\\), %(?:|r|e)ax" 3 } } */ +/* { dg-final { scan-assembler-times "neg(?:l|w|q)\[^\n\r]%(?:|r|e)di, %(?:|r|e)ax" 4 } } */