In case you still want an answer to the original question - I would expect good programming practice to be that you explicitly list all your relevant cases in a switch statement, so hitting default should never happen or should be a rare exception. But I don’t know if real programs are like that and I’m sure there’s at least some code where this is not true.
Regards, Maciej > On Jan 31, 2015, at 12:53 PM, Filip Pizlo <[email protected]> wrote: > > Ha - never mind, I was wrong. My calculation of cost for getting to default > is wrong. Please ignore. > > -Filip > > >> On Jan 31, 2015, at 12:40 PM, Filip Pizlo <[email protected] >> <mailto:[email protected]>> wrote: >> >> I’m having fun calculating the average performance of different switch >> implementations, to be used in the DFG JIT and in our inline caching logic. >> I’ve got two possible implementations that appear to be very nearly optimal >> assuming the capabilities of the hardware we care about and other >> constraints of our JITs. Both implementations involve a tree of branches, >> and they both come into play in exactly those cases where a tree of branches >> is already known to be less expensive than a lookup table. >> >> Here’s the basic switch JIT algorithm: >> >> jitSwitchRecurse(cases) { >> if (cases.size < N) { >> for (C in cases) { >> emit code that checks, and executes, C >> } >> fall through to default >> } else { >> // Note that this only divides-and-conquers and does not explicitly >> check and execute the median case; I’ve calculated that this is the superior >> choice. You can follow along with this here: >> https://bugs.webkit.org/show_bug.cgi?id=141046 >> <https://bugs.webkit.org/show_bug.cgi?id=141046> >> let M = right-median case in cases // for even sizes of cases, pick >> the greater of the two medians; for odd cases, pick either the median or the >> value to the right of the median at random. the point is to split the list >> into two equal-sized lists >> lessThanJump = emit lessThan comparison against M >> jitSwitchRecurse(those cases that are >= M) >> lessThanJump.link() >> jitSwitchRecurse(those cases that are < M) >> } >> >> The two implementations of this algorithm that I’m picking between either >> have N = 2 or N = 3 - i.e. we either stop divide-and-conquering once we have >> two remaining cases, or when we have 3 remaining cases. Those two versions >> are the most optimal for a variety of reasons, but neither is obviously >> better than the other: N = 3 is more optimal for the case that the switch >> bottoms out in one of the cases. N = 2 is more optimal if the switch >> bottoms out in the default (“fall through”) case. N = 2 is significantly >> more optimal for default: it usually results in two fewer comparisons before >> getting to default. N = 3 is slightly more optimal for the non-default >> (i.e. hitting some explicit case) case: it usually results in one fewer >> comparisons before getting to some case. >> >> We could have a switch emitter that selects the strategy based on profiling >> (did we hit the default case, or not?), but that isn’t always available and >> it might be overkill. We could tune this for benchmarks, and I might do >> some of that. But I’m curious what other people’s intuitions and >> experiences are: do your switch statements usually hit some case, or take >> default? If you could control which one was faster, which one of those >> would you be most likely to make faster in the kind of code that you write? >> >> -Filip >> > > _______________________________________________ > webkit-dev mailing list > [email protected] > https://lists.webkit.org/mailman/listinfo/webkit-dev
_______________________________________________ webkit-dev mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-dev

