https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111026
--- Comment #2 from zhaiqiming at baidu dot com ---
(In reply to zhaiqiming from comment #1)
> ======
>
> [summary]
>
> When I upgraded from gcc82 to gcc12, I found that linked_list_t::del
> execution did not meet expectations.
> Looking at .s , i noticed that the assembly statements corresponding to the
> following two lines have disappeared.
>
> (node.*list_node).next->prev = (node.*list_node).prev;
> (node.*list_node).prev->next = (node.*list_node).next;
>
>
> ======
>
> [environment-gcc12]
> Reading specs from
> /home/opt/compiler/gcc-12/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/specs
> COLLECT_GCC=/home/opt/compiler/gcc-12/bin/gcc
> COLLECT_LTO_WRAPPER=/home/opt/compiler/gcc-12/bin/../libexec/gcc/x86_64-pc-
> linux-gnu/12.1.0/lto-wrapper
> Target: x86_64-pc-linux-gnu
> Configured with: ../configure --prefix=/opt/compiler/gcc-12
> --with-local-prefix=/opt/compiler/gcc-12
> --with-native-system-header-dir=/opt/compiler/gcc-12/include
> --enable-languages=c,c++ --disable-libstdcxx-pch --disable-multilib
> --with-default-libstdcxx-abi=gcc4-compatible --disable-bootstrap
> --with-sysroot=/ --build=x86_64-pc-linux-gnu --target=x86_64-pc-linux-gnu
> --enable-gold --enable-lto
> Thread model: posix
> Supported LTO compression algorithms: zlib
> gcc version 12.1.0 (GCC)
>
> [environment-gcc82]
> Using built-in specs.
> COLLECT_GCC=/home/opt/compiler/gcc-8.2/gcc-8.2/bin/gcc
> COLLECT_LTO_WRAPPER=/home/opt/compiler/gcc-8.2/gcc-8.2/bin/../libexec/gcc/
> x86_64-pc-linux-gnu/8.2.0/lto-wrapper
> Target: x86_64-pc-linux-gnu
> Configured with: ../configure --prefix=/opt/compiler/gcc-8.2
> --with-local-prefix=/opt/compiler/gcc-8.2
> --with-native-system-header-dir=/opt/compiler/gcc-8.2/include
> --enable-languages=c,c++ --disable-libstdcxx-pch --disable-multilib
> --disable-bootstrap --with-default-libstdcxx-abi=gcc4-compatible
> Thread model: posix
> gcc version 8.2.0 (GCC)
>
> ======
>
> [source code]
>
>
> struct list_node_t
> {
> list_node_t *next;
> list_node_t *prev;
> };
>
> template <typename T, list_node_t T::*inner_list_node>
> class list_t
> {
> public:
> list_t() { _head.next = _head.prev = &_head; }
> bool is_empty() const { return _head.next == &_head; }
> T* entry(list_node_t &node) const { return &node == &_head ?
> NULL :
> (T*)((char*)&node - (char*)_node_offset); }
>
> void add(T &node)
> {
> _head.next->prev = &(node.*inner_list_node);
> (node.*inner_list_node).next = _head.next;
> (node.*inner_list_node).prev = &_head;
> _head.next = &(node.*inner_list_node);
> }
>
>
> static void del(T &node)
> {
> int slot_1 = 10000;
> printf("slot_1 %d\n", slot_1);
> (node.*inner_list_node).next->prev =
> (node.*inner_list_node).prev;
> (node.*inner_list_node).prev->next =
> (node.*inner_list_node).next;
> int slot_2 = 20000;
> printf("slot_2 %d\n", slot_2);
> }
>
> protected:
> static list_node_t const * const _node_offset;
> list_node_t _head;
> };
> template <typename T, list_node_t T::*inner_list_node>
> list_node_t const * const list_t<T, inner_list_node>::_node_offset = &(((T
> *)0)->*inner_list_node);
>
> template <typename T, list_node_t T::*inner_list_node>
> class safe_list_t: public list_t<T, inner_list_node>
> {
> public:
> safe_list_t(): _alive(1),_num(0)
> {
> pthread_mutex_init(&_mutex, NULL);
> pthread_cond_init(&_cond, NULL);
> }
>
> ~safe_list_t()
> {
> pthread_cond_destroy(&_cond);
> pthread_mutex_destroy(&_mutex);
> }
>
> int len()
> {
> return _num;
> }
>
> void put(T &node)
> {
> pthread_mutex_lock(&_mutex);
> if (_alive)
> {
> this->add(node);
> ++_num;
> }
> pthread_mutex_unlock(&_mutex);
> pthread_cond_signal(&_cond);
> }
>
> T* get()
> {
> T *ret;
> pthread_mutex_lock(&_mutex);
> while (_alive && list_t<T, inner_list_node>::is_empty())
> pthread_cond_wait(&_cond, &_mutex);
> if (_alive)
> {
> ret = this->entry(*list_t<T, inner_list_node>::_head.prev);
> this->del(*ret);
> --_num;
> }
> else
> {
> ret = NULL;
> }
> pthread_mutex_unlock(&_mutex);
> return ret;
> }
>
> protected:
> pthread_mutex_t _mutex;
> pthread_cond_t _cond;
> int _alive;
> int _num;
> };
>
> template <class T>
> class worker_t
> {
> public:
> T *t;
> list_node_t inner_task_list_node;
>
> public:
> worker_t():t(NULL)
> {
> t = new T;
> }
> worker_t(T *tt):t(tt)
> {
> }
>
> ~worker_t()
> {
> delete t;
> }
>
> private:
> worker_t(const worker_t& rhs);
> worker_t& operator=(const worker_t& rhs);
> };
>
> int main() {
> safe_list_t<worker_t<size_t>, &worker_t<size_t>::inner_task_list_node>
> _serialize_merge_scan_move_list;
>
> auto * worker_0 = new worker_t<size_t>;
> *worker_0->t = 100;
> _serialize_merge_scan_move_list.put(*worker_0);
>
> auto * worker_1 = new worker_t<size_t>;
> *worker_1->t = 200;
> _serialize_merge_scan_move_list.put(*worker_1);
>
> auto* temp_0 = _serialize_merge_scan_move_list.get();
> printf("temp_0->t = %zu\n", *temp_0->t);
> delete temp_0;
>
>
> auto* temp_1 = _serialize_merge_scan_move_list.get();
> printf("temp_1->t = %zu\n", *temp_1->t);
> delete temp_1;
> }
>
>
> =====
>
> [.s]
>
> [important parts - gcc82]
> Shell command: /home/opt/compiler/gcc-8.2/gcc-8.2/bin/gcc -S
> -ohello82-use.s -save-temps -std=c++11 -O2 -pipe -Wall -Wextra -W -fPIC
> -Werror=return-local-addr -Werror=return-type test_main.cpp -lstdc++
> -lpthread -lssl -lcrypto -lrt -lz -ldl
>
>
> .L8:
> .cfi_restore_state
> movq 8(%rbx), %r12
> cmpq %rbx, %r12
> je .L15
> movq
> _ZN6list_tI8worker_tImEXadL_ZNS1_20inner_task_list_nodeEEEE12_node_offsetE@GO
> TPCREL(%rip), %rax
> movl $10000, %esi
> leaq .LC0(%rip), %rdi
> subq (%rax), %r12
> xorl %eax, %eax
> call printf@PLT
> movq 8(%r12), %rdx
> movq 16(%r12), %rax
> movl $20000, %esi
> leaq .LC1(%rip), %rdi
> movq %rax, 8(%rdx)
> movq %rdx, (%rax)
> xorl %eax, %eax
> call printf@PLT
> subl $1, 108(%rbx)
> movq %rbp, %rdi
> call pthread_mutex_unlock@PLT
> movq %r12, %rax
> popq %rbx
> .cfi_remember_state
> .cfi_def_cfa_offset 24
> popq %rbp
> .cfi_def_cfa_offset 16
> popq %r12
> .cfi_def_cfa_offset 8
> ret
>
>
> [important parts - gcc12]
> Shell command: /home/opt/compiler/gcc-12/bin/gcc -S -ohello12-use.s
> -save-temps -std=c++11 -O2 -pipe -Wall -Wextra -W -fPIC
> -Werror=return-local-addr -Werror=return-type test_main.cpp -lstdc++
> -lpthread -lssl -lcrypto -lrt -lz -ldl
>
>
> .L11:
> movl $10000, %esi
> leaq .LC0(%rip), %rdi
> xorl %eax, %eax
> call printf@PLT
> movl $20000, %esi
> leaq .LC1(%rip), %rdi
> xorl %eax, %eax
> call printf@PLT
> subl $1, 108(%rbx)
> movq %rbp, %rdi
> call pthread_mutex_unlock@PLT
> movq %r12, %rax
> popq %rbx
> .cfi_remember_state
> .cfi_def_cfa_offset 24
> popq %rbp
> .cfi_def_cfa_offset 16
> popq %r12
> .cfi_def_cfa_offset 8
> ret
> .p2align 4,,10
> .p2align 3
linked_list_t::del => list_t::del