When a switch has less than 4 cases gcc tests for the middle-case-value and makes an additional less-greater check instead of immediately evaluating the other case-values. If there are more case branches in the switch, this kind of checking would speed up the search of the corresponding case branch (but those switches are solved with jump-tables anyway). But for only a few case branches, the direct equality checks would be better. Release: gcc version 3.3 20030210 (prerelease) Environment: BUILD & HOST: Linux 2.4.20 i686 unknown TARGET: arm-unknown-elf How-To-Repeat: arm-elf-gcc -S -g0 -Os -o 01_3d.s ./01_3d.i //01_3d.i # 1 "01_3d.c" # 1 "<built-in>" # 1 "<command line>" # 1 "01_3d.c" unsigned int g; int main () { int r; switch (r) { case 1: g=11; break; case 2: g=12; break; case 3: g=13; break; default: g=20; break; } return 0; }
You are right, gcc should not be using range tests for this case.
Here is a better version of this (f should produce the same code as g) int f (int r) { switch (r) { case 1: return 11; case 2: return 12; case 3: return 13; default: return 20; } } int g(int r) { if(r==1) return 11; else if (r==2) return 12; else if (r==3) return 13; else return 30; }
This is caused by the TREE to RTL expanders so moving to middle-end.
I've got a patch in testing.
Patch: http://gcc.gnu.org/ml/gcc-patches/2004-03/msg02065.html
Subject: Bug 9707 CVSROOT: /cvs/gcc Module name: gcc Changes by: kazu@gcc.gnu.org 2004-03-25 16:16:43 Modified files: gcc : ChangeLog stmt.c Log message: PR optimization/9707. * stmt.c (emit_case_nodes): Emit equality comparisons instead of recursing if both children are single-valued cases with no children. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.3288&r2=2.3289 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/stmt.c.diff?cvsroot=gcc&r1=1.350&r2=1.351
I just checked in the patch.