I am in the process of fixing PR44328 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44328)
The problem is that gen_inbound_check in tree-switch-conversion.c subtracts
info.range_min from info.index_expr, which can cause the MIN and MAX values
for info.index_expr to become invalid.
For example:
typedef enum {
FIRST = 0,
SECOND,
THIRD,
FOURTH
} ExampleEnum;
int dummy (const ExampleEnum e)
{
int mode = 0;
switch (e)
{
case SECOND: mode = 20; break;
case THIRD: mode = 30; break;
case FOURTH: mode = 40; break;
}
return mode;
}
tree-switch-conversion would like to create a lookup table for this, so
that SECOND maps to entry 0, THIRD maps to entry 1 and FOURTH maps to
entry 2. It achieves this by subtracting SECOND from index_expr. The
problem is that after the subtraction, the type of the result can have a
value outside the range 0-3.
Later, when tree-vrp.c sees the inbound check as being <= 2 with a possible
range for the type as 0-3, it converts the <=2 into a != 3, which is
totally wrong. If e==FIRST, then we can end up looking for entry 255 in
the lookup table!
I think the solution is to update the type of the result of the subtraction
to show that it is no longer in the range 0-3, but I have had trouble
implementing this. The attached patch (based off 4.5 branch) shows my
current approach, but I ran into LTO issues:
lto1: internal compiler error: in lto_get_pickled_tree, at lto-streamer-in.c
I am guessing this is because the debug info for the type does not match
the new range I have set for it.
Is there a *right* way to update the range such that LTO doesn't get
unhappy? (Maybe a cast with fold_convert_loc would be right?)
pr44328.gcc4.5.fix.patch
Description: Binary data
