This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Why does gcc suck at switch()?


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]