On Tue, Aug 26, 2025 at 10:24 PM Hongtao Liu <crazy...@gmail.com> wrote: > > On Wed, Aug 27, 2025 at 6:32 AM H.J. Lu <hjl.to...@gmail.com> wrote: > > > > Source operands of 2 *tls_dynamic_gnu2_call_64_di patterns in > > > > (insn 10 9 11 3 (set (reg:DI 100) > > (unspec:DI [ > > (symbol_ref:DI ("caml_state") [flags 0x10] <var_decl > > 0x7fe10e1d9e40 caml_state>) > > ] UNSPEC_TLSDESC)) "x.c":7:16 1674 {*tls_dynamic_gnu2_lea_64_di} > > (nil)) > > (insn 11 10 12 3 (parallel [ > > (set (reg:DI 99) > > (unspec:DI [ > > (symbol_ref:DI ("caml_state") [flags 0x10] > > <var_decl 0x7fe10e1d9e40 caml_state>) > > (reg:DI 100) > > (reg/f:DI 7 sp) > > ] UNSPEC_TLSDESC)) > > (clobber (reg:CC 17 flags)) > > ]) "x.c":7:16 1676 {*tls_dynamic_gnu2_call_64_di} > > (expr_list:REG_DEAD (reg:DI 100) > > (expr_list:REG_UNUSED (reg:CC 17 flags) > > (nil)))) > > > > and > > > > (insn 19 17 20 4 (set (reg:DI 104) > > (unspec:DI [ > > (symbol_ref:DI ("caml_state") [flags 0x10] <var_decl > > 0x7fe10e1d9e40 caml_state>) > > ] UNSPEC_TLSDESC)) "x.c":6:10 discrim 1 1674 > > {*tls_dynamic_gnu2_lea_64_di} > > (nil)) > > (insn 20 19 21 4 (parallel [ > > (set (reg:DI 103) > > (unspec:DI [ > > (symbol_ref:DI ("caml_state") [flags 0x10] > > <var_decl 0x7fe10e1d9e40 caml_state>) > > (reg:DI 104) > > (reg/f:DI 7 sp) > > ] UNSPEC_TLSDESC)) > > (clobber (reg:CC 17 flags)) > > ]) "x.c":6:10 discrim 1 1676 {*tls_dynamic_gnu2_call_64_di} > > (expr_list:REG_DEAD (reg:DI 104) > > (expr_list:REG_UNUSED (reg:CC 17 flags) > > (nil)))) > > > > are the same even though rtx_equal_p returns false since (reg:DI 100) > > and (reg:DI 104) are set from the same symbol. Add x86_cse_rtx_equal_p > > to compare source operands of *tls_dynamic_gnu2_call_64_di patterns and > > return true if only source operands differ and they are set from the > > same symbol. > > > > gcc/ > > > > * config/i386/i386-features.cc > > (pass_x86_cse::x86_cse_rtx_equal_p): New. > > (pass_x86_cse::tls_set_insn_from_symbol): Likewise. > > (pass_x86_cse::candidate_gnu2_tls_p): Call > > tls_set_insn_from_symbol. > > (pass_x86_cse::x86_cse): Call x86_cse_rtx_equal_p, instead of > > rtx_equal_p, to compare 2 values. > > > > gcc/testsuite/ > > > > * gcc.target/i386/pr121668-1b.c: New test. > > > > Signed-off-by: H.J. Lu <hjl.to...@gmail.com> > > --- > > gcc/config/i386/i386-features.cc | 116 +++++++++++++++----- > > gcc/testsuite/gcc.target/i386/pr121668-1b.c | 6 + > > 2 files changed, 95 insertions(+), 27 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/i386/pr121668-1b.c > > > > diff --git a/gcc/config/i386/i386-features.cc > > b/gcc/config/i386/i386-features.cc > > index 93e20947edf..ce77e91c120 100644 > > --- a/gcc/config/i386/i386-features.cc > > +++ b/gcc/config/i386/i386-features.cc > > @@ -4168,8 +4168,95 @@ private: > > bool candidate_gnu_tls_p (rtx_insn *, attr_tls64); > > bool candidate_gnu2_tls_p (rtx, attr_tls64); > > bool candidate_vector_p (rtx); > > + bool x86_cse_rtx_equal_p (const_rtx, const_rtx); > > + rtx_insn *tls_set_insn_from_symbol (const_rtx, rtx *); > > }; // class pass_x86_cse > > > > +/* Return true if X and Y are equal. */ > > + > > +bool > > +pass_x86_cse::x86_cse_rtx_equal_p (const_rtx x, const_rtx y) > > +{ > > + if (kind == X86_CSE_TLSDESC > > + && GET_CODE (x) == UNSPEC > > + && XINT (x, 1) == UNSPEC_TLSDESC > > + && SYMBOL_REF_P (XVECEXP (x, 0, 0))) > > + { > > + /* Compare > > + > > + (unspec:DI [ > > + (symbol_ref:DI ("caml_state") [flags 0x10] <var_decl > > 0x7fffe99d9e40 caml_state>) > > + (reg:DI 100) > > + (reg/f:DI 7 sp) > > + ] UNSPEC_TLSDESC) > > + > > + against > > + > > + (unspec:DI [ > > + (symbol_ref:DI ("caml_state") [flags 0x10] <var_decl > > 0x7fffe99d9e40 caml_state>) > > + (reg:DI 104) > > + (reg/f:DI 7 sp) > > + ] UNSPEC_TLSDESC) > > + > > + If (reg:DI 100) and (reg:DI 104) are defined from the same source, > > + they are equal. */ > > + > > + if (GET_CODE (y) != UNSPEC > > + || XINT (y, 1) != UNSPEC_TLSDESC > > + || !SYMBOL_REF_P (XVECEXP (y, 0, 0)) > > + || !rtx_equal_p (XVECEXP (x, 0, 0), XVECEXP (y, 0, 0))) > > + return false; > > + > > + x = XVECEXP (x, 0, 1); > > + y = XVECEXP (y, 0, 1); > > + if (rtx_equal_p (x, y)) > > + return true; > > + > > + rtx tls_symbol = nullptr; > > + return (tls_set_insn_from_symbol (x, &tls_symbol) > > + && tls_symbol > > + && tls_set_insn_from_symbol (y, &tls_symbol)); > > + } > > + > > + return rtx_equal_p (x, y); > > +} > > + > > +/* Return the instruction which sets REG from one symbol and store the > > + symbol in *TLS_SYMBOL_P if *TLS_SYMBOL_P is nullptr. */ > > + > > +rtx_insn * > > +pass_x86_cse::tls_set_insn_from_symbol (const_rtx reg, rtx *tls_symol_p) > > +{ > > + rtx_insn *set_insn = nullptr; > > + rtx tls_symbol = *tls_symol_p; > > + for (df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg)); > > + ref; > > + ref = DF_REF_NEXT_REG (ref)) > > + { > > + if (DF_REF_IS_ARTIFICIAL (ref)) > > + return nullptr; > > + > > + set_insn = DF_REF_INSN (ref); > > + if (get_attr_tls64 (set_insn) != TLS64_LEA) > > + return nullptr; > > + > > + rtx tls_set = PATTERN (set_insn); > > + rtx tls_src = XVECEXP (SET_SRC (tls_set), 0, 0); > > + if (tls_symbol == nullptr) > > + { > > + if (!SYMBOL_REF_P (tls_src)) > > + return nullptr; > > + > > + tls_symbol = tls_src; > > + *tls_symol_p = tls_src; > > + } > > + else if (!rtx_equal_p (tls_symbol, tls_src)) > > + return nullptr; > > + } > > + > > + return set_insn; > > +} > > + > > /* Return true and output def_insn, val, mode, scalar_mode and kind if > > INSN is UNSPEC_TLS_GD or UNSPEC_TLS_LD_BASE. */ > > > > @@ -4283,32 +4370,7 @@ pass_x86_cse::candidate_gnu2_tls_p (rtx set, > > attr_tls64 tls64) > > > > */ > > > > - df_ref ref; > > - rtx_insn *set_insn = nullptr; > > - for (ref = DF_REG_DEF_CHAIN (REGNO (src)); > > - ref; > > - ref = DF_REF_NEXT_REG (ref)) > > - { > > - if (DF_REF_IS_ARTIFICIAL (ref)) > > - break; > > - > > - set_insn = DF_REF_INSN (ref); > > - tls64 = get_attr_tls64 (set_insn); > > - if (tls64 != TLS64_LEA) > > - { > > - set_insn = nullptr; > > - break; > > - } > > - > > - rtx tls_set = PATTERN (set_insn); > > - rtx tls_src = XVECEXP (SET_SRC (tls_set), 0, 0); > > - if (!rtx_equal_p (tls_symbol, tls_src)) > > - { > > - set_insn = nullptr; > > - break; > > - } > > - } > > - > > + rtx_insn *set_insn = tls_set_insn_from_symbol (src, &tls_symbol); > > if (!set_insn) > > return false; > > > > @@ -4436,7 +4498,7 @@ pass_x86_cse::x86_cse (void) > > /* Non all 0s/1s vector load must be in the same > > basic block if it is in a recursive call. */ > > || !recursive_call_p) > > - && rtx_equal_p (load->val, val)) > > + && x86_cse_rtx_equal_p (load->val, val)) > Can we just record val as tls_symbol in candidate_gnu2_tls_p, and > adjust code in ix86_place_single_tls_call?
I added tlsdesc_val and record val as tls_symbol in the v2 patch. > > { > > /* Record instruction. */ > > bitmap_set_bit (load->insns, INSN_UID (insn)); > > diff --git a/gcc/testsuite/gcc.target/i386/pr121668-1b.c > > b/gcc/testsuite/gcc.target/i386/pr121668-1b.c > > new file mode 100644 > > index 00000000000..54a277506f8 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr121668-1b.c > > @@ -0,0 +1,6 @@ > > +/* { dg-do compile { target *-*-linux* } } */ > > +/* { dg-options "-Og -g -fpic -fplt -mtls-dialect=gnu2" } */ > > + > > +#include "pr121668-1a.c" > > + > > +/* { dg-final { scan-assembler-times "call\[ > > \t\]\\*caml_state@TLSCALL\\(%(?:r|e)ax\\)" 1 { target { ! ia32 } } } } */ > > -- > > 2.51.0 > > > > > -- > BR, > Hongtao -- H.J.