The code sample is here https://github.com/user1095108/cr. gcc crashes only if the optimization level is higher than 2. g++ -I.. -Ofast -no-pie -std=c++20 loop.cpp -o l clang compiles everything without issue. ./lduring RTL pass: sched2 In file included from /usr/include/c++/11.2.0/functional:59, from /usr/include/c++/11.2.0/pstl/glue_algorithm_defs.h:13, from /usr/include/c++/11.2.0/algorithm:74, from loop.hpp:5, from loop.cpp:3: /usr/include/c++/11.2.0/bits/std_function.h: In static member function 'static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes&& ...) [with _Res = void; _Functor = main()::<lambda()>; _ArgTypes = {}]': /usr/include/c++/11.2.0/bits/std_function.h:293:7: internal compiler error: in move_insn, at haifa-sched.c:5471 293 | } | ^ 0xe4c988 internal_error(char const*, ...) ???:0 0xe42d02 fancy_abort(char const*, int, char const*) ???:0 0x13ee792 schedule_block(basic_block_def**, void*) ???:0 0x13da4f2 schedule_insns() ???:0 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://bugs.archlinux.org/> for instructions.
Confirmed, working on that.
Reduced test-case: $ cat ice.ii namespace std { class tuple; template <typename> auto declval() -> decltype(0); template <typename> using remove_reference_t = int; } // namespace std extern "C" void abort(); namespace std { template <int, typename _Tp> using tuple_element_t = _Tp; template <typename _Fn> void __invoke_impl(_Fn __f) { __f(); } template <typename, typename _Callable> void __invoke_r(_Callable __fn) { __invoke_impl(__fn); } template <typename> class function; template <typename _Functor> struct _Base_manager { static _Functor *_M_get_pointer(int) { return 0; } }; template <typename, typename> class _Function_handler; template <typename _Res, typename _Functor, typename... _ArgTypes> struct _Function_handler<_Res(_ArgTypes...), _Functor> { using _Base = _Base_manager<_Functor>; static _Res _M_invoke(const int &__functor) { auto __trans_tmp_1 = _Base::_M_get_pointer(__functor); __invoke_r<_Res>(*__trans_tmp_1); return _Res(); } }; template <typename _Res, typename... _ArgTypes> struct function<_Res(_ArgTypes...)> { template <typename _Functor> using _Handler = _Function_handler<_Res(), _Functor>; function() {} template <typename _Functor> function(_Functor) { using _My_handler = _Handler<_Functor>; _M_invoker = _My_handler::_M_invoke; } using _Invoker_type = _Res (*)(const int &); _Invoker_type _M_invoker; }; } // namespace std bool savestate_r; int savestate_ssb; template <typename T> struct list { using value_type = T; struct node { value_type v_; } * last_; void emplace_back(auto... a) { last_ = new node(a...); } }; namespace cr { namespace detail { template <long I> using at_t = std::tuple_element_t<I, std::tuple>; } struct task { std::function<void()> f_; void *r_; task(auto f) { f_ = f; } template <typename> auto return_ref() { return *static_cast<std::remove_reference_t<int> *>(r_); } }; struct { task *pt_; list<task> l_; auto previous_task() { return pt_; } auto run(auto... f) -> decltype(std::declval<detail::at_t<sizeof...(f)>>()) { (l_.emplace_back(f), ...); return 0; } } thread_local loop; auto await(auto f) { using R = decltype(f); asm("" : "=m"(savestate_ssb), "=r"(savestate_r)); if (savestate_r) { auto pt(loop.previous_task()); return pt->return_ref<R>(); } asm("" : : ""(loop)); abort(); } } // namespace cr int main() { cr::loop.run([] { cr::await([] {}) << cr::await([] {}); }); return 0; } Started with -O2 -std=c++2a since r10-5137-g43aae289866f5ea5.
Weird. Mine then.
Does not crash for aarch64-linux-gnu. Maybe some latent bug the change introduced.
Here is a C testcase which shows this is a latent bug (derived from the gimple of the reduced testcase in comment #2): _Bool savestate_r; int savestate_ssb; extern void abort(); __thread struct { int t; int tt[1]; } loop; void f (const int * __functor) { _Bool savestate_r0_5; _Bool savestate_r1_6; __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r)); savestate_r0_5 = savestate_r; if (savestate_r0_5 != 0) goto bb3; else goto bb4; bb3: __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r)); savestate_r1_6 = savestate_r; if (savestate_r1_6 != 0) goto bb6; else goto bb5; bb4: __asm__ __volatile__("" : : "m" (loop)); abort (); bb5: __asm__ __volatile__("" : : "m" (loop)); abort (); bb6: return; }
Note loop being a thread_local (__thread) is important here to get the crash. Further reduced testcase: int savestate_r; int savestate_ssb; extern void abort(); __thread int loop; void f (void) { int savestate_r0_5; int savestate_r1_6; __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r)); savestate_r0_5 = savestate_r; if (savestate_r0_5 == 0) { __asm__ __volatile__("" : : "m" (loop)); abort (); } __asm__("" : "=m" (savestate_ssb), "=r" (savestate_r)); savestate_r1_6 = savestate_r; if (savestate_r1_6 != 0) return; __asm__ __volatile__("" : : "m" (loop)); abort (); }
Comment 6 testcase started with r270550. I've posted a patch.
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:e1133c0205a7e2a65834a1af780b8da15eead2a9 commit r12-7540-ge1133c0205a7e2a65834a1af780b8da15eead2a9 Author: Marek Polacek <polacek@redhat.com> Date: Mon Mar 7 16:15:46 2022 -0500 rtl: ICE with thread_local and inline asm [PR104777] In r270550, Jakub fixed classify_insn to handle asm goto: if the asm can jump to a label, the insn should be a JUMP_INSN. However, as the following testcase shows, non-null ASM_OPERANDS_LABEL_VEC doesn't guarantee that the rtx has any actual labels it can branch to. Here, the rtvec has 0 elements because expand_asm_stmt created it: rtvec labelvec = rtvec_alloc (nlabels); // nlabels == 0 This causes an ICE in update_br_prob_note: BRANCH_EDGE (bb) crashes because there's no branch edge. I think we can fix this by checking that there is at least one label the asm can jump to before wrapping the ASM_OPERANDS in a JUMP_INSN. PR rtl-optimization/104777 gcc/ChangeLog: * rtl.cc (classify_insn): For ASM_OPERANDS, return JUMP_INSN only if ASM_OPERANDS_LABEL_VEC has at least one element. gcc/testsuite/ChangeLog: * gcc.dg/torture/tls/pr104777.c: New test.
Fixed on trunk so far.
The releases/gcc-11 branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:d66c45fdc14bf88f7390a75129462640c59ce48e commit r11-9647-gd66c45fdc14bf88f7390a75129462640c59ce48e Author: Marek Polacek <polacek@redhat.com> Date: Mon Mar 7 16:15:46 2022 -0500 rtl: ICE with thread_local and inline asm [PR104777] In r270550, Jakub fixed classify_insn to handle asm goto: if the asm can jump to a label, the insn should be a JUMP_INSN. However, as the following testcase shows, non-null ASM_OPERANDS_LABEL_VEC doesn't guarantee that the rtx has any actual labels it can branch to. Here, the rtvec has 0 elements because expand_asm_stmt created it: rtvec labelvec = rtvec_alloc (nlabels); // nlabels == 0 This causes an ICE in update_br_prob_note: BRANCH_EDGE (bb) crashes because there's no branch edge. I think we can fix this by checking that there is at least one label the asm can jump to before wrapping the ASM_OPERANDS in a JUMP_INSN. PR rtl-optimization/104777 gcc/ChangeLog: * rtl.c (classify_insn): For ASM_OPERANDS, return JUMP_INSN only if ASM_OPERANDS_LABEL_VEC has at least one element. gcc/testsuite/ChangeLog: * gcc.dg/torture/tls/pr104777.c: New test. (cherry picked from commit e1133c0205a7e2a65834a1af780b8da15eead2a9)
Fixed.
*** Bug 105936 has been marked as a duplicate of this bug. ***
Please backport the patch also to gcc-10 branch.
(In reply to Uroš Bizjak from comment #13) > Please backport the patch also to gcc-10 branch. 9.4.0 fails for me on ubuntu-20. 8.5.0 also fails. Please back-port to all possible branches.
9.x and 8.x are not supported anymore, nothing can be backported to those (upstream, some vendors do support those on their own).
I'll backport to 10.
The releases/gcc-10 branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:f2851a7cff4d74edca26d39c7bfa1264355a22ed commit r10-10828-gf2851a7cff4d74edca26d39c7bfa1264355a22ed Author: Marek Polacek <polacek@redhat.com> Date: Mon Mar 7 16:15:46 2022 -0500 rtl: ICE with thread_local and inline asm [PR104777] In r270550, Jakub fixed classify_insn to handle asm goto: if the asm can jump to a label, the insn should be a JUMP_INSN. However, as the following testcase shows, non-null ASM_OPERANDS_LABEL_VEC doesn't guarantee that the rtx has any actual labels it can branch to. Here, the rtvec has 0 elements because expand_asm_stmt created it: rtvec labelvec = rtvec_alloc (nlabels); // nlabels == 0 This causes an ICE in update_br_prob_note: BRANCH_EDGE (bb) crashes because there's no branch edge. I think we can fix this by checking that there is at least one label the asm can jump to before wrapping the ASM_OPERANDS in a JUMP_INSN. PR rtl-optimization/104777 gcc/ChangeLog: * rtl.c (classify_insn): For ASM_OPERANDS, return JUMP_INSN only if ASM_OPERANDS_LABEL_VEC has at least one element. gcc/testsuite/ChangeLog: * gcc.dg/torture/tls/pr104777.c: New test. (cherry picked from commit e1133c0205a7e2a65834a1af780b8da15eead2a9)
Done.