public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
@ 2020-12-04 13:54 barry.revzin at gmail dot com
  2020-12-04 13:59 ` [Bug c++/98142] " jakub at gcc dot gnu.org
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: barry.revzin at gmail dot com @ 2020-12-04 13:54 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 98142
           Summary: fstrict-enums optimization applied only for unscoped
                    enums with unfixed underlying type
           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: ---

Consider this simple example

namespace N4 {
enum E {
    A, B, C, D
};

bool compare_logical(E x) { return (x == E::B) || (x == E::D); }
}

Compiled with -O3 -fstrict-enums, gcc 10.2 emits:

N4::compare_logical(N4::E):
        mov     eax, edi
        and     eax, 1
        ret

As desired. I am telling gcc to make an assumption about the range of values,
and it is optimizing based on the fact that 5 is not a valid enumerator.
Fantastic.

However, any other definition of E, whether it's scoped:

enum class E {
    A, B, C, D
};

Or it has a fixed underlying type:

enum E : unsigned {
    A, B, C, D
};

or both:

enum class E : unsigned {
    A, B, C, D
};

in all cases emits the same alternative code:

N3::compare_logical(N3::E):
        and     edi, -3
        cmp     edi, 1
        sete    al
        ret

It does this extra work to be able to reject, for instance, the value 5. But
I'm trying to tell the optimizer that this does not happen.

Full example on compiler explorer: https://godbolt.org/z/Tq58hK

Can this optimization be extended to cover these additional cases, or is there
some reason it cannot?

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
@ 2020-12-04 13:59 ` jakub at gcc dot gnu.org
  2020-12-04 14:10 ` barry.revzin at gmail dot com
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-04 13:59 UTC (permalink / raw)
  To: gcc-bugs

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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I don't see how it could be extended to the case with the fixed underlying
type,
std::byte
is
enum class byte : unsigned char {};
yet it needs to support all the 0 to (unsigned char)~0 values even with
-fstrict-enums.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
  2020-12-04 13:59 ` [Bug c++/98142] " jakub at gcc dot gnu.org
@ 2020-12-04 14:10 ` barry.revzin at gmail dot com
  2020-12-04 14:13 ` jakub at gcc dot gnu.org
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: barry.revzin at gmail dot com @ 2020-12-04 14:10 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Barry Revzin <barry.revzin at gmail dot com> ---
That is a great point.

I guess in general this is kind of a scary optimization, since it doesn't seem
like it's really a global thing? Perhaps this calls for an attribute?

[[gnu::i_promise_on_penalty_of_ub_that_only_these_values_are_used]]
enum class E : unsigned int { A, B, C, D };

Or, you know, [[gnu::strict_enum]] or something.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
  2020-12-04 13:59 ` [Bug c++/98142] " jakub at gcc dot gnu.org
  2020-12-04 14:10 ` barry.revzin at gmail dot com
@ 2020-12-04 14:13 ` jakub at gcc dot gnu.org
  2020-12-04 15:03 ` redi at gcc dot gnu.org
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-04 14:13 UTC (permalink / raw)
  To: gcc-bugs

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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org,
                   |                            |mpolacek at gcc dot gnu.org,
                   |                            |redi at gcc dot gnu.org

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Maybe.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (2 preceding siblings ...)
  2020-12-04 14:13 ` jakub at gcc dot gnu.org
@ 2020-12-04 15:03 ` redi at gcc dot gnu.org
  2020-12-04 15:06 ` jakub at gcc dot gnu.org
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2020-12-04 15:03 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Barry Revzin from comment #2)
> I guess in general this is kind of a scary optimization, since it doesn't
> seem like it's really a global thing? Perhaps this calls for an attribute?
> 
> [[gnu::i_promise_on_penalty_of_ub_that_only_these_values_are_used]]
> enum class E : unsigned int { A, B, C, D };
> 
> Or, you know, [[gnu::strict_enum]] or something.

It couldn't be called "strict_enum". The -fstrict-enums flag means assume no
invalid values, i.e. nothing outside the valid values of the enum type. For any
enum type with a fixed underlying type, all values of the underlying type are
valid values of the enum type, so there are no invalid values. So "strict_enum"
as the attribute name would be contradicting the meaning of -fstrict-enums.

So purely on that basis, the better name would be
"i_promise_on_penalty_of_ub_that_only_these_values_are_used"

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (3 preceding siblings ...)
  2020-12-04 15:03 ` redi at gcc dot gnu.org
@ 2020-12-04 15:06 ` jakub at gcc dot gnu.org
  2020-12-04 15:11 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-04 15:06 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Perhaps spell it as gnu::exhaustive_enum then or something similar?

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (4 preceding siblings ...)
  2020-12-04 15:06 ` jakub at gcc dot gnu.org
@ 2020-12-04 15:11 ` redi at gcc dot gnu.org
  2020-12-04 15:12 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2020-12-04 15:11 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Barry Revzin from comment #0)
> As desired. I am telling gcc to make an assumption about the range of
> values, and it is optimizing based on the fact that 5 is not a valid
> enumerator.

N.B. it has nothing to do with whether it's an enumerator.

Given enum E2 { zero, two=2 } this has the same range of valid values, and so
E2(1) and E2(3) are valid, even though there are no enumerators with those
values, and E2(3) has a higher value than two.

The only enumerators that matter are the ones with the minimum and maximum
values, as those determine the range of valid values as per [dcl.enum] p8. All
other enumerators are just named constants, they have no bearing on the valid
values or optimizations.

All values within the enum's range are valid, whether there is an enumerator
with that value or not.

What you're asking for is not how C++ enumeration types work, although it is
how many, many people think they work, or want them to work.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (5 preceding siblings ...)
  2020-12-04 15:11 ` redi at gcc dot gnu.org
@ 2020-12-04 15:12 ` redi at gcc dot gnu.org
  2020-12-07  7:45 ` rguenth at gcc dot gnu.org
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2020-12-04 15:12 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #5)
> Perhaps spell it as gnu::exhaustive_enum then or something similar?

I like that.

It would be much stricter than -fstrict-enums as it would say that you won't
create E2(1) or E2(3) even though those are valid values.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (6 preceding siblings ...)
  2020-12-04 15:12 ` redi at gcc dot gnu.org
@ 2020-12-07  7:45 ` rguenth at gcc dot gnu.org
  2020-12-07 10:32 ` redi at gcc dot gnu.org
  2020-12-07 10:32 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-12-07  7:45 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
IIRC -fstrict-enums just exposes what the C++ language spec already guarantees
and we're much more forgiving by default.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (7 preceding siblings ...)
  2020-12-07  7:45 ` rguenth at gcc dot gnu.org
@ 2020-12-07 10:32 ` redi at gcc dot gnu.org
  2020-12-07 10:32 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2020-12-07 10:32 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Right, which is as per [dcl.enum] p8.

A type which only allows values corresponding to named enumerators is not
possible in standard C++.

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

* [Bug c++/98142] fstrict-enums optimization applied only for unscoped enums with unfixed underlying type
  2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
                   ` (8 preceding siblings ...)
  2020-12-07 10:32 ` redi at gcc dot gnu.org
@ 2020-12-07 10:32 ` redi at gcc dot gnu.org
  9 siblings, 0 replies; 11+ messages in thread
From: redi at gcc dot gnu.org @ 2020-12-07 10:32 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement

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

end of thread, other threads:[~2020-12-07 10:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-04 13:54 [Bug c++/98142] New: fstrict-enums optimization applied only for unscoped enums with unfixed underlying type barry.revzin at gmail dot com
2020-12-04 13:59 ` [Bug c++/98142] " jakub at gcc dot gnu.org
2020-12-04 14:10 ` barry.revzin at gmail dot com
2020-12-04 14:13 ` jakub at gcc dot gnu.org
2020-12-04 15:03 ` redi at gcc dot gnu.org
2020-12-04 15:06 ` jakub at gcc dot gnu.org
2020-12-04 15:11 ` redi at gcc dot gnu.org
2020-12-04 15:12 ` redi at gcc dot gnu.org
2020-12-07  7:45 ` rguenth at gcc dot gnu.org
2020-12-07 10:32 ` redi at gcc dot gnu.org
2020-12-07 10:32 ` redi 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).