Message ID | 20240206034848.6668-1-hjl.tools@gmail.com |
---|---|
State | New |
Headers | show |
Series | x86: Update constraints for APX NDD instructions | expand |
On Tue, Feb 6, 2024 at 11:49 AM H.J. Lu <hjl.tools@gmail.com> wrote: > > 1. The only supported TLS code sequence with ADD is > > addq foo@gottpoff(%rip),%reg > > Change je constraint to a memory operand in APX NDD ADD pattern with > register source operand. > > 2. The instruction length of APX NDD instructions with immediate operand: > > op imm, mem, reg > > may exceed the size limit of 15 byes when non-default address space, > segment register or address size prefix are used. > > Add jM constraint which is a memory operand valid for APX NDD instructions > with immediate operand and add jO constraint which is an offsetable memory > operand valid for APX NDD instructions with immediate operand. Update > APX NDD patterns with jM and jO constraints. Ok. > > gcc/ > > PR target/113711 > PR target/113733 > * config/i386/constraints.md: List all constraints with j prefix. > (j>): Change auto-dec to auto-inc in documentation. > (je): Changed to a memory constraint with APX NDD TLS operand > check. > (jM): New memory constraint for APX NDD instructions. > (jO): Likewise. > * config/i386/i386-protos.h (x86_poff_operand_p): Removed. > * config/i386/i386.cc (x86_poff_operand_p): Likewise. > * config/i386/i386.md (*add<dwi>3_doubleword): Use rjO. > (*add<mode>_1[SWI48]): Use je and jM. > (addsi_1_zext): Use jM. > (*addv<dwi>4_doubleword_1[DWI]): Likewise. > (*sub<mode>_1[SWI]): Use jM. > (@add<mode>3_cc_overflow_1[SWI]): Likewise. > (*add<dwi>3_doubleword_cc_overflow_1): Use rjO. > (*and<dwi>3_doubleword): Likewise. > (*anddi_1): Use jM. > (*andsi_1_zext): Likewise. > (*and<mode>_1[SWI24]): Likewise. > (*<code><dwi>3_doubleword[any_or]: Use rjO > (*code<mode>_1[any_or SWI248]): Use jM. > (*<code>si_1_zext[zero_extend + any_or]): Likewise. > * config/i386/predicates.md (apx_ndd_memory_operand): New. > (apx_ndd_add_memory_operand): Likewise. > > gcc/testsuite/ > > PR target/113711 > PR target/113733 > * gcc.target/i386/apx-ndd-2.c: New test. > * gcc.target/i386/apx-ndd-base-index-1.c: Likewise. > * gcc.target/i386/apx-ndd-no-seg-global-1.c: Likewise. > * gcc.target/i386/apx-ndd-seg-1.c: Likewise. > * gcc.target/i386/apx-ndd-seg-2.c: Likewise. > * gcc.target/i386/apx-ndd-seg-3.c: Likewise. > * gcc.target/i386/apx-ndd-seg-4.c: Likewise. > * gcc.target/i386/apx-ndd-seg-5.c: Likewise. > * gcc.target/i386/apx-ndd-tls-1a.c: Likewise. > * gcc.target/i386/apx-ndd-tls-2.c: Likewise. > * gcc.target/i386/apx-ndd-tls-3.c: Likewise. > * gcc.target/i386/apx-ndd-tls-4.c: Likewise. > * gcc.target/i386/apx-ndd-x32-1.c: Likewise. > --- > gcc/config/i386/constraints.md | 36 ++++- > gcc/config/i386/i386-protos.h | 1 - > gcc/config/i386/i386.cc | 25 ---- > gcc/config/i386/i386.md | 129 +++++++++--------- > gcc/config/i386/predicates.md | 65 +++++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-2.c | 17 +++ > .../gcc.target/i386/apx-ndd-base-index-1.c | 50 +++++++ > .../gcc.target/i386/apx-ndd-no-seg-global-1.c | 74 ++++++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c | 98 +++++++++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c | 98 +++++++++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c | 14 ++ > gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c | 9 ++ > gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c | 13 ++ > .../gcc.target/i386/apx-ndd-tls-1a.c | 41 ++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c | 38 ++++++ > gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c | 16 +++ > gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c | 31 +++++ > gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c | 49 +++++++ > 18 files changed, 712 insertions(+), 92 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md > index 280e4c8e36c..64702d9c0a8 100644 > --- a/gcc/config/i386/constraints.md > +++ b/gcc/config/i386/constraints.md > @@ -372,6 +372,24 @@ (define_address_constraint "Ts" > "Address operand without segment register" > (match_operand 0 "address_no_seg_operand")) > > +;; j prefix is used for APX operand constraints. > +;; < Auto-dec memory operand without GPR32. > +;; > Auto-inc memory operand without GPR32. > +;; a Vector memory operand without GPR32. > +;; b VSIB address operand without EGPR. > +;; c Integer register. GENERAL_GPR16 for TARGET_APX_EGPR and > +;; !TARGET_AVX, otherwise GENERAL_REGS. > +;; e Memory operand for APX NDD ADD. > +;; j Integer register. GENERAL_GPR16 for TARGET_APX_EGPR, otherwise > +;; GENERAL_REGS. > +;; o Offsetable memory operand without GPR32. > +;; p General address operand without GPR32. > +;; m Memory operand without GPR32. > +;; M Memory operand, with APX NDD check. > +;; R Integer register. GENERAL_REGS. > +;; O Offsettable memory operand, with APX NDD check. > +;; V Non-offsetable memory operand without GPR32. > + > ;; Constraint that force to use EGPR, can only adopt to register class. > (define_register_constraint "jR" "GENERAL_REGS") > > @@ -393,7 +411,7 @@ (define_constraint "j<" > (match_test "x86_extended_rex2reg_mentioned_p (op)"))))) > > (define_constraint "j>" > - "@internal auto-dec memory operand without GPR32." > + "@internal auto-inc memory operand without GPR32." > (and (and (match_code "mem") > (ior (match_test "GET_CODE (XEXP (op, 0)) == PRE_INC") > (match_test "GET_CODE (XEXP (op, 0)) == POST_INC"))) > @@ -438,7 +456,15 @@ (define_address_constraint "jb" > (define_register_constraint "jc" > "TARGET_APX_EGPR && !TARGET_AVX ? GENERAL_GPR16 : GENERAL_REGS") > > -(define_constraint "je" > - "@internal constant that do not allow any unspec global offsets" > - (and (match_operand 0 "x86_64_immediate_operand") > - (match_test "!x86_poff_operand_p (op)"))) > +(define_memory_constraint "je" > + "@internal Memory operand for APX NDD ADD." > + (match_operand 0 "apx_ndd_add_memory_operand")) > + > +(define_memory_constraint "jM" > + "@internal Memory operand, with APX NDD check." > + (match_operand 0 "apx_ndd_memory_operand")) > + > +(define_memory_constraint "jO" > + "@internal Offsettable memory operand, with APX NDD check." > + (and (match_operand 0 "apx_ndd_memory_operand") > + (match_test "offsettable_nonstrict_memref_p (op)"))) > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > index 34b93773b69..46214a63974 100644 > --- a/gcc/config/i386/i386-protos.h > +++ b/gcc/config/i386/i386-protos.h > @@ -66,7 +66,6 @@ extern bool x86_extended_QIreg_mentioned_p (rtx_insn *); > extern bool x86_extended_reg_mentioned_p (rtx); > extern bool x86_extended_rex2reg_mentioned_p (rtx); > extern bool x86_evex_reg_mentioned_p (rtx [], int); > -extern bool x86_poff_operand_p (rtx); > extern bool x86_maybe_negate_const_int (rtx *, machine_mode); > extern machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx); > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > index b3e7c74846e..706dfe8f5b2 100644 > --- a/gcc/config/i386/i386.cc > +++ b/gcc/config/i386/i386.cc > @@ -23406,31 +23406,6 @@ x86_evex_reg_mentioned_p (rtx operands[], int nops) > return false; > } > > -/* Return true when rtx operand does not contain any UNSPEC_*POFF related > - constant to avoid APX_NDD instructions excceed encoding length limit. */ > -bool > -x86_poff_operand_p (rtx operand) > -{ > - if (GET_CODE (operand) == CONST) > - { > - rtx op = XEXP (operand, 0); > - if (GET_CODE (op) == PLUS) > - op = XEXP (op, 0); > - > - if (GET_CODE (op) == UNSPEC) > - { > - int unspec = XINT (op, 1); > - return (unspec == UNSPEC_NTPOFF > - || unspec == UNSPEC_TPOFF > - || unspec == UNSPEC_DTPOFF > - || unspec == UNSPEC_GOTTPOFF > - || unspec == UNSPEC_GOTNTPOFF > - || unspec == UNSPEC_INDNTPOFF); > - } > - } > - return false; > -} > - > /* If profitable, negate (without causing overflow) integer constant > of mode MODE at location LOC. Return true in this case. */ > bool > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > index a82f2e456fe..d5db538bb6a 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -6290,10 +6290,10 @@ (define_expand "add<mode>3" > }) > > (define_insn_and_split "*add<dwi>3_doubleword" > - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") > + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") > (plus:<DWI> > - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") > - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,r"))) > + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") > + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,r"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)" > "#" > @@ -6332,7 +6332,7 @@ (define_insn_and_split "*add<dwi>3_doubleword" > DONE; > } > } > -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) > +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) > > (define_insn_and_split "*add<dwi>3_doubleword_zext" > [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o,&r,&r") > @@ -6424,10 +6424,10 @@ (define_insn_and_split "*add<dwi>3_doubleword_concat_zext" > "split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[5]);") > > (define_insn "*add<mode>_1" > - [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r,r") > + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r") > (plus:SWI48 > - (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rm,r,m,r") > - (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,je,BM"))) > + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rje,jM,r") > + (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,BM"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)" > { > @@ -6462,7 +6462,7 @@ (define_insn "*add<mode>_1" > : "add{<imodesuffix>}\t{%2, %0|%0, %2}"; > } > } > - [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd") > + [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd") > (set (attr "type") > (cond [(eq_attr "alternative" "3") > (const_string "lea") > @@ -6484,10 +6484,10 @@ (define_insn "*add<mode>_1" > ;; patterns constructed from addsi_1 to match. > > (define_insn "addsi_1_zext" > - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r") > + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") > (zero_extend:DI > - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r,r,rm") > - (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le,rBMe,re")))) > + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r,r,rm,rjM") > + (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le,rBMe,r,e")))) > (clobber (reg:CC FLAGS_REG))] > "TARGET_64BIT > && ix86_binary_operator_ok (PLUS, SImode, operands, TARGET_APX_NDD)" > @@ -6523,7 +6523,7 @@ (define_insn "addsi_1_zext" > : "add{l}\t{%2, %k0|%k0, %2}"; > } > } > - [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd") > + [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd,apx_ndd") > (set (attr "type") > (cond [(eq_attr "alternative" "2") > (const_string "lea") > @@ -7463,7 +7463,7 @@ (define_insn_and_split "*addv<dwi>4_doubleword_1" > (eq:CCO > (plus:<QPWI> > (sign_extend:<QPWI> > - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,rm")) > + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,rjM")) > (match_operand:<QPWI> 3 "const_scalar_int_operand" "n,n")) > (sign_extend:<QPWI> > (plus:<DWI> > @@ -7833,18 +7833,19 @@ (define_insn_and_split "*sub<dwi>3_doubleword_zext" > [(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) > > (define_insn "*sub<mode>_1" > - [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") > + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r,r") > (minus:SWI > - (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,r") > - (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>"))) > + (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,rjM,r") > + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r,<i>,<m>"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (MINUS, <MODE>mode, operands, TARGET_APX_NDD)" > "@ > sub{<imodesuffix>}\t{%2, %0|%0, %2} > sub{<imodesuffix>}\t{%2, %0|%0, %2} > sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > + sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" > - [(set_attr "isa" "*,*,apx_ndd,apx_ndd") > + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd") > (set_attr "type" "alu") > (set_attr "mode" "<MODE>")]) > > @@ -9370,18 +9371,19 @@ (define_insn "@add<mode>3_cc_overflow_1" > [(set (reg:CCC FLAGS_REG) > (compare:CCC > (plus:SWI > - (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,r") > - (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>")) > + (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,rjM,r") > + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r,<i>,<m>")) > (match_dup 1))) > - (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") > + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r,r") > (plus:SWI (match_dup 1) (match_dup 2)))] > "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)" > "@ > add{<imodesuffix>}\t{%2, %0|%0, %2} > add{<imodesuffix>}\t{%2, %0|%0, %2} > add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > + add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" > - [(set_attr "isa" "*,*,apx_ndd,apx_ndd") > + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd") > (set_attr "type" "alu") > (set_attr "mode" "<MODE>")]) > > @@ -9501,10 +9503,10 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1" > [(set (reg:CCC FLAGS_REG) > (compare:CCC > (plus:<DWI> > - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") > - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o")) > + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") > + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")) > (match_dup 1))) > - (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") > + (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") > (plus:<DWI> (match_dup 1) (match_dup 2)))] > "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)" > "#" > @@ -9546,7 +9548,7 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1" > else > operands[6] = gen_rtx_ZERO_EXTEND (<DWI>mode, operands[5]); > } > -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) > +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) > > ;; x == 0 with zero flag test can be done also as x < 1U with carry flag > ;; test, where the latter is preferrable if we have some carry consuming > @@ -11690,10 +11692,10 @@ (define_expand "and<mode>3" > }) > > (define_insn_and_split "*and<dwi>3_doubleword" > - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") > + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") > (and:<DWI> > - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") > - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o"))) > + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") > + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (AND, <DWI>mode, operands, TARGET_APX_NDD)" > "#" > @@ -11730,13 +11732,13 @@ (define_insn_and_split "*and<dwi>3_doubleword" > > DONE; > } > -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) > +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) > > (define_insn "*anddi_1" > - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,?k") > + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,?k") > (and:DI > - (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,rm,r,qm,k") > - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,re,m,re,m,L,k"))) > + (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,rm,rjM,r,qm,k") > + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,re,m,r,e,m,L,k"))) > (clobber (reg:CC FLAGS_REG))] > "TARGET_64BIT > && ix86_binary_operator_ok (AND, DImode, operands, TARGET_APX_NDD)" > @@ -11747,11 +11749,12 @@ (define_insn "*anddi_1" > and{q}\t{%2, %0|%0, %2} > and{q}\t{%2, %1, %0|%0, %1, %2} > and{q}\t{%2, %1, %0|%0, %1, %2} > + and{q}\t{%2, %1, %0|%0, %1, %2} > # > #" > - [(set_attr "isa" "x64,apx_ndd,x64,x64,apx_ndd,apx_ndd,x64,avx512bw") > - (set_attr "type" "alu,alu,alu,alu,alu,alu,imovx,msklog") > - (set_attr "length_immediate" "*,*,*,*,*,*,0,*") > + [(set_attr "isa" "x64,apx_ndd,x64,x64,apx_ndd,apx_ndd,apx_ndd,x64,avx512bw") > + (set_attr "type" "alu,alu,alu,alu,alu,alu,alu,imovx,msklog") > + (set_attr "length_immediate" "*,*,*,*,*,*,*,0,*") > (set (attr "prefix_rex") > (if_then_else > (and (eq_attr "type" "imovx") > @@ -11759,7 +11762,7 @@ (define_insn "*anddi_1" > (match_operand 1 "ext_QIreg_operand"))) > (const_string "1") > (const_string "*"))) > - (set_attr "mode" "SI,SI,DI,DI,DI,DI,SI,DI")]) > + (set_attr "mode" "SI,SI,DI,DI,DI,DI,DI,SI,DI")]) > > (define_insn_and_split "*anddi_1_btr" > [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") > @@ -11814,25 +11817,26 @@ (define_split > > ;; See comment for addsi_1_zext why we do use nonimmediate_operand > (define_insn "*andsi_1_zext" > - [(set (match_operand:DI 0 "register_operand" "=r,r,r") > + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") > (zero_extend:DI > - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,r") > - (match_operand:SI 2 "x86_64_general_operand" "rBMe,re,BM")))) > + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,rjM,r") > + (match_operand:SI 2 "x86_64_general_operand" "rBMe,r,e,BM")))) > (clobber (reg:CC FLAGS_REG))] > "TARGET_64BIT > && ix86_binary_operator_ok (AND, SImode, operands, TARGET_APX_NDD)" > "@ > and{l}\t{%2, %k0|%k0, %2} > and{l}\t{%2, %1, %k0|%k0, %1, %2} > + and{l}\t{%2, %1, %k0|%k0, %1, %2} > and{l}\t{%2, %1, %k0|%k0, %1, %2}" > [(set_attr "type" "alu") > - (set_attr "isa" "*,apx_ndd,apx_ndd") > + (set_attr "isa" "*,apx_ndd,apx_ndd,apx_ndd") > (set_attr "mode" "SI")]) > > (define_insn "*and<mode>_1" > - [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,Ya,?k") > - (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,rm,r,qm,k") > - (match_operand:SWI24 2 "<general_operand>" "r<i>,<m>,r<i>,<m>,L,k"))) > + [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,r,Ya,?k") > + (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,rm,rjM,r,qm,k") > + (match_operand:SWI24 2 "<general_operand>" "r<i>,<m>,r,<i>,<m>,L,k"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (AND, <MODE>mode, operands, TARGET_APX_NDD)" > "@ > @@ -11840,19 +11844,20 @@ (define_insn "*and<mode>_1" > and{<imodesuffix>}\t{%2, %0|%0, %2} > and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > + and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > # > #" > [(set (attr "isa") > - (cond [(eq_attr "alternative" "2,3") > + (cond [(eq_attr "alternative" "2,3,4") > (const_string "apx_ndd") > - (eq_attr "alternative" "5") > + (eq_attr "alternative" "6") > (if_then_else (eq_attr "mode" "SI") > (const_string "avx512bw") > (const_string "avx512f")) > ] > (const_string "*"))) > - (set_attr "type" "alu,alu,alu,alu,imovx,msklog") > - (set_attr "length_immediate" "*,*,*,*,0,*") > + (set_attr "type" "alu,alu,alu,alu,alu,imovx,msklog") > + (set_attr "length_immediate" "*,*,*,*,*,0,*") > (set (attr "prefix_rex") > (if_then_else > (and (eq_attr "type" "imovx") > @@ -11860,7 +11865,7 @@ (define_insn "*and<mode>_1" > (match_operand 1 "ext_QIreg_operand"))) > (const_string "1") > (const_string "*"))) > - (set_attr "mode" "<MODE>,<MODE>,<MODE>,<MODE>,SI,<MODE>")]) > + (set_attr "mode" "<MODE>,<MODE>,<MODE>,<MODE>,<MODE>,SI,<MODE>")]) > > (define_insn "*andqi_1" > [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r,r,?k") > @@ -12677,10 +12682,10 @@ (define_expand "<code><mode>3" > }) > > (define_insn_and_split "*<code><dwi>3_doubleword" > - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") > + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") > (any_or:<DWI> > - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") > - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o"))) > + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") > + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (<CODE>, <DWI>mode, operands, TARGET_APX_NDD)" > "#" > @@ -12733,13 +12738,13 @@ (define_insn_and_split "*<code><dwi>3_doubleword" > > DONE; > } > -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) > +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) > > (define_insn "*<code><mode>_1" > - [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,?k") > + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,?k") > (any_or:SWI248 > - (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,rm,r,k") > - (match_operand:SWI248 2 "<general_operand>" "r<i>,<m>,r<i>,<m>,k"))) > + (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,rm,rjM,r,k") > + (match_operand:SWI248 2 "<general_operand>" "r<i>,<m>,r,<i>,<m>,k"))) > (clobber (reg:CC FLAGS_REG))] > "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands, TARGET_APX_NDD)" > "@ > @@ -12747,9 +12752,10 @@ (define_insn "*<code><mode>_1" > <logic>{<imodesuffix>}\t{%2, %0|%0, %2} > <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > + <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} > #" > - [(set_attr "isa" "*,*,apx_ndd,apx_ndd,<kmov_isa>") > - (set_attr "type" "alu, alu, alu, alu, msklog") > + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,<kmov_isa>") > + (set_attr "type" "alu, alu, alu, alu, alu, msklog") > (set_attr "mode" "<MODE>")]) > > (define_insn_and_split "*notxor<mode>_1" > @@ -12864,19 +12870,20 @@ (define_insn_and_split "*xor2andn" > > ;; See comment for addsi_1_zext why we do use nonimmediate_operand > (define_insn "*<code>si_1_zext" > - [(set (match_operand:DI 0 "register_operand" "=r,r,r") > + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") > (zero_extend:DI > - (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,r") > - (match_operand:SI 2 "x86_64_general_operand" "rBMe,re,BM")))) > + (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,rjM,r") > + (match_operand:SI 2 "x86_64_general_operand" "rBMe,r,e,BM")))) > (clobber (reg:CC FLAGS_REG))] > "TARGET_64BIT > && ix86_binary_operator_ok (<CODE>, SImode, operands, TARGET_APX_NDD)" > "@ > <logic>{l}\t{%2, %k0|%k0, %2} > <logic>{l}\t{%2, %1, %k0|%k0, %1, %2} > + <logic>{l}\t{%2, %1, %k0|%k0, %1, %2} > <logic>{l}\t{%2, %1, %k0|%k0, %1, %2}" > [(set_attr "type" "alu") > - (set_attr "isa" "*,apx_ndd,apx_ndd") > + (set_attr "isa" "*,apx_ndd,apx_ndd,apx_ndd") > (set_attr "mode" "SI")]) > > (define_insn "*<code>si_1_zext_imm" > diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md > index 06027a84532..4c1aedd7e70 100644 > --- a/gcc/config/i386/predicates.md > +++ b/gcc/config/i386/predicates.md > @@ -2248,3 +2248,68 @@ (define_predicate "aeswidekl_operation" > } > return true; > }) > + > +;; Return true if OP is a memory operand that can be also used in APX > +;; NDD patterns with immediate operand. With non-default address space, > +;; segment register or address size prefix, APX NDD instruction length > +;; can exceed the 15 byte size limit. > +(define_predicate "apx_ndd_memory_operand" > + (match_operand 0 "memory_operand") > +{ > + /* OK if immediate operand size < 4 bytes. */ > + if (GET_MODE_SIZE (mode) < 4) > + return true; > + > + bool default_addr = ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (op)); > + bool address_size_prefix = TARGET_X32 && Pmode == SImode; > + > + struct ix86_address parts; > + int ok; > + > + op = XEXP (op, 0); > + ok = ix86_decompose_address (op, &parts); > + gcc_assert (ok); > + > + if (default_addr) > + { > + /* Default address space. */ > + > + /* Not OK with address size prefix, index register and disp. */ > + if (address_size_prefix > + && parts.index > + && parts.disp > + && parts.disp != const0_rtx) > + return false; > + } > + else > + { > + /* Non-default address space. */ > + > + /* Not OK without base register. */ > + if (!parts.base) > + return false; > + > + /* Not OK with disp and address size prefix. */ > + if (address_size_prefix && parts.disp) > + return false; > + } > + > + return true; > +}) > + > +;; Return true if OP is a memory operand which can be used in APX NDD > +;; ADD with register source operand. UNSPEC_GOTNTPOFF memory operand > +;; isn't allowed with APX NDD ADD. > +(define_predicate "apx_ndd_add_memory_operand" > + (match_operand 0 "memory_operand") > +{ > + op = XEXP (op, 0); > + > + /* Disallow APX NDD ADD with UNSPEC_GOTNTPOFF. */ > + if (GET_CODE (op) == CONST > + && GET_CODE (XEXP (op, 0)) == UNSPEC > + && XINT (XEXP (op, 0), 1) == UNSPEC_GOTNTPOFF) > + return false; > + > + return true; > +}) > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-2.c > new file mode 100644 > index 00000000000..3a5272d065e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-2.c > @@ -0,0 +1,17 @@ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-options "-mapxf -O3 -w" } */ > + > +long a; > +int b, d, e; > +void > +g (void) > +{ > + int c; > + _Bool f; > + __asm__("" : "=c"(c)); > + switch (d) > + case 2: > + e = f = c & 2; > + if (f) > + a = b; > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c > new file mode 100644 > index 00000000000..208acd36958 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c > @@ -0,0 +1,50 @@ > +/* PR target/113711 */ > +/* { dg-do compile { target { ! ia32 } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +#define FOO(TYPE, OP_NAME, OP, IMM) \ > +TYPE \ > +foo_##OP_NAME##_##TYPE (TYPE *p, int64_t off) \ > +{ \ > + TYPE b = p[off] OP IMM; \ > + return b; \ > +} > + > +FOO (char, add, +, 0x7) > +FOO (short, add, +, 0x2000) > +FOO (int, add, +, 0x2000) > +FOO (int64_t, add, +, 0x2000) > + > +FOO (char, sub, -, 0x7) > +FOO (short, sub, -, 0x2000) > +FOO (int, sub, -, 0x2000) > +FOO (int64_t, sub, -, 0x2000) > + > +FOO (char, and, &, 0x7) > +FOO (short, and, &, 0x2000) > +FOO (int, and, &, 0x2000) > +FOO (int64_t, and, &, 0x2000) > + > +FOO (char, or, |, 0x7) > +FOO (short, or, |, 0x2000) > +FOO (int, or, |, 0x2000) > +FOO (int64_t, or, |, 0x2000) > + > +FOO (char, xor, ^, 0x7) > +FOO (short, xor, ^, 0x2000) > +FOO (int, xor, ^, 0x2000) > +FOO (int64_t, xor, ^, 0x2000) > + > +FOO (char, shl, <<, 0x7) > +FOO (short, shl, <<, 0x7) > +FOO (int, shl, <<, 0x7) > +FOO (int64_t, shl, <<, 0x7) > + > +FOO (char, sar, >>, 0x7) > +FOO (short, sar, >>, 0x7) > +FOO (int, sar, >>, 0x7) > +FOO (int64_t, sar, >>, 0x7) > + > +/* { dg-final { scan-assembler-not "mov"} } */ > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c > new file mode 100644 > index 00000000000..d2a4040975a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c > @@ -0,0 +1,74 @@ > +/* PR target/113711 */ > +/* { dg-do compile { target { ! ia32 } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +#define FOO(TYPE, OP_NAME, OP, IMM) \ > +extern TYPE foo_##OP_NAME##_##TYPE##_var; \ > +TYPE \ > +foo_##OP_NAME##_##TYPE (void) \ > +{ \ > + TYPE b = foo_##OP_NAME##_##TYPE##_var OP IMM; \ > + return b; \ > +} > + > +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ > +extern UTYPE bar_##OP_NAME##_##TYPE##_var; \ > +int64_t \ > +bar_##OP_NAME##_##TYPE (void) \ > +{ \ > + int64_t b = bar_##OP_NAME##_##TYPE##_var OP IMM; \ > + return b; \ > +} > + > +FOO (char, add, +, 0x7) > +FOO (short, add, +, 0x2000) > +FOO (int, add, +, 0x2000) > +BAR (int, unsigned int, add, +, 0x2000) > +FOO (int64_t, add, +, 0x2000) > +BAR (int64_t, uint64_t, add, +, 0x2000) > + > +FOO (char, sub, -, 0x7) > +FOO (short, sub, -, 0x2000) > +FOO (int, sub, -, 0x2000) > +BAR (int, unsigned int, sub, -, 0x2000) > +FOO (int64_t, sub, -, 0x2000) > +BAR (int64_t, uint64_t, sub, -, 0x2000) > + > +FOO (char, and, &, 0x7) > +FOO (short, and, &, 0x2000) > +FOO (int, and, &, 0x2000) > +BAR (int, unsigned int, and, &, 0x2000) > +FOO (int64_t, and, &, 0x2000) > +BAR (int64_t, uint64_t, and, &, 0x2000) > + > +FOO (char, or, |, 0x7) > +FOO (short, or, |, 0x2000) > +FOO (int, or, |, 0x2000) > +BAR (int, unsigned int, or, |, 0x2000) > +FOO (int64_t, or, |, 0x2000) > +BAR (int64_t, uint64_t, or, |, 0x2000) > + > +FOO (char, xor, ^, 0x7) > +FOO (short, xor, ^, 0x2000) > +FOO (int, xor, ^, 0x2000) > +BAR (int, unsigned int, xor, ^, 0x2000) > +FOO (int64_t, xor, ^, 0x2000) > +BAR (int64_t, uint64_t, xor, ^, 0x2000) > + > +FOO (char, shl, <<, 0x7) > +FOO (short, shl, <<, 0x7) > +FOO (int, shl, <<, 0x7) > +BAR (int, unsigned int, shl, <<, 0x7) > +FOO (int64_t, shl, <<, 0x7) > +BAR (int64_t, uint64_t, shl, <<, 0x7) > + > +FOO (char, sar, >>, 0x7) > +FOO (short, sar, >>, 0x7) > +FOO (int, sar, >>, 0x7) > +BAR (int, unsigned int, sar, >>, 0x7) > +FOO (int64_t, sar, >>, 0x7) > +BAR (int64_t, uint64_t, sar, >>, 0x7) > + > +/* { dg-final { scan-assembler-not "mov"} } */ > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c > new file mode 100644 > index 00000000000..d18055a9250 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c > @@ -0,0 +1,98 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +#define FOO(TYPE, OP_NAME, OP, IMM) \ > +TYPE \ > +foo_##OP_NAME##_##TYPE (void) \ > +{ \ > + TYPE b = (*(TYPE __seg_fs *) 0) OP IMM; \ > + return b; \ > +} > + > +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ > +int64_t \ > +bar_##OP_NAME##_##TYPE (void) \ > +{ \ > + int64_t b = (*(UTYPE __seg_fs *) 0) OP IMM; \ > + return b; \ > +} > + > +FOO (char, add, +, 0x7) > +BAR (char, unsigned char, add, +, 0x7) > +FOO (short, add, +, 0x2000) > +BAR (short, unsigned short, add, +, 0x2000) > +FOO (int, add, +, 0x2000) > +BAR (int, unsigned int, add, +, 0x2000) > +FOO (int64_t, add, +, 0x2000) > +BAR (int64_t, uint64_t, add, +, 0x2000) > +FOO (__int128_t, add, +, 0x2000) > +BAR (__int128_t, __uint128_t, add, +, 0x2000) > + > +FOO (char, sub, -, 0x7) > +BAR (char, unsigned char, sub, -, 0x7) > +FOO (short, sub, -, 0x2000) > +BAR (short, unsigned short, sub, -, 0x2000) > +FOO (int, sub, -, 0x2000) > +BAR (int, unsigned int, sub, -, 0x2000) > +FOO (int64_t, sub, -, 0x2000) > +BAR (int64_t, uint64_t, sub, -, 0x2000) > +FOO (__int128_t, sub, -, 0x2000) > +BAR (__int128_t, __uint128_t, sun, -, 0x2000) > + > +FOO (char, and, &, 0x7) > +BAR (char, unsigned char, and, &, 0x7) > +FOO (short, and, &, 0x2000) > +BAR (short, unsigned short, and, &, 0x2000) > +FOO (int, and, &, 0x2000) > +BAR (int, unsigned int, and, &, 0x2000) > +FOO (int64_t, and, &, 0x2000) > +BAR (int64_t, uint64_t, and, &, 0x2000) > +FOO (__int128_t, and, &, 0x2000) > +BAR (__int128_t, __uint128_t, and, &, 0x2000) > + > +FOO (char, or, |, 0x7) > +BAR (char, unsigned char, or, |, 0x7) > +FOO (short, or, |, 0x2000) > +BAR (short, unsigned short, or, |, 0x2000) > +FOO (int, or, |, 0x2000) > +BAR (int, unsigned int, or, |, 0x2000) > +FOO (int64_t, or, |, 0x2000) > +BAR (int64_t, uint64_t, or, |, 0x2000) > +FOO (__int128_t, or, |, 0x2000) > +BAR (__int128_t, __uint128_t, or, |, 0x2000) > + > +FOO (char, xor, ^, 0x7) > +BAR (char, unsigned char, xor, ^, 0x7) > +FOO (short, xor, ^, 0x2000) > +BAR (short, unsigned short, xor, ^, 0x2000) > +FOO (int, xor, ^, 0x2000) > +BAR (int, unsigned int, xor, ^, 0x2000) > +FOO (int64_t, xor, ^, 0x2000) > +BAR (int64_t, uint64_t, xor, ^, 0x2000) > +FOO (__int128_t, xor, ^, 0x2000) > +BAR (__int128_t, __uint128_t, xor, ^, 0x2000) > + > +FOO (char, shl, <<, 0x7) > +BAR (char, unsigned char, shl, <<, 0x7) > +FOO (short, shl, <<, 0x7) > +BAR (short, unsigned short, shl, <<, 0x7) > +FOO (int, shl, <<, 0x7) > +BAR (int, unsigned int, shl, <<, 0x7) > +FOO (int64_t, shl, <<, 0x7) > +BAR (int64_t, uint64_t, shl, <<, 0x7) > +FOO (__int128_t, shl, <<, 0x7) > +BAR (__int128_t, __uint128_t, shl, <<, 0x7) > + > +FOO (char, sar, >>, 0x7) > +BAR (char, unsigned char, sar, >>, 0x7) > +FOO (short, sar, >>, 0x7) > +BAR (short, unsigned short, sar, >>, 0x7) > +FOO (int, sar, >>, 0x7) > +BAR (int, unsigned int, sar, >>, 0x7) > +FOO (int64_t, sar, >>, 0x7) > +BAR (int64_t, uint64_t, sar, >>, 0x7) > +FOO (__int128_t, sar, >>, 0x7) > +BAR (__int128_t, __uint128_t, sar, >>, 0x7) > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c > new file mode 100644 > index 00000000000..5b164ef79a7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c > @@ -0,0 +1,98 @@ > +/* PR target/113711 */ > +/* { dg-do compile { target { ! ia32 } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +#define FOO(TYPE, OP_NAME, OP, IMM) \ > +TYPE \ > +foo_##OP_NAME##_##TYPE (void) \ > +{ \ > + TYPE b = (*(TYPE *) 0x20000) OP IMM; \ > + return b; \ > +} > + > +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ > +int64_t \ > +bar_##OP_NAME##_##TYPE (void) \ > +{ \ > + int64_t b = (*(UTYPE *) 0x20000) OP IMM; \ > + return b; \ > +} > + > +#define SEG(TYPE, OP_NAME, OP, IMM) \ > +TYPE \ > +seg_##OP_NAME##_##TYPE (void) \ > +{ \ > + TYPE b = (*(TYPE __seg_fs *) 0) OP IMM; \ > + return b; \ > +} > + > +FOO (char, add, +, 0x7) > +SEG (char, add, +, 0x7) > +FOO (short, add, +, 0x2000) > +SEG (short, add, +, 0x2000) > +FOO (int, add, +, 0x2000) > +BAR (int, unsigned int, add, +, 0x2000) > +FOO (int64_t, add, +, 0x2000) > +BAR (int64_t, uint64_t, add, +, 0x2000) > + > +FOO (char, sub, -, 0x7) > +SEG (char, sub, -, 0x7) > +FOO (short, sub, -, 0x2000) > +SEG (short, sub, -, 0x2000) > +FOO (int, sub, -, 0x2000) > +BAR (int, unsigned int, sub, -, 0x2000) > +FOO (int64_t, sub, -, 0x2000) > +BAR (int64_t, uint64_t, sub, -, 0x2000) > + > +FOO (char, and, &, 0x7) > +SEG (char, and, &, 0x7) > +FOO (short, and, &, 0x2000) > +SEG (short, and, &, 0x2000) > +FOO (int, and, &, 0x2000) > +BAR (int, unsigned int, and, &, 0x2000) > +FOO (int64_t, and, &, 0x2000) > +BAR (int64_t, uint64_t, and, &, 0x2000) > + > +FOO (char, or, |, 0x7) > +SEG (char, or, |, 0x7) > +FOO (short, or, |, 0x2000) > +SEG (short, or, |, 0x2000) > +FOO (int, or, |, 0x2000) > +BAR (int, unsigned int, or, |, 0x2000) > +FOO (int64_t, or, |, 0x2000) > +BAR (int64_t, uint64_t, or, |, 0x2000) > + > +FOO (char, xor, ^, 0x7) > +SEG (char, xor, ^, 0x7) > +FOO (short, xor, ^, 0x2000) > +SEG (short, xor, ^, 0x2000) > +FOO (int, xor, ^, 0x2000) > +BAR (int, unsigned int, xor, ^, 0x2000) > +FOO (int64_t, xor, ^, 0x2000) > +BAR (int64_t, uint64_t, xor, ^, 0x2000) > + > +FOO (char, shl, <<, 0x7) > +SEG (char, shl, <<, 0x7) > +FOO (short, shl, <<, 0x7) > +SEG (short, shl, <<, 0x7) > +FOO (int, shl, <<, 0x7) > +SEG (int, shl, <<, 0x7) > +BAR (int, unsigned int, shl, <<, 0x7) > +FOO (int64_t, shl, <<, 0x7) > +SEG (int64_t, shl, <<, 0x7) > +BAR (int64_t, uint64_t, shl, <<, 0x7) > + > +FOO (char, sar, >>, 0x7) > +SEG (char, sar, >>, 0x7) > +FOO (short, sar, >>, 0x7) > +SEG (short, sar, >>, 0x7) > +FOO (int, sar, >>, 0x7) > +SEG (int, sar, >>, 0x7) > +BAR (int, unsigned int, sar, >>, 0x7) > +FOO (int64_t, sar, >>, 0x7) > +SEG (int64_t, sar, >>, 0x7) > +BAR (int64_t, uint64_t, sar, >>, 0x7) > + > +/* { dg-final { scan-assembler-not "mov"} } */ > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c > new file mode 100644 > index 00000000000..e7d9c3ca11a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c > @@ -0,0 +1,14 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +typedef signed __int128 S; > +int o; > + > +S > +qux (void) > +{ > + S z; > + o = __builtin_add_overflow (*(S __seg_fs *) 0x1000, 0x200, &z); > + return z; > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c > new file mode 100644 > index 00000000000..a60c4d7d9b6 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c > @@ -0,0 +1,9 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +unsigned __int128 > +foo (void) > +{ > + return *((unsigned __int128 __seg_fs *) 0x1000) + 0x2000; > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c > new file mode 100644 > index 00000000000..9be4e96767c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c > @@ -0,0 +1,13 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +extern int bar __attribute__((__visibility__ ("hidden"))); > + > +uintptr_t > +foo (void) > +{ > + return (*(uintptr_t __seg_fs *) 0x1000) - (uintptr_t) &bar; > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c > new file mode 100644 > index 00000000000..5bf57a76ef7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c > @@ -0,0 +1,41 @@ > +/* PR target/113733 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-mapxf -O3 -w" } */ > + > +extern __thread int a, j; > +enum b > +{ > + c, > + d > +}; > +struct e > +{ > + long f; > + struct > + { > + char g[1024]; > + }; > +} typedef h (); > +long i; > +int o (char *); > +static enum b > +k (int *p) > +{ > + h l; > + struct e n; > + do > + { > + l (n, n.f, p); > + char **m; > + for (; *m; ++m) > + if (o (*m)) > + i = j; > + } > + while (d); > +} > +void > +getgrouplist () > +{ > + k (&a); > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c > new file mode 100644 > index 00000000000..db985940a54 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c > @@ -0,0 +1,38 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#include <stdint.h> > + > +#define DECL(TYPE) \ > +__thread TYPE TYPE##_a = 255; \ > +TYPE * volatile TYPE##_a_in_other_thread = (TYPE *)12345; > + > +DECL(uint64_t) > +DECL(uint32_t) > + > +#define FOO(TYPE, name, op, val) \ > +void * \ > +thread_func##TYPE##name (void *arg) \ > +{ \ > + TYPE##_a_in_other_thread = &TYPE##_a; \ > + TYPE##_a = TYPE##_a op val; \ > + *((TYPE *) arg) = TYPE##_a; \ > + return (void *)0; \ > +} > + > +FOO(uint64_t, add, +, 0x2000) > +FOO(uint32_t, add, +, 0x2000) > + > +FOO(uint64_t, sub, -, 0x2000) > +FOO(uint32_t, sub, -, 0x2000) > + > +FOO(uint64_t, or, |, 0x2000) > +FOO(uint32_t, or, |, 0x2000) > + > +FOO(uint64_t, and, &, 0x2000) > +FOO(uint32_t, and, &, 0x2000) > + > +FOO(uint64_t, xor, ^, 0x2000) > +FOO(uint32_t, xor, ^, 0x2000) > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c > new file mode 100644 > index 00000000000..e7374b44825 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c > @@ -0,0 +1,16 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-mapxf -O2" } */ > + > +typedef signed __int128 S; > +__thread S var; > +int o; > + > +S > +qux (void) > +{ > + S z; > + o = __builtin_add_overflow (var, 0x200, &z); > + return z; > +} > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c > new file mode 100644 > index 00000000000..f3b2eac6a60 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c > @@ -0,0 +1,31 @@ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-mapxf -O2" } */ > + > +#define DECL(TYPE) \ > +extern __thread TYPE TYPE##_a; > + > +DECL(__int128_t) > +DECL(__uint128_t) > + > +#define FOO(TYPE, name, op, val) \ > +TYPE \ > +thread_func##TYPE##name (void) \ > +{ \ > + return TYPE##_a op val; \ > +} > + > +FOO(__int128_t, add, +, 0x2000) > +FOO(__uint128_t, add, +, 0x2000) > + > +FOO(__int128_t, sub, -, 0x2000) > +FOO(__uint128_t, sub, -, 0x2000) > + > +FOO(__int128_t, or, |, 0x2000) > +FOO(__uint128_t, or, |, 0x2000) > + > +FOO(__int128_t, and, &, 0x2000) > +FOO(__uint128_t, and, &, 0x2000) > + > +FOO(__int128_t, xor, ^, 0x2000) > +FOO(__uint128_t, xor, ^, 0x2000) > diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c > new file mode 100644 > index 00000000000..4280d400458 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c > @@ -0,0 +1,49 @@ > +/* PR target/113711 */ > +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ > +/* { dg-require-effective-target maybe_x32 } */ > +/* { dg-options "-mapxf -O2 -mx32" } */ > + > +#include <stdint.h> > + > +#define FOO(TYPE, OP_NAME, OP, IMM) \ > +TYPE \ > +foo_##OP_NAME##_##TYPE (int off, TYPE *ptr) \ > +{ \ > + TYPE b = ptr[off + 0x100] + IMM; \ > + return b; \ > +} > + > +FOO (char, add, +, 0x7) > +FOO (short, add, +, 0x2000) > +FOO (int, add, +, 0x2000) > +FOO (int64_t, add, +, 0x2000) > + > +FOO (char, sub, -, 0x7) > +FOO (short, sub, -, 0x2000) > +FOO (int, sub, -, 0x2000) > +FOO (int64_t, sub, -, 0x2000) > + > +FOO (char, and, &, 0x7) > +FOO (short, and, &, 0x2000) > +FOO (int, and, &, 0x2000) > +FOO (long, and, &, 0x2000) > + > +FOO (char, or, |, 0x7) > +FOO (short, or, |, 0x2000) > +FOO (int, or, |, 0x2000) > +FOO (int64_t, or, |, 0x2000) > + > +FOO (char, xor, ^, 0x7) > +FOO (short, xor, ^, 0x2000) > +FOO (int, xor, ^, 0x2000) > +FOO (long, xor, ^, 0x2000) > + > +FOO (char, shl, <<, 0x7) > +FOO (short, shl, <<, 0x7) > +FOO (int, shl, <<, 0x7) > +FOO (int64_t, shl, <<, 0x7) > + > +FOO (char, sar, >>, 0x7) > +FOO (short, sar, >>, 0x7) > +FOO (int, sar, >>, 0x7) > +FOO (int64_t, sar, >>, 0x7) > -- > 2.43.0 >
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 280e4c8e36c..64702d9c0a8 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -372,6 +372,24 @@ (define_address_constraint "Ts" "Address operand without segment register" (match_operand 0 "address_no_seg_operand")) +;; j prefix is used for APX operand constraints. +;; < Auto-dec memory operand without GPR32. +;; > Auto-inc memory operand without GPR32. +;; a Vector memory operand without GPR32. +;; b VSIB address operand without EGPR. +;; c Integer register. GENERAL_GPR16 for TARGET_APX_EGPR and +;; !TARGET_AVX, otherwise GENERAL_REGS. +;; e Memory operand for APX NDD ADD. +;; j Integer register. GENERAL_GPR16 for TARGET_APX_EGPR, otherwise +;; GENERAL_REGS. +;; o Offsetable memory operand without GPR32. +;; p General address operand without GPR32. +;; m Memory operand without GPR32. +;; M Memory operand, with APX NDD check. +;; R Integer register. GENERAL_REGS. +;; O Offsettable memory operand, with APX NDD check. +;; V Non-offsetable memory operand without GPR32. + ;; Constraint that force to use EGPR, can only adopt to register class. (define_register_constraint "jR" "GENERAL_REGS") @@ -393,7 +411,7 @@ (define_constraint "j<" (match_test "x86_extended_rex2reg_mentioned_p (op)"))))) (define_constraint "j>" - "@internal auto-dec memory operand without GPR32." + "@internal auto-inc memory operand without GPR32." (and (and (match_code "mem") (ior (match_test "GET_CODE (XEXP (op, 0)) == PRE_INC") (match_test "GET_CODE (XEXP (op, 0)) == POST_INC"))) @@ -438,7 +456,15 @@ (define_address_constraint "jb" (define_register_constraint "jc" "TARGET_APX_EGPR && !TARGET_AVX ? GENERAL_GPR16 : GENERAL_REGS") -(define_constraint "je" - "@internal constant that do not allow any unspec global offsets" - (and (match_operand 0 "x86_64_immediate_operand") - (match_test "!x86_poff_operand_p (op)"))) +(define_memory_constraint "je" + "@internal Memory operand for APX NDD ADD." + (match_operand 0 "apx_ndd_add_memory_operand")) + +(define_memory_constraint "jM" + "@internal Memory operand, with APX NDD check." + (match_operand 0 "apx_ndd_memory_operand")) + +(define_memory_constraint "jO" + "@internal Offsettable memory operand, with APX NDD check." + (and (match_operand 0 "apx_ndd_memory_operand") + (match_test "offsettable_nonstrict_memref_p (op)"))) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 34b93773b69..46214a63974 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -66,7 +66,6 @@ extern bool x86_extended_QIreg_mentioned_p (rtx_insn *); extern bool x86_extended_reg_mentioned_p (rtx); extern bool x86_extended_rex2reg_mentioned_p (rtx); extern bool x86_evex_reg_mentioned_p (rtx [], int); -extern bool x86_poff_operand_p (rtx); extern bool x86_maybe_negate_const_int (rtx *, machine_mode); extern machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index b3e7c74846e..706dfe8f5b2 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -23406,31 +23406,6 @@ x86_evex_reg_mentioned_p (rtx operands[], int nops) return false; } -/* Return true when rtx operand does not contain any UNSPEC_*POFF related - constant to avoid APX_NDD instructions excceed encoding length limit. */ -bool -x86_poff_operand_p (rtx operand) -{ - if (GET_CODE (operand) == CONST) - { - rtx op = XEXP (operand, 0); - if (GET_CODE (op) == PLUS) - op = XEXP (op, 0); - - if (GET_CODE (op) == UNSPEC) - { - int unspec = XINT (op, 1); - return (unspec == UNSPEC_NTPOFF - || unspec == UNSPEC_TPOFF - || unspec == UNSPEC_DTPOFF - || unspec == UNSPEC_GOTTPOFF - || unspec == UNSPEC_GOTNTPOFF - || unspec == UNSPEC_INDNTPOFF); - } - } - return false; -} - /* If profitable, negate (without causing overflow) integer constant of mode MODE at location LOC. Return true in this case. */ bool diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a82f2e456fe..d5db538bb6a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6290,10 +6290,10 @@ (define_expand "add<mode>3" }) (define_insn_and_split "*add<dwi>3_doubleword" - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") (plus:<DWI> - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,r"))) + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,r"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)" "#" @@ -6332,7 +6332,7 @@ (define_insn_and_split "*add<dwi>3_doubleword" DONE; } } -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) (define_insn_and_split "*add<dwi>3_doubleword_zext" [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o,&r,&r") @@ -6424,10 +6424,10 @@ (define_insn_and_split "*add<dwi>3_doubleword_concat_zext" "split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[5]);") (define_insn "*add<mode>_1" - [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r,r") + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r") (plus:SWI48 - (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rm,r,m,r") - (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,je,BM"))) + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rje,jM,r") + (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,BM"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)" { @@ -6462,7 +6462,7 @@ (define_insn "*add<mode>_1" : "add{<imodesuffix>}\t{%2, %0|%0, %2}"; } } - [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd") (set (attr "type") (cond [(eq_attr "alternative" "3") (const_string "lea") @@ -6484,10 +6484,10 @@ (define_insn "*add<mode>_1" ;; patterns constructed from addsi_1 to match. (define_insn "addsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r") + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") (zero_extend:DI - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r,r,rm") - (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le,rBMe,re")))) + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r,r,rm,rjM") + (match_operand:SI 2 "x86_64_general_operand" "rBMe,0,le,rBMe,r,e")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands, TARGET_APX_NDD)" @@ -6523,7 +6523,7 @@ (define_insn "addsi_1_zext" : "add{l}\t{%2, %k0|%k0, %2}"; } } - [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd,apx_ndd") (set (attr "type") (cond [(eq_attr "alternative" "2") (const_string "lea") @@ -7463,7 +7463,7 @@ (define_insn_and_split "*addv<dwi>4_doubleword_1" (eq:CCO (plus:<QPWI> (sign_extend:<QPWI> - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,rm")) + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,rjM")) (match_operand:<QPWI> 3 "const_scalar_int_operand" "n,n")) (sign_extend:<QPWI> (plus:<DWI> @@ -7833,18 +7833,19 @@ (define_insn_and_split "*sub<dwi>3_doubleword_zext" [(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) (define_insn "*sub<mode>_1" - [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r,r") (minus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,r") - (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>"))) + (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,rjM,r") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r,<i>,<m>"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, <MODE>mode, operands, TARGET_APX_NDD)" "@ sub{<imodesuffix>}\t{%2, %0|%0, %2} sub{<imodesuffix>}\t{%2, %0|%0, %2} sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "isa" "*,*,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd") (set_attr "type" "alu") (set_attr "mode" "<MODE>")]) @@ -9370,18 +9371,19 @@ (define_insn "@add<mode>3_cc_overflow_1" [(set (reg:CCC FLAGS_REG) (compare:CCC (plus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,r") - (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r<i>,<m>")) + (match_operand:SWI 1 "nonimmediate_operand" "%0,0,rm,rjM,r") + (match_operand:SWI 2 "<general_operand>" "<r><i>,<m>,r,<i>,<m>")) (match_dup 1))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r") + (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>,r,r,r") (plus:SWI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)" "@ add{<imodesuffix>}\t{%2, %0|%0, %2} add{<imodesuffix>}\t{%2, %0|%0, %2} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "isa" "*,*,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd") (set_attr "type" "alu") (set_attr "mode" "<MODE>")]) @@ -9501,10 +9503,10 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1" [(set (reg:CCC FLAGS_REG) (compare:CCC (plus:<DWI> - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o")) + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o")) (match_dup 1))) - (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") + (set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") (plus:<DWI> (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, <DWI>mode, operands, TARGET_APX_NDD)" "#" @@ -9546,7 +9548,7 @@ (define_insn_and_split "*add<dwi>3_doubleword_cc_overflow_1" else operands[6] = gen_rtx_ZERO_EXTEND (<DWI>mode, operands[5]); } -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) ;; x == 0 with zero flag test can be done also as x < 1U with carry flag ;; test, where the latter is preferrable if we have some carry consuming @@ -11690,10 +11692,10 @@ (define_expand "and<mode>3" }) (define_insn_and_split "*and<dwi>3_doubleword" - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") (and:<DWI> - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o"))) + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, <DWI>mode, operands, TARGET_APX_NDD)" "#" @@ -11730,13 +11732,13 @@ (define_insn_and_split "*and<dwi>3_doubleword" DONE; } -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) (define_insn "*anddi_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,?k") + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,?k") (and:DI - (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,rm,r,qm,k") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,re,m,re,m,L,k"))) + (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,rm,rjM,r,qm,k") + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,re,m,r,e,m,L,k"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands, TARGET_APX_NDD)" @@ -11747,11 +11749,12 @@ (define_insn "*anddi_1" and{q}\t{%2, %0|%0, %2} and{q}\t{%2, %1, %0|%0, %1, %2} and{q}\t{%2, %1, %0|%0, %1, %2} + and{q}\t{%2, %1, %0|%0, %1, %2} # #" - [(set_attr "isa" "x64,apx_ndd,x64,x64,apx_ndd,apx_ndd,x64,avx512bw") - (set_attr "type" "alu,alu,alu,alu,alu,alu,imovx,msklog") - (set_attr "length_immediate" "*,*,*,*,*,*,0,*") + [(set_attr "isa" "x64,apx_ndd,x64,x64,apx_ndd,apx_ndd,apx_ndd,x64,avx512bw") + (set_attr "type" "alu,alu,alu,alu,alu,alu,alu,imovx,msklog") + (set_attr "length_immediate" "*,*,*,*,*,*,*,0,*") (set (attr "prefix_rex") (if_then_else (and (eq_attr "type" "imovx") @@ -11759,7 +11762,7 @@ (define_insn "*anddi_1" (match_operand 1 "ext_QIreg_operand"))) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI,SI,DI,DI,DI,DI,SI,DI")]) + (set_attr "mode" "SI,SI,DI,DI,DI,DI,DI,SI,DI")]) (define_insn_and_split "*anddi_1_btr" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -11814,25 +11817,26 @@ (define_split ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*andsi_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") (zero_extend:DI - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,r") - (match_operand:SI 2 "x86_64_general_operand" "rBMe,re,BM")))) + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,rjM,r") + (match_operand:SI 2 "x86_64_general_operand" "rBMe,r,e,BM")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands, TARGET_APX_NDD)" "@ and{l}\t{%2, %k0|%k0, %2} and{l}\t{%2, %1, %k0|%k0, %1, %2} + and{l}\t{%2, %1, %k0|%k0, %1, %2} and{l}\t{%2, %1, %k0|%k0, %1, %2}" [(set_attr "type" "alu") - (set_attr "isa" "*,apx_ndd,apx_ndd") + (set_attr "isa" "*,apx_ndd,apx_ndd,apx_ndd") (set_attr "mode" "SI")]) (define_insn "*and<mode>_1" - [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,Ya,?k") - (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,rm,r,qm,k") - (match_operand:SWI24 2 "<general_operand>" "r<i>,<m>,r<i>,<m>,L,k"))) + [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,r,Ya,?k") + (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,rm,rjM,r,qm,k") + (match_operand:SWI24 2 "<general_operand>" "r<i>,<m>,r,<i>,<m>,L,k"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, <MODE>mode, operands, TARGET_APX_NDD)" "@ @@ -11840,19 +11844,20 @@ (define_insn "*and<mode>_1" and{<imodesuffix>}\t{%2, %0|%0, %2} and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + and{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} # #" [(set (attr "isa") - (cond [(eq_attr "alternative" "2,3") + (cond [(eq_attr "alternative" "2,3,4") (const_string "apx_ndd") - (eq_attr "alternative" "5") + (eq_attr "alternative" "6") (if_then_else (eq_attr "mode" "SI") (const_string "avx512bw") (const_string "avx512f")) ] (const_string "*"))) - (set_attr "type" "alu,alu,alu,alu,imovx,msklog") - (set_attr "length_immediate" "*,*,*,*,0,*") + (set_attr "type" "alu,alu,alu,alu,alu,imovx,msklog") + (set_attr "length_immediate" "*,*,*,*,*,0,*") (set (attr "prefix_rex") (if_then_else (and (eq_attr "type" "imovx") @@ -11860,7 +11865,7 @@ (define_insn "*and<mode>_1" (match_operand 1 "ext_QIreg_operand"))) (const_string "1") (const_string "*"))) - (set_attr "mode" "<MODE>,<MODE>,<MODE>,<MODE>,SI,<MODE>")]) + (set_attr "mode" "<MODE>,<MODE>,<MODE>,<MODE>,<MODE>,SI,<MODE>")]) (define_insn "*andqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r,r,?k") @@ -12677,10 +12682,10 @@ (define_expand "<code><mode>3" }) (define_insn_and_split "*<code><dwi>3_doubleword" - [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r") + [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=ro,r,&r,&r,&r") (any_or:<DWI> - (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,r") - (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r<di>,o"))) + (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0,ro,rjO,r") + (match_operand:<DWI> 2 "x86_64_hilo_general_operand" "r<di>,o,r,<di>,o"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (<CODE>, <DWI>mode, operands, TARGET_APX_NDD)" "#" @@ -12733,13 +12738,13 @@ (define_insn_and_split "*<code><dwi>3_doubleword" DONE; } -[(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) +[(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd")]) (define_insn "*<code><mode>_1" - [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,?k") + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,?k") (any_or:SWI248 - (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,rm,r,k") - (match_operand:SWI248 2 "<general_operand>" "r<i>,<m>,r<i>,<m>,k"))) + (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,rm,rjM,r,k") + (match_operand:SWI248 2 "<general_operand>" "r<i>,<m>,r,<i>,<m>,k"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands, TARGET_APX_NDD)" "@ @@ -12747,9 +12752,10 @@ (define_insn "*<code><mode>_1" <logic>{<imodesuffix>}\t{%2, %0|%0, %2} <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} + <logic>{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2} #" - [(set_attr "isa" "*,*,apx_ndd,apx_ndd,<kmov_isa>") - (set_attr "type" "alu, alu, alu, alu, msklog") + [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,<kmov_isa>") + (set_attr "type" "alu, alu, alu, alu, alu, msklog") (set_attr "mode" "<MODE>")]) (define_insn_and_split "*notxor<mode>_1" @@ -12864,19 +12870,20 @@ (define_insn_and_split "*xor2andn" ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*<code>si_1_zext" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") (zero_extend:DI - (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,r") - (match_operand:SI 2 "x86_64_general_operand" "rBMe,re,BM")))) + (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm,rjM,r") + (match_operand:SI 2 "x86_64_general_operand" "rBMe,r,e,BM")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands, TARGET_APX_NDD)" "@ <logic>{l}\t{%2, %k0|%k0, %2} <logic>{l}\t{%2, %1, %k0|%k0, %1, %2} + <logic>{l}\t{%2, %1, %k0|%k0, %1, %2} <logic>{l}\t{%2, %1, %k0|%k0, %1, %2}" [(set_attr "type" "alu") - (set_attr "isa" "*,apx_ndd,apx_ndd") + (set_attr "isa" "*,apx_ndd,apx_ndd,apx_ndd") (set_attr "mode" "SI")]) (define_insn "*<code>si_1_zext_imm" diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 06027a84532..4c1aedd7e70 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -2248,3 +2248,68 @@ (define_predicate "aeswidekl_operation" } return true; }) + +;; Return true if OP is a memory operand that can be also used in APX +;; NDD patterns with immediate operand. With non-default address space, +;; segment register or address size prefix, APX NDD instruction length +;; can exceed the 15 byte size limit. +(define_predicate "apx_ndd_memory_operand" + (match_operand 0 "memory_operand") +{ + /* OK if immediate operand size < 4 bytes. */ + if (GET_MODE_SIZE (mode) < 4) + return true; + + bool default_addr = ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (op)); + bool address_size_prefix = TARGET_X32 && Pmode == SImode; + + struct ix86_address parts; + int ok; + + op = XEXP (op, 0); + ok = ix86_decompose_address (op, &parts); + gcc_assert (ok); + + if (default_addr) + { + /* Default address space. */ + + /* Not OK with address size prefix, index register and disp. */ + if (address_size_prefix + && parts.index + && parts.disp + && parts.disp != const0_rtx) + return false; + } + else + { + /* Non-default address space. */ + + /* Not OK without base register. */ + if (!parts.base) + return false; + + /* Not OK with disp and address size prefix. */ + if (address_size_prefix && parts.disp) + return false; + } + + return true; +}) + +;; Return true if OP is a memory operand which can be used in APX NDD +;; ADD with register source operand. UNSPEC_GOTNTPOFF memory operand +;; isn't allowed with APX NDD ADD. +(define_predicate "apx_ndd_add_memory_operand" + (match_operand 0 "memory_operand") +{ + op = XEXP (op, 0); + + /* Disallow APX NDD ADD with UNSPEC_GOTNTPOFF. */ + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == UNSPEC + && XINT (XEXP (op, 0), 1) == UNSPEC_GOTNTPOFF) + return false; + + return true; +}) diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-2.c new file mode 100644 index 00000000000..3a5272d065e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-2.c @@ -0,0 +1,17 @@ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-options "-mapxf -O3 -w" } */ + +long a; +int b, d, e; +void +g (void) +{ + int c; + _Bool f; + __asm__("" : "=c"(c)); + switch (d) + case 2: + e = f = c & 2; + if (f) + a = b; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c new file mode 100644 index 00000000000..208acd36958 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-base-index-1.c @@ -0,0 +1,50 @@ +/* PR target/113711 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +#define FOO(TYPE, OP_NAME, OP, IMM) \ +TYPE \ +foo_##OP_NAME##_##TYPE (TYPE *p, int64_t off) \ +{ \ + TYPE b = p[off] OP IMM; \ + return b; \ +} + +FOO (char, add, +, 0x7) +FOO (short, add, +, 0x2000) +FOO (int, add, +, 0x2000) +FOO (int64_t, add, +, 0x2000) + +FOO (char, sub, -, 0x7) +FOO (short, sub, -, 0x2000) +FOO (int, sub, -, 0x2000) +FOO (int64_t, sub, -, 0x2000) + +FOO (char, and, &, 0x7) +FOO (short, and, &, 0x2000) +FOO (int, and, &, 0x2000) +FOO (int64_t, and, &, 0x2000) + +FOO (char, or, |, 0x7) +FOO (short, or, |, 0x2000) +FOO (int, or, |, 0x2000) +FOO (int64_t, or, |, 0x2000) + +FOO (char, xor, ^, 0x7) +FOO (short, xor, ^, 0x2000) +FOO (int, xor, ^, 0x2000) +FOO (int64_t, xor, ^, 0x2000) + +FOO (char, shl, <<, 0x7) +FOO (short, shl, <<, 0x7) +FOO (int, shl, <<, 0x7) +FOO (int64_t, shl, <<, 0x7) + +FOO (char, sar, >>, 0x7) +FOO (short, sar, >>, 0x7) +FOO (int, sar, >>, 0x7) +FOO (int64_t, sar, >>, 0x7) + +/* { dg-final { scan-assembler-not "mov"} } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c new file mode 100644 index 00000000000..d2a4040975a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-no-seg-global-1.c @@ -0,0 +1,74 @@ +/* PR target/113711 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +#define FOO(TYPE, OP_NAME, OP, IMM) \ +extern TYPE foo_##OP_NAME##_##TYPE##_var; \ +TYPE \ +foo_##OP_NAME##_##TYPE (void) \ +{ \ + TYPE b = foo_##OP_NAME##_##TYPE##_var OP IMM; \ + return b; \ +} + +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ +extern UTYPE bar_##OP_NAME##_##TYPE##_var; \ +int64_t \ +bar_##OP_NAME##_##TYPE (void) \ +{ \ + int64_t b = bar_##OP_NAME##_##TYPE##_var OP IMM; \ + return b; \ +} + +FOO (char, add, +, 0x7) +FOO (short, add, +, 0x2000) +FOO (int, add, +, 0x2000) +BAR (int, unsigned int, add, +, 0x2000) +FOO (int64_t, add, +, 0x2000) +BAR (int64_t, uint64_t, add, +, 0x2000) + +FOO (char, sub, -, 0x7) +FOO (short, sub, -, 0x2000) +FOO (int, sub, -, 0x2000) +BAR (int, unsigned int, sub, -, 0x2000) +FOO (int64_t, sub, -, 0x2000) +BAR (int64_t, uint64_t, sub, -, 0x2000) + +FOO (char, and, &, 0x7) +FOO (short, and, &, 0x2000) +FOO (int, and, &, 0x2000) +BAR (int, unsigned int, and, &, 0x2000) +FOO (int64_t, and, &, 0x2000) +BAR (int64_t, uint64_t, and, &, 0x2000) + +FOO (char, or, |, 0x7) +FOO (short, or, |, 0x2000) +FOO (int, or, |, 0x2000) +BAR (int, unsigned int, or, |, 0x2000) +FOO (int64_t, or, |, 0x2000) +BAR (int64_t, uint64_t, or, |, 0x2000) + +FOO (char, xor, ^, 0x7) +FOO (short, xor, ^, 0x2000) +FOO (int, xor, ^, 0x2000) +BAR (int, unsigned int, xor, ^, 0x2000) +FOO (int64_t, xor, ^, 0x2000) +BAR (int64_t, uint64_t, xor, ^, 0x2000) + +FOO (char, shl, <<, 0x7) +FOO (short, shl, <<, 0x7) +FOO (int, shl, <<, 0x7) +BAR (int, unsigned int, shl, <<, 0x7) +FOO (int64_t, shl, <<, 0x7) +BAR (int64_t, uint64_t, shl, <<, 0x7) + +FOO (char, sar, >>, 0x7) +FOO (short, sar, >>, 0x7) +FOO (int, sar, >>, 0x7) +BAR (int, unsigned int, sar, >>, 0x7) +FOO (int64_t, sar, >>, 0x7) +BAR (int64_t, uint64_t, sar, >>, 0x7) + +/* { dg-final { scan-assembler-not "mov"} } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c new file mode 100644 index 00000000000..d18055a9250 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-1.c @@ -0,0 +1,98 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +#define FOO(TYPE, OP_NAME, OP, IMM) \ +TYPE \ +foo_##OP_NAME##_##TYPE (void) \ +{ \ + TYPE b = (*(TYPE __seg_fs *) 0) OP IMM; \ + return b; \ +} + +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ +int64_t \ +bar_##OP_NAME##_##TYPE (void) \ +{ \ + int64_t b = (*(UTYPE __seg_fs *) 0) OP IMM; \ + return b; \ +} + +FOO (char, add, +, 0x7) +BAR (char, unsigned char, add, +, 0x7) +FOO (short, add, +, 0x2000) +BAR (short, unsigned short, add, +, 0x2000) +FOO (int, add, +, 0x2000) +BAR (int, unsigned int, add, +, 0x2000) +FOO (int64_t, add, +, 0x2000) +BAR (int64_t, uint64_t, add, +, 0x2000) +FOO (__int128_t, add, +, 0x2000) +BAR (__int128_t, __uint128_t, add, +, 0x2000) + +FOO (char, sub, -, 0x7) +BAR (char, unsigned char, sub, -, 0x7) +FOO (short, sub, -, 0x2000) +BAR (short, unsigned short, sub, -, 0x2000) +FOO (int, sub, -, 0x2000) +BAR (int, unsigned int, sub, -, 0x2000) +FOO (int64_t, sub, -, 0x2000) +BAR (int64_t, uint64_t, sub, -, 0x2000) +FOO (__int128_t, sub, -, 0x2000) +BAR (__int128_t, __uint128_t, sun, -, 0x2000) + +FOO (char, and, &, 0x7) +BAR (char, unsigned char, and, &, 0x7) +FOO (short, and, &, 0x2000) +BAR (short, unsigned short, and, &, 0x2000) +FOO (int, and, &, 0x2000) +BAR (int, unsigned int, and, &, 0x2000) +FOO (int64_t, and, &, 0x2000) +BAR (int64_t, uint64_t, and, &, 0x2000) +FOO (__int128_t, and, &, 0x2000) +BAR (__int128_t, __uint128_t, and, &, 0x2000) + +FOO (char, or, |, 0x7) +BAR (char, unsigned char, or, |, 0x7) +FOO (short, or, |, 0x2000) +BAR (short, unsigned short, or, |, 0x2000) +FOO (int, or, |, 0x2000) +BAR (int, unsigned int, or, |, 0x2000) +FOO (int64_t, or, |, 0x2000) +BAR (int64_t, uint64_t, or, |, 0x2000) +FOO (__int128_t, or, |, 0x2000) +BAR (__int128_t, __uint128_t, or, |, 0x2000) + +FOO (char, xor, ^, 0x7) +BAR (char, unsigned char, xor, ^, 0x7) +FOO (short, xor, ^, 0x2000) +BAR (short, unsigned short, xor, ^, 0x2000) +FOO (int, xor, ^, 0x2000) +BAR (int, unsigned int, xor, ^, 0x2000) +FOO (int64_t, xor, ^, 0x2000) +BAR (int64_t, uint64_t, xor, ^, 0x2000) +FOO (__int128_t, xor, ^, 0x2000) +BAR (__int128_t, __uint128_t, xor, ^, 0x2000) + +FOO (char, shl, <<, 0x7) +BAR (char, unsigned char, shl, <<, 0x7) +FOO (short, shl, <<, 0x7) +BAR (short, unsigned short, shl, <<, 0x7) +FOO (int, shl, <<, 0x7) +BAR (int, unsigned int, shl, <<, 0x7) +FOO (int64_t, shl, <<, 0x7) +BAR (int64_t, uint64_t, shl, <<, 0x7) +FOO (__int128_t, shl, <<, 0x7) +BAR (__int128_t, __uint128_t, shl, <<, 0x7) + +FOO (char, sar, >>, 0x7) +BAR (char, unsigned char, sar, >>, 0x7) +FOO (short, sar, >>, 0x7) +BAR (short, unsigned short, sar, >>, 0x7) +FOO (int, sar, >>, 0x7) +BAR (int, unsigned int, sar, >>, 0x7) +FOO (int64_t, sar, >>, 0x7) +BAR (int64_t, uint64_t, sar, >>, 0x7) +FOO (__int128_t, sar, >>, 0x7) +BAR (__int128_t, __uint128_t, sar, >>, 0x7) diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c new file mode 100644 index 00000000000..5b164ef79a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-2.c @@ -0,0 +1,98 @@ +/* PR target/113711 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +#define FOO(TYPE, OP_NAME, OP, IMM) \ +TYPE \ +foo_##OP_NAME##_##TYPE (void) \ +{ \ + TYPE b = (*(TYPE *) 0x20000) OP IMM; \ + return b; \ +} + +#define BAR(TYPE, UTYPE, OP_NAME, OP, IMM) \ +int64_t \ +bar_##OP_NAME##_##TYPE (void) \ +{ \ + int64_t b = (*(UTYPE *) 0x20000) OP IMM; \ + return b; \ +} + +#define SEG(TYPE, OP_NAME, OP, IMM) \ +TYPE \ +seg_##OP_NAME##_##TYPE (void) \ +{ \ + TYPE b = (*(TYPE __seg_fs *) 0) OP IMM; \ + return b; \ +} + +FOO (char, add, +, 0x7) +SEG (char, add, +, 0x7) +FOO (short, add, +, 0x2000) +SEG (short, add, +, 0x2000) +FOO (int, add, +, 0x2000) +BAR (int, unsigned int, add, +, 0x2000) +FOO (int64_t, add, +, 0x2000) +BAR (int64_t, uint64_t, add, +, 0x2000) + +FOO (char, sub, -, 0x7) +SEG (char, sub, -, 0x7) +FOO (short, sub, -, 0x2000) +SEG (short, sub, -, 0x2000) +FOO (int, sub, -, 0x2000) +BAR (int, unsigned int, sub, -, 0x2000) +FOO (int64_t, sub, -, 0x2000) +BAR (int64_t, uint64_t, sub, -, 0x2000) + +FOO (char, and, &, 0x7) +SEG (char, and, &, 0x7) +FOO (short, and, &, 0x2000) +SEG (short, and, &, 0x2000) +FOO (int, and, &, 0x2000) +BAR (int, unsigned int, and, &, 0x2000) +FOO (int64_t, and, &, 0x2000) +BAR (int64_t, uint64_t, and, &, 0x2000) + +FOO (char, or, |, 0x7) +SEG (char, or, |, 0x7) +FOO (short, or, |, 0x2000) +SEG (short, or, |, 0x2000) +FOO (int, or, |, 0x2000) +BAR (int, unsigned int, or, |, 0x2000) +FOO (int64_t, or, |, 0x2000) +BAR (int64_t, uint64_t, or, |, 0x2000) + +FOO (char, xor, ^, 0x7) +SEG (char, xor, ^, 0x7) +FOO (short, xor, ^, 0x2000) +SEG (short, xor, ^, 0x2000) +FOO (int, xor, ^, 0x2000) +BAR (int, unsigned int, xor, ^, 0x2000) +FOO (int64_t, xor, ^, 0x2000) +BAR (int64_t, uint64_t, xor, ^, 0x2000) + +FOO (char, shl, <<, 0x7) +SEG (char, shl, <<, 0x7) +FOO (short, shl, <<, 0x7) +SEG (short, shl, <<, 0x7) +FOO (int, shl, <<, 0x7) +SEG (int, shl, <<, 0x7) +BAR (int, unsigned int, shl, <<, 0x7) +FOO (int64_t, shl, <<, 0x7) +SEG (int64_t, shl, <<, 0x7) +BAR (int64_t, uint64_t, shl, <<, 0x7) + +FOO (char, sar, >>, 0x7) +SEG (char, sar, >>, 0x7) +FOO (short, sar, >>, 0x7) +SEG (short, sar, >>, 0x7) +FOO (int, sar, >>, 0x7) +SEG (int, sar, >>, 0x7) +BAR (int, unsigned int, sar, >>, 0x7) +FOO (int64_t, sar, >>, 0x7) +SEG (int64_t, sar, >>, 0x7) +BAR (int64_t, uint64_t, sar, >>, 0x7) + +/* { dg-final { scan-assembler-not "mov"} } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c new file mode 100644 index 00000000000..e7d9c3ca11a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-3.c @@ -0,0 +1,14 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-options "-mapxf -O2" } */ + +typedef signed __int128 S; +int o; + +S +qux (void) +{ + S z; + o = __builtin_add_overflow (*(S __seg_fs *) 0x1000, 0x200, &z); + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c new file mode 100644 index 00000000000..a60c4d7d9b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-4.c @@ -0,0 +1,9 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-options "-mapxf -O2" } */ + +unsigned __int128 +foo (void) +{ + return *((unsigned __int128 __seg_fs *) 0x1000) + 0x2000; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c new file mode 100644 index 00000000000..9be4e96767c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-seg-5.c @@ -0,0 +1,13 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +extern int bar __attribute__((__visibility__ ("hidden"))); + +uintptr_t +foo (void) +{ + return (*(uintptr_t __seg_fs *) 0x1000) - (uintptr_t) &bar; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c new file mode 100644 index 00000000000..5bf57a76ef7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-1a.c @@ -0,0 +1,41 @@ +/* PR target/113733 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-require-effective-target tls } */ +/* { dg-options "-mapxf -O3 -w" } */ + +extern __thread int a, j; +enum b +{ + c, + d +}; +struct e +{ + long f; + struct + { + char g[1024]; + }; +} typedef h (); +long i; +int o (char *); +static enum b +k (int *p) +{ + h l; + struct e n; + do + { + l (n, n.f, p); + char **m; + for (; *m; ++m) + if (o (*m)) + i = j; + } + while (d); +} +void +getgrouplist () +{ + k (&a); +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c new file mode 100644 index 00000000000..db985940a54 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-2.c @@ -0,0 +1,38 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-require-effective-target tls } */ +/* { dg-options "-mapxf -O2" } */ + +#include <stdint.h> + +#define DECL(TYPE) \ +__thread TYPE TYPE##_a = 255; \ +TYPE * volatile TYPE##_a_in_other_thread = (TYPE *)12345; + +DECL(uint64_t) +DECL(uint32_t) + +#define FOO(TYPE, name, op, val) \ +void * \ +thread_func##TYPE##name (void *arg) \ +{ \ + TYPE##_a_in_other_thread = &TYPE##_a; \ + TYPE##_a = TYPE##_a op val; \ + *((TYPE *) arg) = TYPE##_a; \ + return (void *)0; \ +} + +FOO(uint64_t, add, +, 0x2000) +FOO(uint32_t, add, +, 0x2000) + +FOO(uint64_t, sub, -, 0x2000) +FOO(uint32_t, sub, -, 0x2000) + +FOO(uint64_t, or, |, 0x2000) +FOO(uint32_t, or, |, 0x2000) + +FOO(uint64_t, and, &, 0x2000) +FOO(uint32_t, and, &, 0x2000) + +FOO(uint64_t, xor, ^, 0x2000) +FOO(uint32_t, xor, ^, 0x2000) diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c new file mode 100644 index 00000000000..e7374b44825 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-3.c @@ -0,0 +1,16 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-require-effective-target tls } */ +/* { dg-options "-mapxf -O2" } */ + +typedef signed __int128 S; +__thread S var; +int o; + +S +qux (void) +{ + S z; + o = __builtin_add_overflow (var, 0x200, &z); + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c new file mode 100644 index 00000000000..f3b2eac6a60 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-tls-4.c @@ -0,0 +1,31 @@ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-require-effective-target tls } */ +/* { dg-options "-mapxf -O2" } */ + +#define DECL(TYPE) \ +extern __thread TYPE TYPE##_a; + +DECL(__int128_t) +DECL(__uint128_t) + +#define FOO(TYPE, name, op, val) \ +TYPE \ +thread_func##TYPE##name (void) \ +{ \ + return TYPE##_a op val; \ +} + +FOO(__int128_t, add, +, 0x2000) +FOO(__uint128_t, add, +, 0x2000) + +FOO(__int128_t, sub, -, 0x2000) +FOO(__uint128_t, sub, -, 0x2000) + +FOO(__int128_t, or, |, 0x2000) +FOO(__uint128_t, or, |, 0x2000) + +FOO(__int128_t, and, &, 0x2000) +FOO(__uint128_t, and, &, 0x2000) + +FOO(__int128_t, xor, ^, 0x2000) +FOO(__uint128_t, xor, ^, 0x2000) diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c new file mode 100644 index 00000000000..4280d400458 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ndd-x32-1.c @@ -0,0 +1,49 @@ +/* PR target/113711 */ +/* { dg-do assemble { target { apxf && { ! ia32 } } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-mapxf -O2 -mx32" } */ + +#include <stdint.h> + +#define FOO(TYPE, OP_NAME, OP, IMM) \ +TYPE \ +foo_##OP_NAME##_##TYPE (int off, TYPE *ptr) \ +{ \ + TYPE b = ptr[off + 0x100] + IMM; \ + return b; \ +} + +FOO (char, add, +, 0x7) +FOO (short, add, +, 0x2000) +FOO (int, add, +, 0x2000) +FOO (int64_t, add, +, 0x2000) + +FOO (char, sub, -, 0x7) +FOO (short, sub, -, 0x2000) +FOO (int, sub, -, 0x2000) +FOO (int64_t, sub, -, 0x2000) + +FOO (char, and, &, 0x7) +FOO (short, and, &, 0x2000) +FOO (int, and, &, 0x2000) +FOO (long, and, &, 0x2000) + +FOO (char, or, |, 0x7) +FOO (short, or, |, 0x2000) +FOO (int, or, |, 0x2000) +FOO (int64_t, or, |, 0x2000) + +FOO (char, xor, ^, 0x7) +FOO (short, xor, ^, 0x2000) +FOO (int, xor, ^, 0x2000) +FOO (long, xor, ^, 0x2000) + +FOO (char, shl, <<, 0x7) +FOO (short, shl, <<, 0x7) +FOO (int, shl, <<, 0x7) +FOO (int64_t, shl, <<, 0x7) + +FOO (char, sar, >>, 0x7) +FOO (short, sar, >>, 0x7) +FOO (int, sar, >>, 0x7) +FOO (int64_t, sar, >>, 0x7)