<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Dec 7, 2010, at 12:20 PM, Duncan Sands wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>In the case of Bill's proposal this property holds because of special rules<br>about what you are allowed to do with landing pads: you are not allowed to move<br>a dispatch instruction out of a landing pad etc.</div></blockquote><div><br></div><div>I hope I didn't misstate this, but you can move it out of a landing pad, however the landing pad must dominate the dispatch. For instance, code like this:</div><div><br></div><div>lpad: landingpad</div><div> call void @a_cleanup_function()</div><div> dispatch …</div><div><br></div><div>may inline the @a_cleanup_function() call, which may result in the dispatch no longer being in the landing pad.</div><br><blockquote type="cite"><div>These rules could actually<br>be applied to eh.selector without any IR changes providing much the same effect<br>without a new instruction. However the reason for not doing this is that it<br>then makes some optimizations impossible, for example when you inline a call<br>to _Unwind_Resume through an invoke you would like to turn it into a branch to<br>the landing pad, but this would result in eh.selector calls that fail the rules.<br>It's not clear to me if the dispatch instruction has this problem too, I need<br>to ask Bill about it.<br><br>In fact Bill's proposal mostly seems to be about replacing the current explicit<br>sequence of comparisons that llvm-gcc uses to find which handler to run (I guess<br>everyone who has looked at LLVM IR with exception handling in it has seen all<br>the calls to eh.typeid.for, the comparisons and the branching that I'm talking<br>about here) with a more compact representation that is easier to analyse. As<br>such, from my point of view it doesn't really have much to do with the inlining<br>issue, which is not to say it doesn't have merit on other grounds.<br></div></blockquote><br><div>The compactness of information and ease of analysis are what I think of as the key advantages of my proposal. Also, it doesn't rely upon intrinsics, but builds the EH into the IR explicitly.</div><br><blockquote type="cite"><div>An interesting point is that Bill's dispatch instruction is quite analogous to<br>GCC's gimple_eh_dispatch statement. This statement represents the transfer of<br>control to the appropriate catch handler for an exception region, and is at a<br>fairly high level of abstraction. It takes an exception handling try region as<br>an argument (it can also have an "allowed exceptions" region as an argument,<br>but there's no added value in discussing that). Since the list of associated<br>catches is stored in the region info, there is no need for it to explicitly<br>list tries and where to branch to, while Bill is obliged to put the info that<br>GCC stores in the region directly into his dispatch instruction.<br><br>Once GCC has finished running the inliner it runs the lower_eh_dispatch pass,<br>which removes all gimple_eh_dispatch statements by turning them into explicit<br>control flow: a sequence of comparisons and branches (exactly like the code<br>llvm-gcc/clang produce right now, comparing the selector value with the result<br>of eh.typeid.for calls). Since my proposal doesn't change this aspect of LLVM,<br>you can consider that before this pass GCC's representation is like Bill's and<br>after it is like in my proposal.<br></div></blockquote><div><br></div><div>Interesting. . . How do they handle LTO with exception handling if the gimple_eh_dispatch statements are all ready lowered?</div><br><blockquote type="cite"><div><blockquote type="cite">So, in view of their equivalence, I think Bill's proposal is better<br></blockquote><blockquote type="cite">for two reasons:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> 1. It eases the future elimination of invoke, or at least, the<br></blockquote><blockquote type="cite">treatment of current instruction-level exception (as in Java) in a<br></blockquote><blockquote type="cite">cleaner way.<br></blockquote><br>I don't see what is cleaner about it, except that it is overall at a higher<br>level of abstraction (see above).<br></div></blockquote><div><br></div><div>I also think that both of our proposals are flexible enough to handle the future elimination of invokes and support of basic block throws (as you explained in a future email).</div><br><blockquote type="cite"><div><blockquote type="cite"> 2. It reinforces the idea of having one personality function for<br></blockquote><blockquote type="cite">each EH table (ie. per function), especially when inlining code from<br></blockquote><blockquote type="cite">different paradigms (if that's possible).<br></blockquote><br>According to Bill's proposal each dispatch instruction can specify a different<br>personality function, so it's just the same as my proposal in this respect.<br></div></blockquote><div><br></div><div>Yeah. Multiple personality functions per function is something Chris has a mild interest in. The devil is in the details, of course.</div><br><blockquote type="cite"><div><blockquote type="cite">However, your proposal is better in two other accounts:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> 1. If we do want to support EH tables with multiple personalities in<br></blockquote><blockquote type="cite">the future.<br></blockquote><br>As mentioned above, Bill's proposal also supports multiple personalities per<br>function.<br><br><blockquote type="cite"> 2. It's less invasive and closer to the problem it meant to fix in<br></blockquote><blockquote type="cite">the first place. So it'll be faster and easier to do that way.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">It's more of a design decision, IMO.<br></blockquote><br>Exactly, and this brings up the question of what criteria should be used to<br>decide which proposal is best. Presumably, all else being equal, whichever<br>one makes it easiest to optimize the IR. I didn't yet think about the<br>advantages and disadvantages of each proposal in this respect.<br></div></blockquote></div><div><br></div><div>I have my own opinions, of course. But I think there are two criteria which should be met:</div><div><br></div><div>1. Firstly, it must work and work well. I.e., it will solve all of our current EH problems – it's slow, it doesn't follow any ABI, it's fragile, it requires expensive transformations before code-gen – and</div><div><br></div><div>2. It must be flexible enough for future changes.</div><div><br></div><div>Here are some of the things I would like to have:</div><div><br></div><div>1. Limited use of intrinsics.</div><div> Reasoning: Intrinsics are indistinguishable from calls. And as such are harder to work with than IR instructions.</div><div><br></div><div>2. EH metadata shouldn't be encoded in the CFG if at all possible.</div><div> Reasoning: The IR is meant for executable instructions. As such, transformations don't know about or care about any EH metadata there.</div><div><br></div><div>3. The front-ends should be able to emit the EH data easily.</div><div> Reasoning: The front-end guys are just down the hall from me and I sit with my back to the door. :-)</div><div><br></div><div>-bw</div><div><br></div></body></html>