public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction
@ 2020-05-28 14:07 barry.revzin at gmail dot com
  2020-05-28 14:17 ` [Bug c++/95384] " barry.revzin at gmail dot com
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: barry.revzin at gmail dot com @ 2020-05-28 14:07 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 95384
           Summary: Poor codegen cause by using base class instead of
                    member for Optional construction
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

Following up on #95383:

struct nullopt_t {} inline constexpr nullopt{};

template <typename T>
struct OptionalStorage {
    struct Empty { };
    union {
        Empty _;
        T value;
    };
    bool engaged;

    OptionalStorage(nullopt_t) : _(), engaged(false) { }
    OptionalStorage(T v) : value(v), engaged(true) { }
};

template <typename T>
struct OptionalWithBase : OptionalStorage<T> {
    using OptionalStorage<T>::OptionalStorage;
};

template <typename T>
struct OptionalWithMember {
    OptionalStorage<T> o;
    OptionalWithMember(nullopt_t) : o(nullopt) { }
    OptionalWithMember(T v) : o(v) { }
};

OptionalWithBase<int> foo_with_base(bool b) {
    if (b) {
        return 42;
    }
    return nullopt;
}

OptionalWithMember<int> foo_with_member(bool b) {
    if (b) {
        return 42;
    }
    return nullopt;
}

OptionalWithBase<T> and OptionalWithMember<T> should be the same thing. It's
just that one inherits from its storage and the other has it as a member. But
the codegen is very different (https://godbolt.org/z/j8m68Y), probably
something to do with tail padding?

gcc 10.1 -O2:

foo_with_base(bool):
        test    dil, dil
        je      .L2
        mov     DWORD PTR [rsp-8], 42
        mov     BYTE PTR [rsp-4], 1
        mov     rax, QWORD PTR [rsp-8]
        ret
.L2:
        mov     BYTE PTR [rsp-4], 0
        mov     rax, QWORD PTR [rsp-8]
        ret
foo_with_member(bool):
        test    dil, dil
        mov     eax, 0
        movabs  rdx, 4294967338
        cmovne  rax, rdx
        ret

gcc 10.2 -O3 or gcc trunk -O2:

foo_with_base(bool):
        xor     eax, eax
        test    dil, dil
        je      .L2
        mov     DWORD PTR [rsp-8], 42
        mov     eax, 1
.L2:
        mov     BYTE PTR [rsp-4], al
        mov     rax, QWORD PTR [rsp-8]
        ret
foo_with_member(bool):
        xor     edx, edx
        mov     ecx, 42
        test    dil, dil
        cmovne  rax, rcx
        mov     ecx, 1
        cmovne  rdx, rcx
        movabs  rcx, -1095216660481
        and     rax, rcx
        sal     rdx, 32
        or      rax, rdx
        ret

clang 10, -O2 or -O3:

foo_with_base(bool):                     # @foo_with_base(bool)
        shl     rdi, 32
        lea     rax, [rdi + 42]
        ret
foo_with_member(bool):                   # @foo_with_member(bool)
        shl     rdi, 32
        lea     rax, [rdi + 42]
        ret

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

* [Bug c++/95384] Poor codegen cause by using base class instead of member for Optional construction
  2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
@ 2020-05-28 14:17 ` barry.revzin at gmail dot com
  2020-06-03 23:50 ` glisse at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: barry.revzin at gmail dot com @ 2020-05-28 14:17 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Barry Revzin <barry.revzin at gmail dot com> ---
Here's a simpler example: https://godbolt.org/z/FD7uEQ

If the engaged member is an int instead of a bool (to remove the tail padding),
gcc generates better code.

This follows up on "PR 95383"

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

* [Bug c++/95384] Poor codegen cause by using base class instead of member for Optional construction
  2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
  2020-05-28 14:17 ` [Bug c++/95384] " barry.revzin at gmail dot com
@ 2020-06-03 23:50 ` glisse at gcc dot gnu.org
  2021-08-04  4:48 ` [Bug tree-optimization/95384] " pinskia at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: glisse at gcc dot gnu.org @ 2020-06-03 23:50 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Marc Glisse <glisse at gcc dot gnu.org> ---
Or with less templates:

struct A {
  A() = default;
  union S {
    constexpr S() noexcept : e() { }
    struct {} e;
    int i;
  } s;
  bool b = false;
};
struct B : A {
  B() = default;
  using A::A;
};
B f() { return {}; }


        movl    $0, -12(%rsp)
        movq    -16(%rsp), %rax
        ret

instead of a plain

        xorl    %eax, %eax

optimized dump is

  MEM <char[4]> [(struct B *)&D.2265 + 4B] = {};
  MEM[(union S *)&D.2265] ={v} {CLOBBER};
  D.2275 = D.2265;
  D.2265 ={v} {CLOBBER};
  return D.2275;

expand

(insn 5 2 6 2 (set (mem/c:SI (plus:DI (reg/f:DI 77 virtual-stack-vars)
                (const_int -12 [0xfffffffffffffff4])) [7 MEM <char[4]> [(struct
B *)&D.2265 + 4B]+0 S4 A32])
        (const_int 0 [0])) "o.cc":14:17 -1
     (nil))
(insn 6 5 7 2 (set (reg:DI 83)
        (mem/c:DI (plus:DI (reg/f:DI 77 virtual-stack-vars)
                (const_int -16 [0xfffffffffffffff0])) [7 D.2265+0 S8 A64]))
"o.cc":14:17 -1
     (nil))
(insn 7 6 8 2 (set (mem/c:DI (plus:DI (reg/f:DI 77 virtual-stack-vars)
                (const_int -8 [0xfffffffffffffff8])) [7 D.2275+0 S8 A64])
        (reg:DI 83)) "o.cc":14:17 -1
     (nil))
(insn 8 7 9 2 (set (reg:DI 84)
        (const_int 0 [0])) "o.cc":14:17 -1
     (nil))
(insn 9 8 10 2 (set (reg:DI 84)
        (mem/c:DI (plus:DI (reg/f:DI 77 virtual-stack-vars)
                (const_int -8 [0xfffffffffffffff8])) [7 D.2275+0 S8 A64]))
"o.cc":14:17 -1
     (nil))
(insn 10 9 11 2 (set (reg:DI 85)
        (reg:DI 84)) "o.cc":14:17 -1
     (nil))
(insn 11 10 15 2 (set (reg:DI 82 [ <retval> ])
        (reg:DI 85)) "o.cc":14:17 -1
     (nil))
(insn 15 11 16 2 (set (reg/i:DI 0 ax)
        (reg:DI 82 [ <retval> ])) "o.cc":14:20 -1
     (nil))
(insn 16 15 0 2 (use (reg/i:DI 0 ax)) "o.cc":14:20 -1
     (nil))

and dfinish

(insn:TI 5 2 15 2 (set (mem/c:SI (plus:DI (reg/f:DI 7 sp)
                (const_int -12 [0xfffffffffffffff4])) [7 MEM <char[4]> [(struct
B *)&D.2265 + 4B]+0 S4 A32])
        (const_int 0 [0])) "o.cc":14:17 67 {*movsi_internal}
     (nil))
(insn 15 5 16 2 (set (reg/i:DI 0 ax)
        (mem/c:DI (plus:DI (reg/f:DI 7 sp)
                (const_int -16 [0xfffffffffffffff0])) [7 D.2265+0 S8 A64]))
"o.cc":14:20 66 {*movdi_internal}
     (nil))
(insn 16 15 25 2 (use (reg/i:DI 0 ax)) "o.cc":14:20 -1
     (nil))

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

* [Bug tree-optimization/95384] Poor codegen cause by using base class instead of member for Optional construction
  2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
  2020-05-28 14:17 ` [Bug c++/95384] " barry.revzin at gmail dot com
  2020-06-03 23:50 ` glisse at gcc dot gnu.org
@ 2021-08-04  4:48 ` pinskia at gcc dot gnu.org
  2021-08-04  5:04 ` pinskia at gcc dot gnu.org
  2021-10-13  0:08 ` barry.revzin at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-04  4:48 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|c++                         |tree-optimization
           Severity|normal                      |enhancement

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

* [Bug tree-optimization/95384] Poor codegen cause by using base class instead of member for Optional construction
  2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
                   ` (2 preceding siblings ...)
  2021-08-04  4:48 ` [Bug tree-optimization/95384] " pinskia at gcc dot gnu.org
@ 2021-08-04  5:04 ` pinskia at gcc dot gnu.org
  2021-10-13  0:08 ` barry.revzin at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-04  5:04 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2021-08-04

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Confirmed.
All bad around.  I wonder if we could "expose" some of the details of the ABI
late in gimple to simplify/solve this.

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

* [Bug tree-optimization/95384] Poor codegen cause by using base class instead of member for Optional construction
  2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
                   ` (3 preceding siblings ...)
  2021-08-04  5:04 ` pinskia at gcc dot gnu.org
@ 2021-10-13  0:08 ` barry.revzin at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: barry.revzin at gmail dot com @ 2021-10-13  0:08 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Barry Revzin <barry.revzin at gmail dot com> ---
Here's another example of the same kind of issue
(https://godbolt.org/z/KWr9rMssj):

template <class T, class U>
struct tagged_union {
    tagged_union(T t) : index(0), a(t) { }
    tagged_union(U u) : index(1), b(u) { }


    union {
        T a;
        U b;
    };
    char index;
};

struct X { int i; };
struct Y { int j; };

tagged_union<X, Y> as_tagged_union(X x) {
    return x;
}

template <typename T, typename U>
struct tagged_union_wrapped : tagged_union<T, U> {
    using tagged_union<T, U>::tagged_union;
};

auto as_tagged_union2(X x) {
    return tagged_union_wrapped<X, Y>(x);
}

this on -O3 emits:

as_tagged_union(X):
        mov     eax, edi
        ret
as_tagged_union2(X):
        mov     DWORD PTR [rsp-8], edi
        mov     BYTE PTR [rsp-4], 0
        mov     rax, QWORD PTR [rsp-8]
        ret

If you change the index member from 'char' to 'int', causing the tail padding
to disappear, as_tagged_union2 improves to the same code gen as
as_tagged_union.

This is relevant for std::variant performance. std::variant<X, Y> behaves like
tagged_union_wrapped<X, Y>, whereas if you drop down to the implementation
details and directly use _Variant_storage_alias<X, Y>, that behaves like
tagged_union<X, Y> for these purposes.

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

end of thread, other threads:[~2021-10-13  0:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-28 14:07 [Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction barry.revzin at gmail dot com
2020-05-28 14:17 ` [Bug c++/95384] " barry.revzin at gmail dot com
2020-06-03 23:50 ` glisse at gcc dot gnu.org
2021-08-04  4:48 ` [Bug tree-optimization/95384] " pinskia at gcc dot gnu.org
2021-08-04  5:04 ` pinskia at gcc dot gnu.org
2021-10-13  0:08 ` barry.revzin at gmail dot com

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