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