<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 8, 2017, at 3:14 PM, Chris Lattner &lt;<a href="mailto:clattner@nondot.org" class="">clattner@nondot.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline">On Oct 8, 2017, at 11:57 AM, Michael Gottesman via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Oct 6, 2017, at 11:06 PM, Chris Lattner via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:<br class=""><br class="">This question is somewhere between swift-dev and swift-users, not sure where best to post this. &nbsp;<br class=""><br class="">I’m working on a project that wants to get very low-abstraction penalty array operations, particularly with varargs. &nbsp;Given the currently language limitations (no fixed size arrays), the best I’ve been able to come up with is something like this, where “lowlevelAPI” contains the heavy lifting (and is assumed to be opaque), and the “safeAPI” wrappers exist merely to provide a convenient safe wrapper for clients:<br class=""><br class="">&lt;array_abstraction.swift&gt;<br class=""><br class="">Given whole module optimization of the program, we should in principle, be able to optimize this down to the equivalent of an LLVM array alloca in the clients, a few stores to it, then passing the pointers to the LLVM alloca into lowlevelAPI. &nbsp;However, Swift is not doing this, not even with:<br class=""><br class="">$ swiftc array_abstraction.swift -emit-sil -o - -O<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">In this trivial case (with constant initializers) it does do the “array outlining” optimization,<br class=""></blockquote><br class="">What do you mean by the array outlining optimization specifically?<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I mean the "Outline global variable” thing that IPO/GlobalOpt.cpp does. &nbsp;I have no idea why it is called that.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">We definitely already have a heap-&gt;stack for classes in the guise of the StackPromotion optimization is that what you are talking about with the "array outlining" optimization? (outlining to me is referring to specifically code outlining). IIRC Erik (+CC) do special work to make it work for fixed size array. I would ask why that optimization is not kicking in for varargs. Perhaps, we could add a special recognition that the given array will not escape through a varargs? Or provide some way of saying, trust me this doesn't escape.<br class=""></blockquote></div></blockquote><div><br class=""></div><div>We already do heap-&gt;stack promotion for array buffers. This is done in the StackPromotion pass. It uses interprocedural escape analysis to check if it can be done. So if the callee is known it should work with the varargs array. BTW it also works in your example, in testAPI():</div><div><br class=""></div><div>%1 = alloc_ref <b class="">[stack]</b> [tail_elems $Int * %0 : $Builtin.Word] $_ContiguousArrayStorage&lt;Int&gt;</div><div><br class=""></div><div>But it’s not zero cost, because we initialize the metadata pointer + refcount in a runtime function. Also we do ref-count operations on the array in the callee (this will improve as soon as we have a ref count representation for immortal objects).</div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">This is actually pretty straight-forward to fit into the existing optimizer, and I’m working on a proto patch for it in my spare time this weekend. &nbsp;The problem is that it will only work on non-Apple systems because of the way that BridgeSupport model’s the ObjC interop goop. IMO, SIL and the stdlib have the wrong division of labor here. &nbsp;I’ll follow up with something more concrete when I have a chance.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">In terms of what Slava was talking about with copy-on-escape. That can be implemented (assuming a sane runtime ; p) by initializing any COW data structure with a count of 2. Then you are guaranteed to know that any write use or escape from the COW data structure will cause a copy. Once we have guaranteed, this comes for free since any guaranteed parameter must be copied before a mutable use.<br class=""><br class="">I do think that you will run into issues with escaping around C APIs though.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">C APIs cannot escape an array unless they have access to the refcount. &nbsp;Beyond the SIL representational problem with bridging, what I’m getting at seems like a straight-forward extension to ArrayElementValuePropagation.cpp.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">-Chris</span></div></blockquote></div><br class=""></div></body></html>