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).
