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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |missed-optimization
             Status|RESOLVED                    |NEW
   Last reconfirmed|                            |2018-11-09
                 CC|                            |msebor at gcc dot gnu.org
         Resolution|INVALID                     |---
     Ever confirmed|0                           |1

--- Comment #12 from Martin Sebor <msebor at gcc dot gnu.org> ---
I do agree there is room for improvement here.  Consider the following test
case:

  $ cat t.c && gcc -O2 -S -Wall -Wextra -Wpedantic -Wswitch-enum
-fdump-tree-optimized=/dev/stdout t.c

  enum E { e0 } e;

  int f (void)
  {
    switch (e)
      case e0: return 0;
  }
  t.c: In function ‘f’:
  t.c:7:1: warning: control reaches end of non-void function [-Wreturn-type]
      7 | }
        | ^

  ;; Function f (f, funcdef_no=0, decl_uid=1909, cgraph_uid=1, symbol_order=1)

  f ()
  {
    E e.0_1;

    <bb 2> [local count: 1073741824]:
    e.0_1 = e;
    if (e.0_1 == 0)
      goto <bb 3>; [50.00%]
    else
      goto <bb 4>; [50.00%]

    <bb 3> [local count: 536870913]:
    return 0;

    <bb 4> [local count: 536870913]:
    return;

  }

The -Wswitch-enum option doesn't warn about the switch statement not handling
switch values that don't correspond to any of the enumerators.  To have it
diagnosed the -Wswitch-default option has to be explicitly specified (it's off
by default).

Given that, I believe the same logic should apply to the -Wreturn-type warning:
it should not trigger for the snippet above or for the test case in comment #0
unless explicitly requested somehow (perhaps it should consider
-Wswitch-default).

In addition, note the comparison to zero in the optimized GIMPLE.  It's
unnecessary because the function returns no value when the value of e is
non-zero.  Clang notices that and avoids the comparison.  But perhaps a better
example to illustrate the missed optimization opportunity than the contrived
test case above is this:

  enum E { e0, e1, e2 } e;

  int f (void)
  {
    switch (e)
    {
      case e0: return 1;
      case e1: return 2;
      case e2: return 3;
    }
  }

Here, GCC also emits the same pointless comparison/branch:

  f:
        movl    e(%rip), %eax
        cmpl    $2, %eax
        ja      .L2
        addl    $1, %eax
        ret
  .L2:
        ret

Reply via email to