https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128437

--- Comment #13 from Uroš Bizjak <ubizjak at gmail dot com> ---
The ICE is caused by dead code elimination in sched2, not by the front end.

At expand, the 64-bit local-dynamic base is a const call to __tls_get_addr
whose result is used by an insn that references current@dtpoff. In the testcase
the load of "current" feeds only a compare whose flags are immediately
overwritten. Both insns are dead, and the fast DCE run from sched2 deletes
them:

  DCE: Deleting insn 103 (cmp)
  DCE: Deleting insn 102 (load of current@dtpoff)

The call itself survives with REG_UNUSED on %rax. In deletable_insn_p, calls
are only deletable if (!df_in_progress), because deleting a call can delete
basic blocks while df is still running. df_in_progress is true here (checked in
gdb), so the dead call is kept.  No DCE pass runs after sched2.

The surviving call is output through the *tls_local_dynamic_base_64_<mode>
pattern, which prints '%&'.  print_operand implements '%&' via
get_some_local_dynamic_name, which scans the insn stream for a SYMBOL_REF with
TLS_MODEL_LOCAL_DYNAMIC. The only such reference was in the deleted load, so no
symbol is found and final ICEs with "'%&' used without any local dynamic TLS
references".

The 32-bit sequences are non-call insns and are removed by the same DCE
together with their users, so only the 64-bit call form is affected.

PR110606 on powerpc64le looks like the same mechanism (dead tls_dtprel insns
deleted in sched2, __tls_get_addr call left behind).

Reply via email to