public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/111028] New: Incorrect optimization with -o1,-o2
@ 2023-08-15 11:42 zhaiqiming at baidu dot com
  2023-08-15 13:47 ` [Bug c++/111028] " rguenth at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: zhaiqiming at baidu dot com @ 2023-08-15 11:42 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 111028
           Summary: Incorrect optimization with -o1,-o2
           Product: gcc
           Version: 12.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zhaiqiming at baidu dot com
  Target Milestone: ---

======

[summary]

When I upgraded from gcc82 to gcc12, I found that 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.*inner_list_node).next->prev = (node.*inner_list_node).prev;
(node.*inner_list_node).prev->next = (node.*inner_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]

#include <stdlib.h>
#include <vector>
#include <iostream>
#include <pthread.h>

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@GOTPCREL(%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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
@ 2023-08-15 13:47 ` rguenth at gcc dot gnu.org
  2023-08-15 14:38 ` ppalka at gcc dot gnu.org
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-08-15 13:47 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
      Known to work|                            |9.5.0
      Known to fail|                            |10.5.0, 12.3.0, 13.2.0

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
I can confirm the finding, not sure if the program is valid though.  Neither
-fno-strict-aliasing nor -fno-lifetime-dse has any effect.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
  2023-08-15 13:47 ` [Bug c++/111028] " rguenth at gcc dot gnu.org
@ 2023-08-15 14:38 ` ppalka at gcc dot gnu.org
  2023-08-15 14:49 ` ppalka at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2023-08-15 14:38 UTC (permalink / raw)
  To: gcc-bugs

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

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ppalka at gcc dot gnu.org
           Keywords|needs-bisection             |

--- Comment #2 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Seems to have started with r10-515-g810c42c38d3731 / r271414.

The line

                T* entry(list_node_t &node) const { return &node == &_head ?
NULL : (T*)((char*)&node - (char*)_node_offset); }

seems suspiciously similar to PR96993 which was deemed invalid due to treating
the difference of two pointers as a valid pointer.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
  2023-08-15 13:47 ` [Bug c++/111028] " rguenth at gcc dot gnu.org
  2023-08-15 14:38 ` ppalka at gcc dot gnu.org
@ 2023-08-15 14:49 ` ppalka at gcc dot gnu.org
  2023-08-15 14:53 ` ppalka at gcc dot gnu.org
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2023-08-15 14:49 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Converting _node_offset from a pointer into an integer offset seems to fix the
testcase:

diff --git a/111028.C b/111028.C
index ed4106e..ef2b1be 100644
--- a/111028.C
+++ b/111028.C
@@ -15,7 +15,7 @@ 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); }
+               T* entry(list_node_t &node) const { return &node == &_head ?
NULL : (T*)((char*)&node - _node_offset); }

                void add(T &node)
                {
@@ -37,11 +37,11 @@ class list_t
                }

        protected:
-               static list_node_t const * const _node_offset;
+               static size_t 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);
+size_t const list_t<T, inner_list_node>::_node_offset = size_t(&(((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>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
                   ` (2 preceding siblings ...)
  2023-08-15 14:49 ` ppalka at gcc dot gnu.org
@ 2023-08-15 14:53 ` ppalka at gcc dot gnu.org
  2023-08-16  4:09 ` zhaiqiming at baidu dot com
  2023-08-17  6:45 ` rguenth at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2023-08-15 14:53 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Or simply just:

diff --git a/111028.C b/111028.C
index ed4106e..85f1c2a 100644
--- a/111028.C
+++ b/111028.C
@@ -15,7 +15,7 @@ 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); }
+               T* entry(list_node_t &node) const { return &node == &_head ?
NULL : (T*)((char*)&node - (size_t)_node_offset); }

                void add(T &node)
                {

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
                   ` (3 preceding siblings ...)
  2023-08-15 14:53 ` ppalka at gcc dot gnu.org
@ 2023-08-16  4:09 ` zhaiqiming at baidu dot com
  2023-08-17  6:45 ` rguenth at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: zhaiqiming at baidu dot com @ 2023-08-16  4:09 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from zhaiqiming at baidu dot com ---
(In reply to Patrick Palka from comment #4)

thanks for your plan. Because my project need -o2 optimization, i use "#pragma
GCC optimize("-O0")" to temporarily solve the problem with this function. hope
this case can make gcc-optimization better at a higher version.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/111028] Incorrect optimization with -o1,-o2
  2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
                   ` (4 preceding siblings ...)
  2023-08-16  4:09 ` zhaiqiming at baidu dot com
@ 2023-08-17  6:45 ` rguenth at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-08-17  6:45 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> ---
Yeah, if you subtract two pointers like

   (char*)&node - (char*)_node_offset

then both have to point to the same object (otherwise the behavior is
undefined) and you get a difference in the number of elements.
That difference isn't a pointer.  The correct fix is as suggested, this isn't
a bug in GCC.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-08-17  6:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-15 11:42 [Bug c++/111028] New: Incorrect optimization with -o1,-o2 zhaiqiming at baidu dot com
2023-08-15 13:47 ` [Bug c++/111028] " rguenth at gcc dot gnu.org
2023-08-15 14:38 ` ppalka at gcc dot gnu.org
2023-08-15 14:49 ` ppalka at gcc dot gnu.org
2023-08-15 14:53 ` ppalka at gcc dot gnu.org
2023-08-16  4:09 ` zhaiqiming at baidu dot com
2023-08-17  6:45 ` rguenth at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).