On Tue, Aug 10, 2010 at 6:48 PM, Ian Bolton <ian.bol...@arm.com> wrote: > 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?)
The fix is to always use a standard unsigned integer type for the new index value. lang_hooks.types.type_for_mode (TYPE_MODE (old-idx-type), 1) would give you one. Richard.