<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 19, 2015, at 4:46 AM, Frej Drejhammar <<a href="mailto:frej@sics.se" class="">frej@sics.se</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">Hi All,<br class=""><br class="">I am observing something i suspect is a misbehaviour of the register<br class="">allocator which impacts the performance of patchpoints. This occurs in<br class="">the context of an abstract machine which in some places uses inline<br class="">caches. The problematic code looks like this:<br class=""><br class="">entry: ; Initialize the abstract machine<br class="">  %db = call create_big_seldom_used_database()<br class="">  ; do a lot of things which increases register pressure and spills %db<br class="">  br label %main_execution_loop;<br class=""><br class="">main_execution_loop:<br class="">  ; We do instruction dispatch here<br class="">  ...<br class=""><br class="">opcode_a:<br class="">  %name0 = ...<br class="">  ; Use the database to look up %name0 and then overwrite the patchpoint<br class="">  ; with a direct call<br class="">  tail call anyregcc void (i64, i32, i8*, i32, ...)*<br class="">    @llvm.experimental.patchpoint.void(i64 4711, i32 16, @lookup_and_patch, i32 0,<br class="">                                       some_type %name0, some_type %db)<br class="">  ...<br class=""><br class="">  %name1 = ...<br class="">  ; Use the database to look up %name1 and then overwrite the patchpoint<br class="">  ; with a direct call<br class="">  tail call anyregcc void (i64, i32, i8*, i32, ...)*<br class="">    @llvm.experimental.patchpoint.void(i64 4711, i32 16, @lookup_and_patch, i32 0,<br class="">                                       some_type %name1, some_type %db)<br class="">  ...<br class=""><br class="">  br label %main_execution_loop;<br class=""><br class="">If I run this through llc (for x86_64) I will frequently see, especially<br class="">if I have two cache lookups in the same basic block or low register<br class="">pressure, that %db is loaded from the stack and into a register. The<br class="">generated code looks like this:<br class=""><br class="">reload %db into reg0<br class="">; %name0 is in reg1<br class="">call lookup_and_patch(reg1, reg0)<br class="">; shadow<br class="">; %name1 is in reg2<br class="">call lookup_and_patch(reg1, reg0)<br class="">; shadow<br class=""><br class="">This is a performance problem as, although the calls to<br class="">lookup_and_patch() are overwritten, we will always pay for the, now<br class="">useless, load of %db into reg0. If I wanted the arguments to<br class="">lookup_and_patch() in registers I would not have used the anyregcc<br class="">calling convention. In this toy example lookup_and_patch() only refers a<br class="">single variable, but in my real application it uses multiple values<br class="">(most of them spilled) and the slowdown is quite noticeable (overheads<br class="">of up to 600% for some opcodes).<br class=""><br class="">To me this looks like the register allocator is too eager to load values<br class="">which are only used by anyregcc patchpoints into registers, or is this<br class="">the intended behavior of anyregcc patchpoints?<br class=""></div></blockquote><div><br class=""></div><div>The calling convention affects the patchpoint call arguments only. </div><div><br class=""></div><div>Patchpoint operands that can be in any location should be in the set of “live values”, not call arguments. You’ve done this correctly.</div><div><br class=""></div><div>For other cases where those live values should be forced into registers, they should be promoted to call arguments and anyregcc should be used.</div><div><br class=""></div><div>But since you’re not using the calling convention, you don’t need to specify anyregcc. The only affect it will have is to clobber %rax, which you probably don’t want. And the purpose of that convention is really the opposite of what you want anyway.</div><div><br class=""></div><div>You’re right, this is a register allocator performance bug. It is too aggressive at optimizing local live ranges, and ignores the fact that these uses can be spilled for free.</div><div><br class=""></div><blockquote type="cite" class=""><div class="">I would be grateful for suggestions of how I could modify the register<br class="">allocator (RAGreedy) to avoid reloading values when they are only used<br class="">by instructions which are anyregcc patchpoints. During the last two<br class="">weeks I have made a couple unsuccessful attempts at that and could<br class="">really use some pointers from someone who understands it.<br class=""></div></blockquote><div><br class=""></div><div>See <a href="http://llvm.org/PR22832" class="">http://llvm.org/PR22832</a> for more information.</div><div><br class=""></div><div>-Andy</div><div><br class=""></div><blockquote type="cite" class=""></blockquote><blockquote type="cite" class=""><div class=""><br class="">Attached is a the smallest example I have managed to find which shows<br class="">the problem.<br class=""><br class="">Regards,<br class=""><br class="">--Frej<br class=""><br class=""><span id="cid:9E04EAD4-306F-42BC-89F5-8042D320BE49@apple.com"><bug.ll></span>_______________________________________________<br class="">LLVM Developers mailing list<br class=""><a href="mailto:LLVMdev@cs.uiuc.edu" class="">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" class="">http://llvm.cs.uiuc.edu</a><br class=""><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br class=""></div></blockquote></div><br class=""></body></html>