From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17200 invoked by alias); 3 Oct 2003 14:56:16 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 17192 invoked from network); 3 Oct 2003 14:56:15 -0000 Received: from unknown (HELO www.linux.org.uk) (195.92.249.252) by sources.redhat.com with SMTP; 3 Oct 2003 14:56:15 -0000 Received: from willy by www.linux.org.uk with local (Exim 4.22) id 1A5RLr-0007ob-0n; Fri, 03 Oct 2003 15:56:15 +0100 Date: Fri, 03 Oct 2003 14:56:00 -0000 From: Matthew Wilcox To: gcc@gcc.gnu.org Cc: acpi-devel@lists.sourceforge.net Subject: Why does gcc suck at switch()? Message-ID: <20031003145614.GP24824@parcelfarce.linux.theplanet.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-SW-Source: 2003-10/txt/msg00095.txt.bz2 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