On 7/15/2026 12:18 PM, Matt Turner wrote:
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.
rth doesn't do much with GCC these days (he's over in QEMU land), so I went ahead with the review and pushed this as everything seemed sensible.

Thanks again!

jeff

Reply via email to