Don't allow mask/sse/mmx mov in TLS code sequences.
Commit Message
>Why is the above declared as a special memory constraint? Also the
Change to define_memory_constraint since it's ok for
reload can make them match by converting the operand to the form
‘(mem (reg X))’.where X is a base register (from the register class specified
by BASE_REG_CLASS
>predicate comment is missing and the description should say something
>like:
>
>@internal TLS address that allows insn using non-integer registers
Changed.
>I think it is better to avoid negative logic. So, something like
>
>Return true if the TLS address requires insn using integer registers.
>
>bool
>ix86_gpr_tls_address_pattern_p
>
>(and use not in the predicate)
Changed.
>> +{
>> + gcc_assert (MEM_P (mem));
>> +
>> + rtx addr = XEXP (mem, 0);
>> + subrtx_var_iterator::array_type array;
>> + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
>> + {
>> + rtx op = *iter;
>> + if (GET_CODE (op) == UNSPEC)
>> + switch (XINT (op, 1))
>> + {
>> + case UNSPEC_GOTNTPOFF:
>> + return false;
>> + case UNSPEC_TPOFF:
>> + if (!TARGET_64BIT)
>> + return false;
>> + break;
>> + default:
>> + break;
>> + }
>> + /* Should iter.skip_subrtxes ();
>> + if there's no inner UNSPEC in addr???. */
>You should figure the above before submitting the patch.
ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so
remove comments.
>Can you please minimize the testcase?
Done;
As change in assembler, refer to [1], this patch disallow mask/sse/mmx
mov in TLS code sequences which require integer MOV instructions.
[1] https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d7e3e627027fcf37d63e284144fe27ff4eba36b5
gcc/ChangeLog:
PR target/103275
* config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p):
Declare.
* config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New
function.
* config/i386/i386.md (*movsi_internal): Don't allow
mask/sse/mmx move in TLS code sequences.
(*movdi_internal): Ditto.
gcc/testsuite/ChangeLog:
* gcc.target/i386/pr103275.c: New test.
---
gcc/config/i386/constraints.md | 5 ++
gcc/config/i386/i386-protos.h | 1 +
gcc/config/i386/i386.c | 32 +++++++++
gcc/config/i386/i386.md | 18 ++---
gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++
5 files changed, 130 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c
Comments
On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote:
>
> >Why is the above declared as a special memory constraint? Also the
> Change to define_memory_constraint since it's ok for
> reload can make them match by converting the operand to the form
> ‘(mem (reg X))’.where X is a base register (from the register class specified
> by BASE_REG_CLASS
>
> >predicate comment is missing and the description should say something
> >like:
> >
> >@internal TLS address that allows insn using non-integer registers
> Changed.
>
> >I think it is better to avoid negative logic. So, something like
> >
> >Return true if the TLS address requires insn using integer registers.
> >
> >bool
> >ix86_gpr_tls_address_pattern_p
> >
> >(and use not in the predicate)
>
> Changed.
>
> >> +{
> >> + gcc_assert (MEM_P (mem));
> >> +
> >> + rtx addr = XEXP (mem, 0);
> >> + subrtx_var_iterator::array_type array;
> >> + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> >> + {
> >> + rtx op = *iter;
> >> + if (GET_CODE (op) == UNSPEC)
> >> + switch (XINT (op, 1))
> >> + {
> >> + case UNSPEC_GOTNTPOFF:
> >> + return false;
> >> + case UNSPEC_TPOFF:
> >> + if (!TARGET_64BIT)
> >> + return false;
> >> + break;
> >> + default:
> >> + break;
> >> + }
> >> + /* Should iter.skip_subrtxes ();
> >> + if there's no inner UNSPEC in addr???. */
>
> >You should figure the above before submitting the patch.
> ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so
> remove comments.
>
> >Can you please minimize the testcase?
> Done;
>
> As change in assembler, refer to [1], this patch disallow mask/sse/mmx
> mov in TLS code sequences which require integer MOV instructions.
>
> [1] https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d7e3e627027fcf37d63e284144fe27ff4eba36b5
>
> gcc/ChangeLog:
>
> PR target/103275
> * config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p):
> Declare.
> * config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New
> function.
> * config/i386/i386.md (*movsi_internal): Don't allow
> mask/sse/mmx move in TLS code sequences.
> (*movdi_internal): Ditto.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/i386/pr103275.c: New test.
OK, with a small comment adjustment below.
Thanks,
Uros.
> ---
> gcc/config/i386/constraints.md | 5 ++
> gcc/config/i386/i386-protos.h | 1 +
> gcc/config/i386/i386.c | 32 +++++++++
> gcc/config/i386/i386.md | 18 ++---
> gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++
> 5 files changed, 130 insertions(+), 9 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c
>
> diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> index eaa582d2055..15c5950ee6f 100644
> --- a/gcc/config/i386/constraints.md
> +++ b/gcc/config/i386/constraints.md
> @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc"
> (and (match_operand 0 "memory_operand")
> (match_test "constant_address_p (XEXP (op, 0))")))
>
> +(define_memory_constraint "Bk"
> + "@internal TLS address that allows insn using non-integer registers."
> + (and (match_operand 0 "memory_operand")
> + (not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
> +
> (define_special_memory_constraint "Bn"
> "@internal Memory operand without REX prefix."
> (match_operand 0 "norex_memory_operand"))
> diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> index 7782cf1163f..941e91636d8 100644
> --- a/gcc/config/i386/i386-protos.h
> +++ b/gcc/config/i386/i386-protos.h
> @@ -240,6 +240,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
> #endif
>
> extern rtx ix86_tls_module_base (void);
> +extern bool ix86_gpr_tls_address_pattern_p (rtx);
> extern bool ix86_tls_address_pattern_p (rtx);
> extern rtx ix86_rewrite_tls_address (rtx);
>
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 42c47d2b12b..68079e4230e 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -11468,6 +11468,38 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
> return dest;
> }
>
> +/* Return true if the TLS address requires insn using integer registers.
> + NB: it's different from ix86_tls_address_pattern_p since it also matchs
> + gottpoff/gotntpoff.
The above NB comment is not needed, the fact is obvious from the code.
> + It's used to prevent KMOV/VMOV in TLS code sequences which require integer
> + MOV instructions, refer to PR103275. */
> +bool
> +ix86_gpr_tls_address_pattern_p (rtx mem)
> +{
> + gcc_assert (MEM_P (mem));
> +
> + rtx addr = XEXP (mem, 0);
> + subrtx_var_iterator::array_type array;
> + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> + {
> + rtx op = *iter;
> + if (GET_CODE (op) == UNSPEC)
> + switch (XINT (op, 1))
> + {
> + case UNSPEC_GOTNTPOFF:
> + return true;
> + case UNSPEC_TPOFF:
> + if (!TARGET_64BIT)
> + return true;
> + break;
> + default:
> + break;
> + }
> + }
> +
> + return false;
> +}
> +
> /* Return true if OP refers to a TLS address. */
> bool
> ix86_tls_address_pattern_p (rtx op)
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index 97325e38676..82b85b26059 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -2085,9 +2085,9 @@ (define_split
>
> (define_insn "*movdi_internal"
> [(set (match_operand:DI 0 "nonimmediate_operand"
> - "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
> + "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k,*k ,*r,*m,*k")
> (match_operand:DI 1 "general_operand"
> - "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
> + "riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*k,*Bk,*k,*k,CBC"))]
> "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> && ix86_hardreg_mov_ok (operands[0], operands[1])"
> {
> @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal"
> [(set (attr "isa")
> (cond [(eq_attr "alternative" "0,1,17,18")
> (const_string "nox64")
> - (eq_attr "alternative" "2,3,4,5,10,11,23,25")
> + (eq_attr "alternative" "2,3,4,5,10,11,23,26")
> (const_string "x64")
> (eq_attr "alternative" "19,20")
> (const_string "x64_sse2")
> @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal"
> (const_string "ssemov")
> (eq_attr "alternative" "21,22")
> (const_string "ssecvt")
> - (eq_attr "alternative" "23,24,25,26")
> + (eq_attr "alternative" "23,24,25,26,27")
> (const_string "mskmov")
> - (eq_attr "alternative" "27")
> + (eq_attr "alternative" "28")
> (const_string "msklog")
> (and (match_operand 0 "register_operand")
> (match_operand 1 "pic_32bit_operand"))
> @@ -2306,9 +2306,9 @@ (define_peephole2
>
> (define_insn "*movsi_internal"
> [(set (match_operand:SI 0 "nonimmediate_operand"
> - "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
> + "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*k,*rm,*k")
> (match_operand:SI 1 "general_operand"
> - "g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
> + "g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*k, *Bk,*k ,CBC"))]
> "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> && ix86_hardreg_mov_ok (operands[0], operands[1])"
> {
> @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal"
> (const_string "sselog1")
> (eq_attr "alternative" "9,10,11,12,13")
> (const_string "ssemov")
> - (eq_attr "alternative" "14,15,16")
> + (eq_attr "alternative" "14,15,16,17")
> (const_string "mskmov")
> - (eq_attr "alternative" "17")
> + (eq_attr "alternative" "18")
> (const_string "msklog")
> (and (match_operand 0 "register_operand")
> (match_operand 1 "pic_32bit_operand"))
> diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c
> new file mode 100644
> index 00000000000..c93413f3cde
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr103275.c
> @@ -0,0 +1,83 @@
> +/* { dg-do compile { target ia32 } } */
> +/* { dg-options "-O2 -march=tigerlake -fPIC" } */
> +/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
> +
> +typedef unsigned short uint16_t;
> +typedef int int32_t;
> +typedef unsigned int uint32_t;
> +typedef unsigned char uint8_t;
> +
> +typedef uint32_t in_addr_t;
> +struct in_addr { in_addr_t s_addr; };
> +
> +extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
> +extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
> +
> +extern unsigned long strtoul (const char*, char**, int);
> +extern uint32_t __bswap_32 (in_addr_t);
> +int
> +inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
> +{
> + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
> + in_addr_t val;
> + char c;
> + union iaddr
> + {
> + uint8_t bytes[4];
> + uint32_t word;
> + } res;
> + uint8_t *pp = res.bytes;
> + int digit;
> +
> + int saved_errno = __libc_errno;
> + __libc_errno = 0;
> + res.word = 0;
> + c = *cp;
> +
> + for (;;)
> + {
> + if (c < '0' || c > '9')
> + goto ret_0;
> + {
> + char *endp;
> + unsigned long ul = strtoul (cp, &endp, 0);
> + if (ul == 0x7fffffffL && __libc_errno == 34)
> + goto ret_0;
> + if (ul > 0xfffffffful)
> + goto ret_0;
> + val = ul;
> + digit = cp != endp;
> + cp = endp;
> + }
> + c = *cp;
> + if (c == '.')
> + {
> + if (pp > res.bytes + 2 || val > 0xff)
> + goto ret_0;
> + *pp++ = val;
> + c = *++cp;
> + }
> + else
> + break;
> + }
> +
> + if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
> + goto ret_0;
> +
> + if (!digit)
> + goto ret_0;
> +
> + if (val > max[pp - res.bytes])
> + goto ret_0;
> +
> + if (addr != 0)
> + addr->s_addr = res.word | __bswap_32 (val);
> + *endp = cp;
> +
> + __libc_errno = saved_errno;
> + return 1;
> +
> + ret_0:
> + __libc_errno = saved_errno;
> + return 0;
> +}
> --
> 2.18.1
>
On Fri, Nov 19, 2021 at 8:50 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote:
> >
> > >Why is the above declared as a special memory constraint? Also the
> > Change to define_memory_constraint since it's ok for
> > reload can make them match by converting the operand to the form
> > ‘(mem (reg X))’.where X is a base register (from the register class specified
> > by BASE_REG_CLASS
> >
> > >predicate comment is missing and the description should say something
> > >like:
> > >
> > >@internal TLS address that allows insn using non-integer registers
> > Changed.
> >
> > >I think it is better to avoid negative logic. So, something like
> > >
> > >Return true if the TLS address requires insn using integer registers.
> > >
> > >bool
> > >ix86_gpr_tls_address_pattern_p
> > >
> > >(and use not in the predicate)
> >
> > Changed.
> >
> > >> +{
> > >> + gcc_assert (MEM_P (mem));
> > >> +
> > >> + rtx addr = XEXP (mem, 0);
> > >> + subrtx_var_iterator::array_type array;
> > >> + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> > >> + {
> > >> + rtx op = *iter;
> > >> + if (GET_CODE (op) == UNSPEC)
> > >> + switch (XINT (op, 1))
> > >> + {
> > >> + case UNSPEC_GOTNTPOFF:
> > >> + return false;
> > >> + case UNSPEC_TPOFF:
> > >> + if (!TARGET_64BIT)
> > >> + return false;
> > >> + break;
> > >> + default:
> > >> + break;
> > >> + }
> > >> + /* Should iter.skip_subrtxes ();
> > >> + if there's no inner UNSPEC in addr???. */
> >
> > >You should figure the above before submitting the patch.
> > ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so
> > remove comments.
> >
> > >Can you please minimize the testcase?
> > Done;
> >
> > As change in assembler, refer to [1], this patch disallow mask/sse/mmx
> > mov in TLS code sequences which require integer MOV instructions.
> >
> > [1] https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d7e3e627027fcf37d63e284144fe27ff4eba36b5
> >
> > gcc/ChangeLog:
> >
> > PR target/103275
> > * config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p):
> > Declare.
> > * config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New
> > function.
> > * config/i386/i386.md (*movsi_internal): Don't allow
> > mask/sse/mmx move in TLS code sequences.
> > (*movdi_internal): Ditto.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/i386/pr103275.c: New test.
>
> OK, with a small comment adjustment below.
Ops, sorry, I was too fast. You can simplify the patch to change the
constraint from
*km to *kBk
Then no renumbering is needed.
Uros.
>
> Thanks,
> Uros.
>
> > ---
> > gcc/config/i386/constraints.md | 5 ++
> > gcc/config/i386/i386-protos.h | 1 +
> > gcc/config/i386/i386.c | 32 +++++++++
> > gcc/config/i386/i386.md | 18 ++---
> > gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++
> > 5 files changed, 130 insertions(+), 9 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c
> >
> > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> > index eaa582d2055..15c5950ee6f 100644
> > --- a/gcc/config/i386/constraints.md
> > +++ b/gcc/config/i386/constraints.md
> > @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc"
> > (and (match_operand 0 "memory_operand")
> > (match_test "constant_address_p (XEXP (op, 0))")))
> >
> > +(define_memory_constraint "Bk"
> > + "@internal TLS address that allows insn using non-integer registers."
> > + (and (match_operand 0 "memory_operand")
> > + (not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
> > +
> > (define_special_memory_constraint "Bn"
> > "@internal Memory operand without REX prefix."
> > (match_operand 0 "norex_memory_operand"))
> > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> > index 7782cf1163f..941e91636d8 100644
> > --- a/gcc/config/i386/i386-protos.h
> > +++ b/gcc/config/i386/i386-protos.h
> > @@ -240,6 +240,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
> > #endif
> >
> > extern rtx ix86_tls_module_base (void);
> > +extern bool ix86_gpr_tls_address_pattern_p (rtx);
> > extern bool ix86_tls_address_pattern_p (rtx);
> > extern rtx ix86_rewrite_tls_address (rtx);
> >
> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > index 42c47d2b12b..68079e4230e 100644
> > --- a/gcc/config/i386/i386.c
> > +++ b/gcc/config/i386/i386.c
> > @@ -11468,6 +11468,38 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
> > return dest;
> > }
> >
> > +/* Return true if the TLS address requires insn using integer registers.
> > + NB: it's different from ix86_tls_address_pattern_p since it also matchs
> > + gottpoff/gotntpoff.
>
> The above NB comment is not needed, the fact is obvious from the code.
>
> > + It's used to prevent KMOV/VMOV in TLS code sequences which require integer
> > + MOV instructions, refer to PR103275. */
> > +bool
> > +ix86_gpr_tls_address_pattern_p (rtx mem)
> > +{
> > + gcc_assert (MEM_P (mem));
> > +
> > + rtx addr = XEXP (mem, 0);
> > + subrtx_var_iterator::array_type array;
> > + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> > + {
> > + rtx op = *iter;
> > + if (GET_CODE (op) == UNSPEC)
> > + switch (XINT (op, 1))
> > + {
> > + case UNSPEC_GOTNTPOFF:
> > + return true;
> > + case UNSPEC_TPOFF:
> > + if (!TARGET_64BIT)
> > + return true;
> > + break;
> > + default:
> > + break;
> > + }
> > + }
> > +
> > + return false;
> > +}
> > +
> > /* Return true if OP refers to a TLS address. */
> > bool
> > ix86_tls_address_pattern_p (rtx op)
> > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> > index 97325e38676..82b85b26059 100644
> > --- a/gcc/config/i386/i386.md
> > +++ b/gcc/config/i386/i386.md
> > @@ -2085,9 +2085,9 @@ (define_split
> >
> > (define_insn "*movdi_internal"
> > [(set (match_operand:DI 0 "nonimmediate_operand"
> > - "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
> > + "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k,*k ,*r,*m,*k")
> > (match_operand:DI 1 "general_operand"
> > - "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
> > + "riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*k,*Bk,*k,*k,CBC"))]
> > "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> > && ix86_hardreg_mov_ok (operands[0], operands[1])"
> > {
> > @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal"
> > [(set (attr "isa")
> > (cond [(eq_attr "alternative" "0,1,17,18")
> > (const_string "nox64")
> > - (eq_attr "alternative" "2,3,4,5,10,11,23,25")
> > + (eq_attr "alternative" "2,3,4,5,10,11,23,26")
> > (const_string "x64")
> > (eq_attr "alternative" "19,20")
> > (const_string "x64_sse2")
> > @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal"
> > (const_string "ssemov")
> > (eq_attr "alternative" "21,22")
> > (const_string "ssecvt")
> > - (eq_attr "alternative" "23,24,25,26")
> > + (eq_attr "alternative" "23,24,25,26,27")
> > (const_string "mskmov")
> > - (eq_attr "alternative" "27")
> > + (eq_attr "alternative" "28")
> > (const_string "msklog")
> > (and (match_operand 0 "register_operand")
> > (match_operand 1 "pic_32bit_operand"))
> > @@ -2306,9 +2306,9 @@ (define_peephole2
> >
> > (define_insn "*movsi_internal"
> > [(set (match_operand:SI 0 "nonimmediate_operand"
> > - "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
> > + "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*k,*rm,*k")
> > (match_operand:SI 1 "general_operand"
> > - "g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
> > + "g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*k, *Bk,*k ,CBC"))]
> > "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> > && ix86_hardreg_mov_ok (operands[0], operands[1])"
> > {
> > @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal"
> > (const_string "sselog1")
> > (eq_attr "alternative" "9,10,11,12,13")
> > (const_string "ssemov")
> > - (eq_attr "alternative" "14,15,16")
> > + (eq_attr "alternative" "14,15,16,17")
> > (const_string "mskmov")
> > - (eq_attr "alternative" "17")
> > + (eq_attr "alternative" "18")
> > (const_string "msklog")
> > (and (match_operand 0 "register_operand")
> > (match_operand 1 "pic_32bit_operand"))
> > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c
> > new file mode 100644
> > index 00000000000..c93413f3cde
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c
> > @@ -0,0 +1,83 @@
> > +/* { dg-do compile { target ia32 } } */
> > +/* { dg-options "-O2 -march=tigerlake -fPIC" } */
> > +/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
> > +
> > +typedef unsigned short uint16_t;
> > +typedef int int32_t;
> > +typedef unsigned int uint32_t;
> > +typedef unsigned char uint8_t;
> > +
> > +typedef uint32_t in_addr_t;
> > +struct in_addr { in_addr_t s_addr; };
> > +
> > +extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
> > +extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
> > +
> > +extern unsigned long strtoul (const char*, char**, int);
> > +extern uint32_t __bswap_32 (in_addr_t);
> > +int
> > +inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
> > +{
> > + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
> > + in_addr_t val;
> > + char c;
> > + union iaddr
> > + {
> > + uint8_t bytes[4];
> > + uint32_t word;
> > + } res;
> > + uint8_t *pp = res.bytes;
> > + int digit;
> > +
> > + int saved_errno = __libc_errno;
> > + __libc_errno = 0;
> > + res.word = 0;
> > + c = *cp;
> > +
> > + for (;;)
> > + {
> > + if (c < '0' || c > '9')
> > + goto ret_0;
> > + {
> > + char *endp;
> > + unsigned long ul = strtoul (cp, &endp, 0);
> > + if (ul == 0x7fffffffL && __libc_errno == 34)
> > + goto ret_0;
> > + if (ul > 0xfffffffful)
> > + goto ret_0;
> > + val = ul;
> > + digit = cp != endp;
> > + cp = endp;
> > + }
> > + c = *cp;
> > + if (c == '.')
> > + {
> > + if (pp > res.bytes + 2 || val > 0xff)
> > + goto ret_0;
> > + *pp++ = val;
> > + c = *++cp;
> > + }
> > + else
> > + break;
> > + }
> > +
> > + if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
> > + goto ret_0;
> > +
> > + if (!digit)
> > + goto ret_0;
> > +
> > + if (val > max[pp - res.bytes])
> > + goto ret_0;
> > +
> > + if (addr != 0)
> > + addr->s_addr = res.word | __bswap_32 (val);
> > + *endp = cp;
> > +
> > + __libc_errno = saved_errno;
> > + return 1;
> > +
> > + ret_0:
> > + __libc_errno = saved_errno;
> > + return 0;
> > +}
> > --
> > 2.18.1
> >
On Fri, Nov 19, 2021 at 3:53 PM Uros Bizjak via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Fri, Nov 19, 2021 at 8:50 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Fri, Nov 19, 2021 at 2:14 AM liuhongt <hongtao.liu@intel.com> wrote:
> > >
> > > >Why is the above declared as a special memory constraint? Also the
> > > Change to define_memory_constraint since it's ok for
> > > reload can make them match by converting the operand to the form
> > > ‘(mem (reg X))’.where X is a base register (from the register class specified
> > > by BASE_REG_CLASS
> > >
> > > >predicate comment is missing and the description should say something
> > > >like:
> > > >
> > > >@internal TLS address that allows insn using non-integer registers
> > > Changed.
> > >
> > > >I think it is better to avoid negative logic. So, something like
> > > >
> > > >Return true if the TLS address requires insn using integer registers.
> > > >
> > > >bool
> > > >ix86_gpr_tls_address_pattern_p
> > > >
> > > >(and use not in the predicate)
> > >
> > > Changed.
> > >
> > > >> +{
> > > >> + gcc_assert (MEM_P (mem));
> > > >> +
> > > >> + rtx addr = XEXP (mem, 0);
> > > >> + subrtx_var_iterator::array_type array;
> > > >> + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> > > >> + {
> > > >> + rtx op = *iter;
> > > >> + if (GET_CODE (op) == UNSPEC)
> > > >> + switch (XINT (op, 1))
> > > >> + {
> > > >> + case UNSPEC_GOTNTPOFF:
> > > >> + return false;
> > > >> + case UNSPEC_TPOFF:
> > > >> + if (!TARGET_64BIT)
> > > >> + return false;
> > > >> + break;
> > > >> + default:
> > > >> + break;
> > > >> + }
> > > >> + /* Should iter.skip_subrtxes ();
> > > >> + if there's no inner UNSPEC in addr???. */
> > >
> > > >You should figure the above before submitting the patch.
> > > ix86_print_operand_address_as shows there could be inner UNSPEC in addr, so
> > > remove comments.
> > >
> > > >Can you please minimize the testcase?
> > > Done;
> > >
> > > As change in assembler, refer to [1], this patch disallow mask/sse/mmx
> > > mov in TLS code sequences which require integer MOV instructions.
> > >
> > > [1] https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d7e3e627027fcf37d63e284144fe27ff4eba36b5
> > >
> > > gcc/ChangeLog:
> > >
> > > PR target/103275
> > > * config/i386/i386-protos.h (ix86_gpr_tls_address_pattern_p):
> > > Declare.
> > > * config/i386/i386.c (ix86_gpr_tls_address_pattern_p): New
> > > function.
> > > * config/i386/i386.md (*movsi_internal): Don't allow
> > > mask/sse/mmx move in TLS code sequences.
> > > (*movdi_internal): Ditto.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * gcc.target/i386/pr103275.c: New test.
> >
> > OK, with a small comment adjustment below.
>
> Ops, sorry, I was too fast. You can simplify the patch to change the
> constraint from
>
> *km to *kBk
>
> Then no renumbering is needed.
Yes, changed, thanks for the review.
this is the final patch i'm checking in.
>
> Uros.
>
> >
> > Thanks,
> > Uros.
> >
> > > ---
> > > gcc/config/i386/constraints.md | 5 ++
> > > gcc/config/i386/i386-protos.h | 1 +
> > > gcc/config/i386/i386.c | 32 +++++++++
> > > gcc/config/i386/i386.md | 18 ++---
> > > gcc/testsuite/gcc.target/i386/pr103275.c | 83 ++++++++++++++++++++++++
> > > 5 files changed, 130 insertions(+), 9 deletions(-)
> > > create mode 100644 gcc/testsuite/gcc.target/i386/pr103275.c
> > >
> > > diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> > > index eaa582d2055..15c5950ee6f 100644
> > > --- a/gcc/config/i386/constraints.md
> > > +++ b/gcc/config/i386/constraints.md
> > > @@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc"
> > > (and (match_operand 0 "memory_operand")
> > > (match_test "constant_address_p (XEXP (op, 0))")))
> > >
> > > +(define_memory_constraint "Bk"
> > > + "@internal TLS address that allows insn using non-integer registers."
> > > + (and (match_operand 0 "memory_operand")
> > > + (not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
> > > +
> > > (define_special_memory_constraint "Bn"
> > > "@internal Memory operand without REX prefix."
> > > (match_operand 0 "norex_memory_operand"))
> > > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> > > index 7782cf1163f..941e91636d8 100644
> > > --- a/gcc/config/i386/i386-protos.h
> > > +++ b/gcc/config/i386/i386-protos.h
> > > @@ -240,6 +240,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
> > > #endif
> > >
> > > extern rtx ix86_tls_module_base (void);
> > > +extern bool ix86_gpr_tls_address_pattern_p (rtx);
> > > extern bool ix86_tls_address_pattern_p (rtx);
> > > extern rtx ix86_rewrite_tls_address (rtx);
> > >
> > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > index 42c47d2b12b..68079e4230e 100644
> > > --- a/gcc/config/i386/i386.c
> > > +++ b/gcc/config/i386/i386.c
> > > @@ -11468,6 +11468,38 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
> > > return dest;
> > > }
> > >
> > > +/* Return true if the TLS address requires insn using integer registers.
> > > + NB: it's different from ix86_tls_address_pattern_p since it also matchs
> > > + gottpoff/gotntpoff.
> >
> > The above NB comment is not needed, the fact is obvious from the code.
> >
> > > + It's used to prevent KMOV/VMOV in TLS code sequences which require integer
> > > + MOV instructions, refer to PR103275. */
> > > +bool
> > > +ix86_gpr_tls_address_pattern_p (rtx mem)
> > > +{
> > > + gcc_assert (MEM_P (mem));
> > > +
> > > + rtx addr = XEXP (mem, 0);
> > > + subrtx_var_iterator::array_type array;
> > > + FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
> > > + {
> > > + rtx op = *iter;
> > > + if (GET_CODE (op) == UNSPEC)
> > > + switch (XINT (op, 1))
> > > + {
> > > + case UNSPEC_GOTNTPOFF:
> > > + return true;
> > > + case UNSPEC_TPOFF:
> > > + if (!TARGET_64BIT)
> > > + return true;
> > > + break;
> > > + default:
> > > + break;
> > > + }
> > > + }
> > > +
> > > + return false;
> > > +}
> > > +
> > > /* Return true if OP refers to a TLS address. */
> > > bool
> > > ix86_tls_address_pattern_p (rtx op)
> > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> > > index 97325e38676..82b85b26059 100644
> > > --- a/gcc/config/i386/i386.md
> > > +++ b/gcc/config/i386/i386.md
> > > @@ -2085,9 +2085,9 @@ (define_split
> > >
> > > (define_insn "*movdi_internal"
> > > [(set (match_operand:DI 0 "nonimmediate_operand"
> > > - "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
> > > + "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k,*k ,*r,*m,*k")
> > > (match_operand:DI 1 "general_operand"
> > > - "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
> > > + "riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*k,*Bk,*k,*k,CBC"))]
> > > "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> > > && ix86_hardreg_mov_ok (operands[0], operands[1])"
> > > {
> > > @@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal"
> > > [(set (attr "isa")
> > > (cond [(eq_attr "alternative" "0,1,17,18")
> > > (const_string "nox64")
> > > - (eq_attr "alternative" "2,3,4,5,10,11,23,25")
> > > + (eq_attr "alternative" "2,3,4,5,10,11,23,26")
> > > (const_string "x64")
> > > (eq_attr "alternative" "19,20")
> > > (const_string "x64_sse2")
> > > @@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal"
> > > (const_string "ssemov")
> > > (eq_attr "alternative" "21,22")
> > > (const_string "ssecvt")
> > > - (eq_attr "alternative" "23,24,25,26")
> > > + (eq_attr "alternative" "23,24,25,26,27")
> > > (const_string "mskmov")
> > > - (eq_attr "alternative" "27")
> > > + (eq_attr "alternative" "28")
> > > (const_string "msklog")
> > > (and (match_operand 0 "register_operand")
> > > (match_operand 1 "pic_32bit_operand"))
> > > @@ -2306,9 +2306,9 @@ (define_peephole2
> > >
> > > (define_insn "*movsi_internal"
> > > [(set (match_operand:SI 0 "nonimmediate_operand"
> > > - "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
> > > + "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*k,*rm,*k")
> > > (match_operand:SI 1 "general_operand"
> > > - "g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
> > > + "g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*k, *Bk,*k ,CBC"))]
> > > "!(MEM_P (operands[0]) && MEM_P (operands[1]))
> > > && ix86_hardreg_mov_ok (operands[0], operands[1])"
> > > {
> > > @@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal"
> > > (const_string "sselog1")
> > > (eq_attr "alternative" "9,10,11,12,13")
> > > (const_string "ssemov")
> > > - (eq_attr "alternative" "14,15,16")
> > > + (eq_attr "alternative" "14,15,16,17")
> > > (const_string "mskmov")
> > > - (eq_attr "alternative" "17")
> > > + (eq_attr "alternative" "18")
> > > (const_string "msklog")
> > > (and (match_operand 0 "register_operand")
> > > (match_operand 1 "pic_32bit_operand"))
> > > diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c
> > > new file mode 100644
> > > index 00000000000..c93413f3cde
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/i386/pr103275.c
> > > @@ -0,0 +1,83 @@
> > > +/* { dg-do compile { target ia32 } } */
> > > +/* { dg-options "-O2 -march=tigerlake -fPIC" } */
> > > +/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
> > > +
> > > +typedef unsigned short uint16_t;
> > > +typedef int int32_t;
> > > +typedef unsigned int uint32_t;
> > > +typedef unsigned char uint8_t;
> > > +
> > > +typedef uint32_t in_addr_t;
> > > +struct in_addr { in_addr_t s_addr; };
> > > +
> > > +extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
> > > +extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
> > > +
> > > +extern unsigned long strtoul (const char*, char**, int);
> > > +extern uint32_t __bswap_32 (in_addr_t);
> > > +int
> > > +inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
> > > +{
> > > + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
> > > + in_addr_t val;
> > > + char c;
> > > + union iaddr
> > > + {
> > > + uint8_t bytes[4];
> > > + uint32_t word;
> > > + } res;
> > > + uint8_t *pp = res.bytes;
> > > + int digit;
> > > +
> > > + int saved_errno = __libc_errno;
> > > + __libc_errno = 0;
> > > + res.word = 0;
> > > + c = *cp;
> > > +
> > > + for (;;)
> > > + {
> > > + if (c < '0' || c > '9')
> > > + goto ret_0;
> > > + {
> > > + char *endp;
> > > + unsigned long ul = strtoul (cp, &endp, 0);
> > > + if (ul == 0x7fffffffL && __libc_errno == 34)
> > > + goto ret_0;
> > > + if (ul > 0xfffffffful)
> > > + goto ret_0;
> > > + val = ul;
> > > + digit = cp != endp;
> > > + cp = endp;
> > > + }
> > > + c = *cp;
> > > + if (c == '.')
> > > + {
> > > + if (pp > res.bytes + 2 || val > 0xff)
> > > + goto ret_0;
> > > + *pp++ = val;
> > > + c = *++cp;
> > > + }
> > > + else
> > > + break;
> > > + }
> > > +
> > > + if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
> > > + goto ret_0;
> > > +
> > > + if (!digit)
> > > + goto ret_0;
> > > +
> > > + if (val > max[pp - res.bytes])
> > > + goto ret_0;
> > > +
> > > + if (addr != 0)
> > > + addr->s_addr = res.word | __bswap_32 (val);
> > > + *endp = cp;
> > > +
> > > + __libc_errno = saved_errno;
> > > + return 1;
> > > +
> > > + ret_0:
> > > + __libc_errno = saved_errno;
> > > + return 0;
> > > +}
> > > --
> > > 2.18.1
> > >
@@ -185,6 +185,11 @@ (define_special_memory_constraint "Bc"
(and (match_operand 0 "memory_operand")
(match_test "constant_address_p (XEXP (op, 0))")))
+(define_memory_constraint "Bk"
+ "@internal TLS address that allows insn using non-integer registers."
+ (and (match_operand 0 "memory_operand")
+ (not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
+
(define_special_memory_constraint "Bn"
"@internal Memory operand without REX prefix."
(match_operand 0 "norex_memory_operand"))
@@ -240,6 +240,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
#endif
extern rtx ix86_tls_module_base (void);
+extern bool ix86_gpr_tls_address_pattern_p (rtx);
extern bool ix86_tls_address_pattern_p (rtx);
extern rtx ix86_rewrite_tls_address (rtx);
@@ -11468,6 +11468,38 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
return dest;
}
+/* Return true if the TLS address requires insn using integer registers.
+ NB: it's different from ix86_tls_address_pattern_p since it also matchs
+ gottpoff/gotntpoff.
+ It's used to prevent KMOV/VMOV in TLS code sequences which require integer
+ MOV instructions, refer to PR103275. */
+bool
+ix86_gpr_tls_address_pattern_p (rtx mem)
+{
+ gcc_assert (MEM_P (mem));
+
+ rtx addr = XEXP (mem, 0);
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
+ {
+ rtx op = *iter;
+ if (GET_CODE (op) == UNSPEC)
+ switch (XINT (op, 1))
+ {
+ case UNSPEC_GOTNTPOFF:
+ return true;
+ case UNSPEC_TPOFF:
+ if (!TARGET_64BIT)
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
/* Return true if OP refers to a TLS address. */
bool
ix86_tls_address_pattern_p (rtx op)
@@ -2085,9 +2085,9 @@ (define_split
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
+ "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k,*k ,*r,*m,*k")
(match_operand:DI 1 "general_operand"
- "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
+ "riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*k,*Bk,*k,*k,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{
@@ -2149,7 +2149,7 @@ (define_insn "*movdi_internal"
[(set (attr "isa")
(cond [(eq_attr "alternative" "0,1,17,18")
(const_string "nox64")
- (eq_attr "alternative" "2,3,4,5,10,11,23,25")
+ (eq_attr "alternative" "2,3,4,5,10,11,23,26")
(const_string "x64")
(eq_attr "alternative" "19,20")
(const_string "x64_sse2")
@@ -2170,9 +2170,9 @@ (define_insn "*movdi_internal"
(const_string "ssemov")
(eq_attr "alternative" "21,22")
(const_string "ssecvt")
- (eq_attr "alternative" "23,24,25,26")
+ (eq_attr "alternative" "23,24,25,26,27")
(const_string "mskmov")
- (eq_attr "alternative" "27")
+ (eq_attr "alternative" "28")
(const_string "msklog")
(and (match_operand 0 "register_operand")
(match_operand 1 "pic_32bit_operand"))
@@ -2306,9 +2306,9 @@ (define_peephole2
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
+ "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*k,*rm,*k")
(match_operand:SI 1 "general_operand"
- "g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
+ "g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*k, *Bk,*k ,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{
@@ -2373,9 +2373,9 @@ (define_insn "*movsi_internal"
(const_string "sselog1")
(eq_attr "alternative" "9,10,11,12,13")
(const_string "ssemov")
- (eq_attr "alternative" "14,15,16")
+ (eq_attr "alternative" "14,15,16,17")
(const_string "mskmov")
- (eq_attr "alternative" "17")
+ (eq_attr "alternative" "18")
(const_string "msklog")
(and (match_operand 0 "register_operand")
(match_operand 1 "pic_32bit_operand"))
new file mode 100644
@@ -0,0 +1,83 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -march=tigerlake -fPIC" } */
+/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
+
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+
+typedef uint32_t in_addr_t;
+struct in_addr { in_addr_t s_addr; };
+
+extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
+extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
+
+extern unsigned long strtoul (const char*, char**, int);
+extern uint32_t __bswap_32 (in_addr_t);
+int
+inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
+{
+ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
+ in_addr_t val;
+ char c;
+ union iaddr
+ {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+ uint8_t *pp = res.bytes;
+ int digit;
+
+ int saved_errno = __libc_errno;
+ __libc_errno = 0;
+ res.word = 0;
+ c = *cp;
+
+ for (;;)
+ {
+ if (c < '0' || c > '9')
+ goto ret_0;
+ {
+ char *endp;
+ unsigned long ul = strtoul (cp, &endp, 0);
+ if (ul == 0x7fffffffL && __libc_errno == 34)
+ goto ret_0;
+ if (ul > 0xfffffffful)
+ goto ret_0;
+ val = ul;
+ digit = cp != endp;
+ cp = endp;
+ }
+ c = *cp;
+ if (c == '.')
+ {
+ if (pp > res.bytes + 2 || val > 0xff)
+ goto ret_0;
+ *pp++ = val;
+ c = *++cp;
+ }
+ else
+ break;
+ }
+
+ if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
+ goto ret_0;
+
+ if (!digit)
+ goto ret_0;
+
+ if (val > max[pp - res.bytes])
+ goto ret_0;
+
+ if (addr != 0)
+ addr->s_addr = res.word | __bswap_32 (val);
+ *endp = cp;
+
+ __libc_errno = saved_errno;
+ return 1;
+
+ ret_0:
+ __libc_errno = saved_errno;
+ return 0;
+}