First Last Prev Next    No search results available      Search page      Enter new bug
Bug#: 11823
Product:  
Component:  
Status: RESOLVED
Resolution: FIXED
Assigned To: Not yet assigned to anyone <unassigned@gcc.gnu.org>
Host:
Reported against  
Priority:  
Severity:  
Target Milestone:  
 
 
Target:
Reporter: Gábor Lóki <loki@gcc.gnu.org>
Add CC:
CC:
Remove selected CCs
Build:
URL:
Summary:
Keywords:
Known to work:
Known to fail:

Attachment Description Type Created Size Actions
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 11823 depends on: Show dependency tree
Show dependency graph
Bug 11823 blocks:

Additional Comments:






View Bug Activity   |   Format For Printing   |   Clone This Bug


Description:   Last confirmed: 2003-08-06 20:03 Opened: 2003-08-06 08:39
In some cases GCC generates very large jump tables, e.g. the table can contain
too few different case values wrt. the table size. In these cases when
optimizing for size it would be preferable to use some other mechanism for the
jumping problem. For example, in some cases it would be more effecient to
create simple compare and branch pairs for checking the case values.

--- c example ---
// arm-elf-gcc -S -g0 -Os -o large-jump.s large-jump.c
int i;
int func(int a)
{
  switch(a)
  {
    case 0:   i = 20; break;
    case 1:   i = 50; break;
    case 2:   i = 29; break;
    case 10:  i = 20; break;
    case 11:  i = 50; break;
    case 12:  i = 29; break;
    case 20:  i = 20; break;
    case 21:  i = 50; break;
    case 22:  i = 29; break;
    case 52:  i = 79; break;
    case 110: i = 27; break;
    default:  i = 77; break;
  }
  return i;
}

--- arm code ---
func:
	ldr	r2, .L17
	cmp	r0, #110
	ldrls	pc, [pc, r0, asl #2]
	b	.L14
	.p2align 2
.L15:
	.word	.L9
	.word	.L10
	.word	.L11
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L9
	.word	.L10
	.word	.L11
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L9
	.word	.L10
	.word	.L11
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L12
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L14
	.word	.L13
.L9:
	mov	r3, #20
	b	.L16
.L10:
	mov	r3, #50
	b	.L16
.L11:
	mov	r3, #29
	b	.L16
.L12:
	mov	r3, #79
	b	.L16
.L13:
	mov	r3, #27
	b	.L16
.L14:
	mov	r3, #77
.L16:
	str	r3, [r2, #0]
	ldr	r3, .L17
	ldr	r0, [r3, #0]
	mov	pc, lr

------- Comment #1 From Andrew Pinski 2003-08-06 20:03 -------
I agruee with this and maybe this one can be done with GCC's current
infrostructor but 
who knows.

------- Comment #2 From Steven Bosscher 2003-08-07 13:01 -------
You should look at stmt.c:expand_end_case_type(), under the comment:

      /* If range of values is much bigger than number of values,
         make a sequence of conditional branches instead of a dispatch.
         If the switch-index is a constant, do it this way
         because we can optimize it.  */

The heuristic following this comment now does:

               || compare_tree_int (range, 10 * count) > 0

where "count" is the number of case labels, and range is the range of the case
labels.  In your example, count==11, and range==110, so you just hit the case
where it still gets expanded with a jump table.  (I suppose you knew this,
judging from your example ;-)

So why not replace this heuristic with something like:

               || compare_tree_int (range, (optimize_size ? 3 : 10) * count) > 0

and see if it helps...

------- Comment #3 From Gábor Lóki 2003-09-05 06:47 -------
The problem has been fixed.
See the following mail and cvs diff.
http://gcc.gnu.org/ml/gcc-patches/2003-08/msg02054.html
http://sources.redhat.com/cgi-bin/cvsweb.cgi/gcc/gcc/stmt.c.diff?r1=1.326&r2=1.327&cvsroot=gcc

First Last Prev Next    No search results available      Search page      Enter new bug