[llvm-bugs] [Bug 44472] New: Wrong optimization: devirtualization vs. conditional equivalence

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jan 6 09:19:46 PST 2020


https://bugs.llvm.org/show_bug.cgi?id=44472

            Bug ID: 44472
           Summary: Wrong optimization: devirtualization vs. conditional
                    equivalence
           Product: new-bugs
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: ch3root at openwall.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

This is based on bug 34548, comment 49, and bug 44313. It seems there was an
effort to fix the problem as it applies to devirtualization independently from
the general case, so filing this separately. As mentioned in the referenced
comment, GVN changes a pointer to an older one inside the `if` (it doesn't
matter which pointer is on the left in the comparison and which one is on the
right). Visible only with -fstrict-vtable-pointers.

Devirtualization seems not to be concerned with past-the-end pointers and with
`restrict`, so the focus is on the case of a living object located at the same
place where another, now dead, object was located, e.g.:
- after new/delete/new (or malloc/free/malloc);
- after placement new;
- when two local variables in disjoint blocks occupy the same space.

It seems comparison of naked pointers and casts to integers are handled. What I
spotted missing:
- conversions to pointers to classes without virtual tables -- probably just an
oversight;
- direct memory access like memcpy/memcmp -- much more serious problem.

Example with pointers to a class without virtual tables and a placement new:

----------------------------------------------------------------------
#include <stdio.h>
#include <new>

struct B {
    void m() {}
};

struct X : B {
    virtual void foo() { puts("foo"); }
};

struct Y : B {
    virtual void bar() { puts("bar"); }
};

static_assert(sizeof(X) == sizeof(Y));

int main()
{
    B *q = new Y;
    X *p = new (q) X;

    if (p == q)
        p->foo();
}
----------------------------------------------------------------------
$ clang++ -std=c++2a -Wall -fstrict-vtable-pointers test.cc && ./a.out
foo
$ clang++ -std=c++2a -Wall -fstrict-vtable-pointers -O3 test.cc && ./a.out
bar
----------------------------------------------------------------------
clang x86-64 version: clang version 10.0.0
(https://github.com/llvm/llvm-project.git
c5fb73c5d1b3f1adb77d99fc85c594b48bff08f9)
----------------------------------------------------------------------

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200106/18a87691/attachment.html>


More information about the llvm-bugs mailing list