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 <[email protected]>
---
 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))
              {
                /* 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

Reply via email to