https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94779
--- Comment #13 from Andrew Macleod <amacleod at redhat dot com> --- (In reply to Jakub Jelinek from comment #12) > So, for start I think we should do: > 1) query->range_of_expr (m_index_range, m_index_expr, swtch) > where query is address of gimple_ranger passed down from the caller > to figure out range of the index expression; case labels without For starters, you can probably simply create a gimple_ranger on the spot to do the query. At least until everything works the way you want. Its low overhead... we had reasonable success with that early on with some pass conversions, and ultimately we hope by next release to make this more generally accessible without passing a ranger around anyway. > CASE_HIGH for > which m_index_range.contains_p (CASE_LOW (case)) is false can be ignored > for the optimization (well, handled the way it is better for the > optimization) > For CASE_HIGH labels, similarly query if the range overlaps the index > range. > Note, I don't remember exactly in which way the types of the index > expression > and of the case labels can differ, I believe all case labels have to have > the > same type, so probably for the computation of the range if it has > different > type from the case label ones, it needs to call something that would > emulate > the effect of conversion to that type (or vice versa?) > CCing Andrew for the range stuff There are a couple of PRs related to this, I forget the current resolution, but I originally opened https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87798 for it. Ranger currently punts if the precision of the labels is different than the precision of the switch expr in gimple-range-edge.cc : outgoing_range::get_edge_range In order to convert between types, range-op.h exports the routine extern void range_cast (irange &, tree type); which does an in place conversion to type... supports full cast semantics. there are uses of it sprinkled around. Furthermore, IIRC there can be multiple cases sharing the same edge.. It seems it might be useful to make more use of gimple-range-edge.h here.. (we may need some tweaks in order to get things working with a ranger since this is a private member to ranger) so I would again start by simply creating my own local outgoing_range instance and then you can ask int_range_max range; outgoing_range_instance.edge_range_p (range, switch_edge) where this will give you the cumulative union of all the case-labels on that switch edge. (its unrelated to the index variable... Ranger intersects this range with the index variable range when you ask for the range of the index variable on an edge) If this turns out to be useful, we can probably figure a way to get it exported from ranger to avoid creating a local instance The last useful bit of info that may not be obvious... if you ask ranger for the range of the index variable on the default edge, and if all the cases cover the known range of the index variable, as in the first example, then ranger will return a range of UNDEFINED ... meaning it can never take that edge. ie the function in the first example shows me: =========== BB 4 ============ x_2(D) unsigned int [0, 2] <bb 4> : switch (x_2(D)) <default: <L5> [INV], case 0: <L7> [INV], case 1: <L3> [INV], case 2: <L4> [INV]> 4->7 x_2(D) : UNDEFINED 4->8 x_2(D) : unsigned int [0, 0] 4->5 x_2(D) : unsigned int [1, 1] 4->6 x_2(D) : unsigned int [2, 2] where edge 4->7 is the default case...