<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><span class="" style="float: none; display: inline !important;">The way I would do this is I would first look at two values to figure</span><br class=""><span class="" style="float: none; display: inline !important;">out the offset and multiplier, and then iterate through the rest of</span><br class=""><span class="" style="float: none; display: inline !important;">the values and see if they fit.</span><br class=""></blockquote><br class=""></div><div class="">Basically a good idea, but it would require to duplicate the checks, so IMO it would make things more complicated.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><span class="" style="float: none; display: inline !important;">even in the case of </span><span class="" style="float: none; display: inline !important;">overflows </span></blockquote><br class=""></div><div class="">Overflows are not a problem. I added a test case for it.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><span class="" style="float: none; display: inline !important;"> It will also make handling undefs easier, i.e. we </span><span class="" style="float: none; display: inline !important;">can just ignore them.</span></blockquote><div class=""><br class=""></div><div class="">I don't agree. This is only true if you assume that the first two values are not undefs.</div><div class=""><br class=""></div><div class="">I decided to not handle undefs because according to my findings, they are very seldom in switch tables (even in non-linear ones).</div><div class="">In the whole test-suite there is only a single case. IMO it's not worth the additional complexity it would add to the code.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Erik</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On 13 Nov 2014, at 22:29, Hans Wennborg <<a href="mailto:hans@chromium.org" class="">hans@chromium.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">On Thu, Nov 13, 2014 at 12:20 PM, Erik Eckstein <</span><a href="mailto:eeckstein@apple.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">eeckstein@apple.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">> wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Thanks for reviewing!<br class=""><br class=""><blockquote type="cite" class="">Do you have any numbers on how often this fires in a Clang bootstrap<br class="">or other benchmark?<br class=""></blockquote><br class="">29 in the test-suite (including External).<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Nice.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class="">This enum is sorted in a "cheapest first" order, which matches the<br class="">order that the SwitchLookupTable tries things. LinearMapKind should go<br class="">before ArrayKind.<br class=""></blockquote><br class="">In this case I would put it even before BitMapKind.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Sounds good.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class="">I think undef is probably the only possible case here, right?<br class=""></blockquote><br class="">I'm not sure.<br class=""><br class=""><blockquote type="cite" class="">For undef, it shouldn't matter what result we return (someone please<br class="">correct me if I'm wrong here), so it would be nice if we could ignore<br class="">undef values when trying to find the linear relationship. If it makes<br class="">things more complicated we could do it in a follow-up patch.<br class=""></blockquote><br class="">Let's do it in a follow-up patch. I'll add a TODO.<br class=""><br class=""><blockquote type="cite" class="">Should we handle the cases where the multiplier is 1 or offset is 0<br class="">and generate simpler code for that?<br class=""></blockquote><br class="">I didn't do it to keep the code simpler. But if there is a good reason to simplify it here and not in follow-up optimizations, it's not a problem.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Yeah, I think we should do it here.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">A few more thoughts about the patch:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">+ // Check if we can derive the value with a linear transformation from the<br class="">+ // table index.<br class="">+ IntegerType *ValueIntType = dyn_cast<IntegerType>(ValueType);<br class="">+ if (ValueIntType) {<br class="">+ bool LinearMappingPossible = true;<br class="">+ APInt PrevVal;<br class="">+ APInt DistToPrev;<br class="">+ // Check if there is the same distance between two consecutive values.<br class="">+ for (uint64_t I = 0; I < TableSize; ++I) {<br class="">+ ConstantInt *ResConst = dyn_cast<ConstantInt>(TableContents[I]);<br class="">+ if (!ResConst) {<br class="">+ // E.g. if it is an undef.<br class="">+ LinearMappingPossible = false;<br class="">+ break;<br class="">+ }<br class="">+ APInt Val = ResConst->getValue();<br class="">+ if (I > 0) {<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Not a big deal, but checking "I != 0" seems like a more clear way to</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">check that it's not the first iteration.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">+ APInt Dist = Val - PrevVal;<br class="">+ if (I == 1) {<br class="">+ DistToPrev = Dist;<br class="">+ } else if (Dist != DistToPrev) {<br class="">+ LinearMappingPossible = false;<br class="">+ break;<br class="">+ }<br class="">+ }<br class="">+ PrevVal = Val;<br class="">+ }<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">The way I would do this is I would first look at two values to figure</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">out the offset and multiplier, and then iterate through the rest of</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">the values and see if they fit.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I think that might be a little easier to read, and it would also make</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">it more obvious that all the results are correct even in the case of</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">overflows etc., because we've checked the same computation that will</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">happen at run-time. It will also make handling undefs easier, i.e. we</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">can just ignore them.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Thanks,</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Hans</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class="">On 13 Nov 2014, at 19:40, Hans Wennborg <<a href="mailto:hans@chromium.org" class="">hans@chromium.org</a>> wrote:<br class=""><br class="">On Thu, Nov 13, 2014 at 7:26 AM, Erik Eckstein <<a href="mailto:eeckstein@apple.com" class="">eeckstein@apple.com</a>> wrote:<br class=""><blockquote type="cite" class="">Hi Hans,<br class=""><br class="">this patch adds a simple optimization for switch table lookup: It computes the output value directly with an (optional) mul and add if there is a linear mapping between index and output. Example:<br class=""></blockquote><br class="">Thanks! This has been on my mental todo list for switch transformation<br class="">stuff for a while, so I'm very happy to review it.<br class=""><br class="">Do you have any numbers on how often this fires in a Clang bootstrap<br class="">or other benchmark?<br class=""><br class=""><blockquote type="cite" class="">Index: lib/Transforms/Utils/SimplifyCFG.cpp<br class="">===================================================================<br class="">--- lib/Transforms/Utils/SimplifyCFG.cpp (revision 221882)<br class="">+++ lib/Transforms/Utils/SimplifyCFG.cpp (working copy)<br class="">@@ -70,6 +70,7 @@<br class=""> cl::desc("Hoist conditional stores if an unconditional store precedes"));<br class=""><br class="">STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");<br class="">+STATISTIC(NumLinearMaps, "Number of switch instructions turned into linear mapping");<br class="">STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables");<br class="">STATISTIC(NumLookupTablesHoles, "Number of switch instructions turned into lookup tables (holes checked)");<br class="">STATISTIC(NumSinkCommons, "Number of common instructions sunk down to the end block");<br class="">@@ -3663,7 +3664,12 @@<br class=""><br class=""> // The table is stored as an array of values. Values are retrieved by load<br class=""> // instructions from the table.<br class="">- ArrayKind<br class="">+ ArrayKind,<br class="">+<br class="">+ // For tables where there is a linear relationship between table index<br class="">+ // and values. We calculate the result with a simple multiplication<br class="">+ // and addition instead of a table lookup.<br class="">+ LinearMapKind<br class=""></blockquote><br class="">This enum is sorted in a "cheapest first" order, which matches the<br class="">order that the SwitchLookupTable tries things. LinearMapKind should go<br class="">before ArrayKind.<br class=""><br class=""><br class=""><blockquote type="cite" class=""> } Kind;<br class=""><br class=""> // For SingleValueKind, this is the single value.<br class="">@@ -3673,6 +3679,10 @@<br class=""> ConstantInt *BitMap;<br class=""> IntegerType *BitMapElementTy;<br class=""><br class="">+ // For LinearMapKind, these are the constants used to derive the value.<br class="">+ Constant *ValueOffset;<br class="">+ Constant *Multiplier;<br class=""></blockquote><br class="">Maybe LinearOffset and LinearMultiplier, to tie the names even tighter<br class="">to the LinearMapKind?<br class=""><br class=""><blockquote type="cite" class="">+<br class=""> // For ArrayKind, this is the array.<br class=""> GlobalVariable *Array;<br class=""> };<br class="">@@ -3685,7 +3695,7 @@<br class=""> Constant *DefaultValue,<br class=""> const DataLayout *DL)<br class=""> : SingleValue(nullptr), BitMap(nullptr), BitMapElementTy(nullptr),<br class="">- Array(nullptr) {<br class="">+ ValueOffset(nullptr), Multiplier(nullptr), Array(nullptr) {<br class=""> assert(Values.size() && "Can't build lookup table without values!");<br class=""> assert(TableSize >= Values.size() && "Can't fit values in table!");<br class=""><br class="">@@ -3730,6 +3740,42 @@<br class=""> return;<br class=""> }<br class=""><br class="">+ // Check if we can derive the value with a linear transformation from the<br class="">+ // table index.<br class="">+ IntegerType *ValueIntType = dyn_cast<IntegerType>(ValueType);<br class="">+ if (ValueIntType) {<br class=""></blockquote><br class="">In LLVM style it's more common to do:<br class=""><br class="">if (IntegerType *ValueIntType = dyn_cast<...<br class=""><br class="">This saves a line and reduces the scope of ValueIntType to only the if<br class="">statement, which is where it's used.<br class=""><br class=""><blockquote type="cite" class="">+ bool LinearMappingPossible = true;<br class="">+ APInt PrevVal;<br class="">+ APInt DistToPrev;<br class="">+ // Check if there is the same distance between two consecutive values.<br class="">+ for (uint64_t I = 0; I < TableSize; ++I) {<br class="">+ ConstantInt *ResConst = dyn_cast<ConstantInt>(TableContents[I]);<br class=""></blockquote><br class="">ResConst feels a little backwards to me. Why not ConstRes, as in<br class="">"constant result"?<br class=""><br class=""><blockquote type="cite" class="">+ if (!ResConst) {<br class="">+ // E.g. if it is an undef.<br class=""></blockquote><br class="">I think undef is probably the only possible case here, right?<br class=""><br class="">For undef, it shouldn't matter what result we return (someone please<br class="">correct me if I'm wrong here), so it would be nice if we could ignore<br class="">undef values when trying to find the linear relationship. If it makes<br class="">things more complicated we could do it in a follow-up patch.<br class=""><br class=""><blockquote type="cite" class="">+ LinearMappingPossible = false;<br class="">+ break;<br class="">+ }<br class="">+ APInt Val = ResConst->getValue();<br class="">+ if (I > 0) {<br class="">+ APInt Dist = Val - PrevVal;<br class="">+ if (I == 1) {<br class="">+ DistToPrev = Dist;<br class="">+ } else if (Dist != DistToPrev) {<br class="">+ LinearMappingPossible = false;<br class="">+ break;<br class="">+ }<br class="">+ }<br class="">+ PrevVal = Val;<br class="">+ }<br class="">+ if (LinearMappingPossible) {<br class="">+ ValueOffset = TableContents[0];<br class="">+ Multiplier = ConstantInt::get(ValueIntType, DistToPrev);<br class="">+ Kind = LinearMapKind;<br class="">+ ++NumLinearMaps;<br class="">+ return;<br class="">+ }<br class="">+ }<br class="">+<br class=""> // If the type is integer and the table fits in a register, build a bitmap.<br class=""> if (WouldFitInRegister(DL, TableSize, ValueType)) {<br class=""> IntegerType *IT = cast<IntegerType>(ValueType);<br class="">@@ -3802,6 +3848,14 @@<br class=""> "switch.gep");<br class=""> return Builder.CreateLoad(GEP, "switch.load");<br class=""> }<br class="">+ case LinearMapKind: {<br class="">+ // Derive the result value from the input value.<br class="">+ Value *Result = Builder.CreateIntCast(Index, Multiplier->getType(), false,<br class="">+ "switch.idx.cast");<br class="">+ Result = Builder.CreateMul(Result, Multiplier, "switch.idx.mult");<br class="">+ Result = Builder.CreateAdd(Result, ValueOffset, "switch.offset");<br class=""></blockquote><br class="">Should we handle the cases where the multiplier is 1 or offset is 0<br class="">and generate simpler code for that? It seems like it would be easy to<br class="">handle here, so we might as well do it and save some churn.</blockquote></blockquote></div></blockquote></div><br class=""></div></body></html>