public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Why does gcc suck at switch()?
@ 2003-10-03 14:56 Matthew Wilcox
  2003-10-05 16:53 ` [ACPI] " Pavel Machek
  2003-10-12  5:49 ` law
  0 siblings, 2 replies; 3+ messages in thread
From: Matthew Wilcox @ 2003-10-03 14:56 UTC (permalink / raw)
  To: gcc; +Cc: acpi-devel


Why does gcc generate worse code for switch() statements than for
multiple-if?

$ gcc --version
gcc (GCC) 3.3.2 20030908 (Debian prerelease)

I would expect a compiler to produce the same code for these cases.
Instead, switch is worse than the multiple-if:

-       switch (event) {
-       case ACPI_THERMAL_NOTIFY_TEMPERATURE:
+       if (event == ACPI_THERMAL_NOTIFY_TEMPERATURE) {
                acpi_thermal_check(tz);
-               break;
-       case ACPI_THERMAL_NOTIFY_THRESHOLDS:
+       } else if (event == ACPI_THERMAL_NOTIFY_THRESHOLDS) {
                acpi_thermal_get_trip_points(tz);
                acpi_thermal_check(tz);
                acpi_bus_generate_event(device, event, 0);
-               break;
-       case ACPI_THERMAL_NOTIFY_DEVICES:
+       } else if (event == ACPI_THERMAL_NOTIFY_DEVICES) {
                if (tz->flags.devices)
                        acpi_thermal_get_devices(tz);
                acpi_bus_generate_event(device, event, 0);
-               break;
-       default:
+       } else {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                        "Unsupported event [0x%x]\n", event));
-               break;
        }

$ size *.o
   text    data     bss     dec     hex filename
   5996     704      16    6716    1a3c thermal-multiple-if.o
   6005     704      16    6725    1a45 thermal-switch.o

Here's the asm diff between the two versions:

-       cmpl    $129, %esi
-       je      .L597
-       cmpl    $129, %esi
-       ja      .L602
-       addl    $-128, %esi
-       je      .L596
-       jmp     .L592
-.L602:
-       cmpl    $130, %esi
-       je      .L598
-       jmp     .L592
-.L596:
+       cmpl    $128, %esi
+       jne     .L595
 ...
-.L597:
+.L595:
+       cmpl    $129, %esi
+       jne     .L597
 ...
-.L598:
+.L597:
+       cmpl    $130, %esi
+       jne     .L592

The other diffs are just label numbers changing.  Given that gcc was
instructed to optimise for space (full command line:

gcc -Wp,-MD,drivers/acpi/.thermal.o.d -nostdinc -iwithprefix include \
	-D__KERNEL__ -Iinclude  -D__KERNEL__ -Iinclude  -Wall \
	-Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing \
	-fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 \
	-Iinclude/asm-i386/mach-default -fomit-frame-pointer  -Os   \
	-DKBUILD_BASENAME=thermal -DKBUILD_MODNAME=thermal -c \
	-o drivers/acpi/thermal.o drivers/acpi/thermal.c

I think it should choose the more space-efficient approach.

-- 
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk

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

* Re: [ACPI] Why does gcc suck at switch()?
  2003-10-03 14:56 Why does gcc suck at switch()? Matthew Wilcox
@ 2003-10-05 16:53 ` Pavel Machek
  2003-10-12  5:49 ` law
  1 sibling, 0 replies; 3+ messages in thread
From: Pavel Machek @ 2003-10-05 16:53 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: gcc

Hi!

> Why does gcc generate worse code for switch() statements than for
> multiple-if?
> 
> $ gcc --version
> gcc (GCC) 3.3.2 20030908 (Debian prerelease)
> 
> I would expect a compiler to produce the same code for these cases.
> Instead, switch is worse than the multiple-if:
> 
> -       switch (event) {
> -       case ACPI_THERMAL_NOTIFY_TEMPERATURE:
> +       if (event == ACPI_THERMAL_NOTIFY_TEMPERATURE) {
>                 acpi_thermal_check(tz);
> -               break;
> -       case ACPI_THERMAL_NOTIFY_THRESHOLDS:
> +       } else if (event == ACPI_THERMAL_NOTIFY_THRESHOLDS) {
>                 acpi_thermal_get_trip_points(tz);
>                 acpi_thermal_check(tz);
>                 acpi_bus_generate_event(device, event, 0);
> -               break;
> -       case ACPI_THERMAL_NOTIFY_DEVICES:
> +       } else if (event == ACPI_THERMAL_NOTIFY_DEVICES) {
>                 if (tz->flags.devices)
>                         acpi_thermal_get_devices(tz);
>                 acpi_bus_generate_event(device, event, 0);
> -               break;
> -       default:
> +       } else {
>                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>                         "Unsupported event [0x%x]\n", event));
> -               break;
>         }
> 
> $ size *.o
>    text    data     bss     dec     hex filename
>    5996     704      16    6716    1a3c thermal-multiple-if.o
>    6005     704      16    6725    1a45 thermal-switch.o
> 
> Here's the asm diff between the two versions:
> 
> -       cmpl    $129, %esi
> -       je      .L597
> -       cmpl    $129, %esi
> -       ja      .L602
> -       addl    $-128, %esi
> -       je      .L596
> -       jmp     .L592
> -.L602:
> -       cmpl    $130, %esi
> -       je      .L598
> -       jmp     .L592
> -.L596:
> +       cmpl    $128, %esi
> +       jne     .L595
>  ...
> -.L597:
> +.L595:
> +       cmpl    $129, %esi
> +       jne     .L597
>  ...
> -.L598:
> +.L597:
> +       cmpl    $130, %esi
> +       jne     .L592
> 
> The other diffs are just label numbers changing.  Given that gcc was
> instructed to optimise for space (full command line:
> 
> gcc -Wp,-MD,drivers/acpi/.thermal.o.d -nostdinc -iwithprefix include \
> 	-D__KERNEL__ -Iinclude  -D__KERNEL__ -Iinclude  -Wall \
> 	-Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing \
> 	-fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 \
> 	-Iinclude/asm-i386/mach-default -fomit-frame-pointer  -Os   \
> 	-DKBUILD_BASENAME=thermal -DKBUILD_MODNAME=thermal -c \
> 	-o drivers/acpi/thermal.o drivers/acpi/thermal.c
> 
> I think it should choose the more space-efficient approach.

Okay, but please don't change kernel code to workaround compiler
problem. This should probably be sent to gcc mailing list... Ahha, it
is. Not sure if it needs to be cc-ed to acpi at all.

								Pavel

-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

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

* Re: Why does gcc suck at switch()?
  2003-10-03 14:56 Why does gcc suck at switch()? Matthew Wilcox
  2003-10-05 16:53 ` [ACPI] " Pavel Machek
@ 2003-10-12  5:49 ` law
  1 sibling, 0 replies; 3+ messages in thread
From: law @ 2003-10-12  5:49 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: gcc, acpi-devel

In message <20031003145614.GP24824@parcelfarce.linux.theplanet.co.uk>, Matthew 
Wilcox writes:
 >
 >Why does gcc generate worse code for switch() statements than for
 >multiple-if?
Because it apparently is trying to do the tests in range form rather
than naively generating a simple test for each case in the switch
(there's no way to actually verify that since you didn't provide a
complete testcase).


The range-forms can be more effective in some cases or at least that's
the claim.  I'm not particularly familiar with that code so I've never
tried to re-tune it.  [ I have noticed it generating spectacularly bad
code in certain circumstances, yours may just be another of those cases. ]


jeff


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

end of thread, other threads:[~2003-10-12  3:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-03 14:56 Why does gcc suck at switch()? Matthew Wilcox
2003-10-05 16:53 ` [ACPI] " Pavel Machek
2003-10-12  5:49 ` law

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