From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id BCD19387085E; Thu, 28 May 2020 13:56:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BCD19387085E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1590674176; bh=tt9nH/CkXbZAfm3+00VMAzE3no7yYT2a36qvVrNbiAo=; h=From:To:Subject:Date:From; b=VkxA+2JpkrCai2anQNE0xdjBtGiuNFvQqhK+MiwV2VDQ135pwWXIDde186cFWaums 24jFzPP2JNQrNCEl8fJaLacfldTz9IoyDRX4R4Oi2g7RXOoSctwLDyWGK9m8MITpjv r3dGrELG2rl3AE55MeTgrW5J9EepyMqJvv8CAE1M= From: "barry.revzin at gmail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/95383] New: Poor codegen when constructing a trivial Optional Date: Thu, 28 May 2020 13:56:16 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 10.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: barry.revzin at gmail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 May 2020 13:56:16 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D95383 Bug ID: 95383 Summary: Poor codegen when constructing a trivial Optional 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: --- Here is a complete example: struct nullopt_t {} inline constexpr nullopt{}; template struct Optional { struct Empty { }; union { Empty _; T value; }; bool engaged; Optional(nullopt_t) : _(), engaged(false) { } Optional(T v) : value(v), engaged(true) { } }; Optional foo(bool b) { if (b) { return 42; } return nullopt; } Optional here is a valid implementation strategy for trivial types, like in= t. You can see some codegen examples here: https://godbolt.org/z/KwuWzB gcc 10.1 -O2 emits: foo(bool): test dil, dil mov eax, 0 movabs rdx, 4294967338 cmovne rax, rdx ret gcc 10.1 -O3 is worse: foo(bool): xor eax, eax mov ecx, 42 test dil, dil cmovne rdx, rcx mov ecx, 1 cmovne rax, rcx movabs rcx, -1095216660481 and rdx, rcx sal rax, 32 or rax, rdx ret gcc trunk (as of today) -O2 is the same as this bad -O3 version. clang 10, on the other hand, on -O2 or -O3, emits: foo(bool): # @foo(bool) shl rdi, 32 lea rax, [rdi + 42] ret which is much better.=20 Using std::optional instead of this Optional (https://godbolt.org/z/By-fYx)= for comparison, clang emits the same code as above. gcc 10 -O3 emits a branch: foo(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=