[gcc r17-2497] [PATCH] alpha: do not gate cannot_copy_insn_p on reload_completed

Jeff Law via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:7b18a7c536e62dffdbdbeb5f7457ff22f1cc44dc

commit r17-2497-g7b18a7c536e62dffdbdbeb5f7457ff22f1cc44dc
Author: Matt Turner <[email protected]>
Date:   Fri Jul 17 07:26:12 2026 -0600

    [PATCH] alpha: do not gate cannot_copy_insn_p on reload_completed
    
    alpha_legitimize_address emits movdi_er_tlsgd and movdi_er_tlsldm together
    with their paired call_value_osf_tlsgd/tlsldm at expand time, and both halves
    already carry the sequence number that ties the pair together.  Those patterns
    are marked with the cannot_copy attribute, but alpha_cannot_copy_insn_p
    returned false whenever !reload_completed, so the hook had no effect on any
    pass running before register allocation.
    
    Unrolling a loop whose body contains such a pair therefore copies the sequence
    number along with it.  With
    
      extern __thread int tv;
      extern int cond (int);
      int f (int n)
      {
        int s = 0;
        for (int i = 0; i < n; i++)
          if (cond (i))
            s += tv;
        return s;
      }
    
    compiled with -O2 -funroll-loops -fno-move-loop-invariants -fPIC
    -ftls-model=global-dynamic, the unroller produces seven copies of !tlsgd!1 and
    the assembler rejects the result:
    
      Error: duplicate !tlsgd!1
      Error: too many lituse insns for !lituse_tlsgd!1
    
    Drop the reload_completed test.  The gpdisp pairs are only created after
    reload, so this does not change their handling; it only lets the hook protect
    the TLS pairs that already exist before register allocation.  This is
    independent of the register allocator: the failure reproduces identically with
    both reload and LRA.
    
    gcc/
            * config/alpha/alpha.cc (alpha_cannot_copy_insn_p): Do not return
            false before reload_completed.  Update comment.
    
    gcc/testsuite/
            * gcc.target/alpha/tlsgd-dup-1.c: New test.

Diff:
---
 gcc/config/alpha/alpha.cc                    | 17 +++++++++++++----
 gcc/testsuite/gcc.target/alpha/tlsgd-dup-1.c | 22 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
index 9b8433c5bb04..90e4c21dd11b 100644
--- a/gcc/config/alpha/alpha.cc
+++ b/gcc/config/alpha/alpha.cc
@@ -1242,8 +1242,8 @@ split_small_symbolic_operand (rtx x)
 }
 
 /* Indicate that INSN cannot be duplicated.  This is true for any insn
-   that we've marked with gpdisp relocs, since those have to stay in
-   1-1 correspondence with one another.
+   that we've marked with a relocation sequence number, since those have
+   to stay in 1-1 correspondence with one another.
 
    Technically we could copy them if we could set up a mapping from one
    sequence number to another, across the set of insns to be duplicated.
@@ -1253,12 +1253,21 @@ split_small_symbolic_operand (rtx x)
    Also cannot allow jsr insns to be duplicated.  If they throw exceptions,
    then they'll be in a different block from their ldgp.  Which could lead
    the bb reorder code to think that it would be ok to copy just the block
-   containing the call and branch to the block containing the ldgp.  */
+   containing the call and branch to the block containing the ldgp.
+
+   Note this must not be gated on reload_completed.  While the gpdisp pairs
+   are only created after reload, alpha_legitimize_address emits
+   movdi_er_tlsgd and movdi_er_tlsldm together with their paired
+   call_value_osf_tlsgd/tlsldm at expand time, and those already carry the
+   sequence number that ties each pair together.  Returning false before
+   reload lets the pre-RA duplicators reach them: unrolling a loop whose
+   body holds such a pair copies the sequence number along with it, and the
+   assembler then rejects the result with "duplicate !tlsgd!N".  */
 
 static bool
 alpha_cannot_copy_insn_p (rtx_insn *insn)
 {
-  if (!reload_completed || !TARGET_EXPLICIT_RELOCS)
+  if (!TARGET_EXPLICIT_RELOCS)
     return false;
   if (recog_memoized (insn) >= 0)
     return get_attr_cannot_copy (insn);
diff --git a/gcc/testsuite/gcc.target/alpha/tlsgd-dup-1.c b/gcc/testsuite/gcc.target/alpha/tlsgd-dup-1.c
new file mode 100644
index 000000000000..33ffc4d5deaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/alpha/tlsgd-dup-1.c
@@ -0,0 +1,22 @@
+/* Verify that a TLS sequence insn and its paired call are not duplicated by
+   the pre-RA passes.  Each movdi_er_tlsgd carries a sequence number that must
+   stay in 1-1 correspondence with the !lituse_tlsgd of its call; duplicating
+   the loop body used to copy both halves and make the assembler reject the
+   result with "duplicate !tlsgd!1".  */
+/* { dg-do assemble } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -funroll-loops -fno-move-loop-invariants -fPIC -ftls-model=global-dynamic" } */
+
+extern __thread int tv;
+extern int cond (int);
+
+int
+f (int n)
+{
+  int s = 0;
+  for (int i = 0; i < n; i++)
+    if (cond (i))
+      s += tv;
+  return s;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.