https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94779
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amacleod at redhat dot com --- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> --- 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 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 2) similarly, cases that refer to blocks which have EDGE_COUNT (bb->succs) == 0 && gimple_seq_unreachable_p (bb_seq (bb)) should be treated again like cases one shouldn't need to care about 3) to handle the #c0 testcase in C (C++ already adds __builtin_unreachable), handle also the case where case refers to block which has EDGE_COUNT (bb->succs) and ends in GIMPLE_RETURN without expression in a function that returns integral or pointer value (for simplicity) and has no statements other than debug stmts or clobber stmts before it. Note, this case can't be treated completely like a UB case, there is no UB in C unless the caller checks the return value, but it could be handled conditionally, as long as the code we emit for that doesn't invoke UB in the function, we really don't care about the value we return to the caller. So e.g. if we are considering a linear function and other case labels return that linear value and some return unspecified value, just use the linear function to cover those too. 4) to be able to optimize the int f1(unsigned x) { if (x >= 3) __builtin_unreachable(); switch (x) { case 0: return 1; case 1: return 2; case 2: return 3; } } testcase, we should for consideration virtually undo the evrp optimization which removed the case 0: and replaced it with default: - here the handled cases (that should include the really handled ones and ones that and the UB ones (if the case is outside of range or __builtin_unreachable) cover everything but one case, assume the default label is that for that single case rather than handling anything else; similarly, if the whole range is covered, ignore the default label