<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Aug 21, 2015 at 10:35 AM, Michael Zolotukhin via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Yes, I've considered a builitin as an alternative. In fact, I started with it as it was easier to implement, but then decided to switch to type attribute due to the following reasons:<br>
<br>
1. ARM ACLE 2.0 mentions attribute. Though it's not a final version of the document, AFAIU, I still preferred to use it as an argument for type-attribute.<br></blockquote><div><br></div><div>I don't think this argument carries much weight by itself: I would imagine that the reason this was listed as a possible future direction was to solicit feedback from implementers and users; I think it's entirely appropriate for our feedback to be "this is the wrong approach".</div><div><br></div><div>Another objection I have to the ACLE proposal is that it puts the attribute on a pointer type but applies it to the pointee. This seems to make various reasonable use cases awkward to support. For instance, suppose I want to have a global variable to which I perform nontemporal loads and stores: I would need to take the address of that global, cast it to a nontemporal pointer, and dereference that in order to get a nontemporal operation. It would seem more natural to have the attribute apply to any type, and to apply to loads and stores of that type. So:</div><div><br></div><div>  int __attribute__((nontemporal)) *p; // a pointer to a nontemporal int</div><div>  int * __attribute__((nontemporal)) q; // a pointer (within nontemporal storage) to an int</div><div><br></div><div>  int x = *p; // normal load of p, nontemporal load of *p<br></div><div><div>  int y = *q; // nontemporal load of q, normal load of *q</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
2. Once we introduce a builtin, we'll have to support it forever (otherwise we could break someone's code). With the attribute the burden is much smaller, as we can just start ignoring it at any point if we need to - all the code will remain correct and compilable.<br></blockquote><div><br></div><div>Whatever we do here, we will in practice support it forever. We already have target-specific versions of these nontemporal operations that we intend to support forever. The support cost of the builtins is lower than that of a type attribute.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
3. We'll need to have an intrinsic for every type + separate intrinsics for loads and stores. If we use the type attribute, one fits all.<br></blockquote><div><br></div><div>Builtins can have custom type checking, and if they do they can effectively be overloaded for any type. (See the atomic builtins for an example.)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
4. While it's true, that this is more type of operation, than a type, I think in real use-cases a user would rarely need to use it on a single operation. I.e. nontemporal operations are usually used for processing bulk volumes of data, and probably this data is almost always is processed as a whole. That's why I think it's fine to mark the entire 'data' as nontemporal. And, if a user then wants to work with a small subset of it, she can use a usual (not nontemporal) pointer to it.<br></blockquote><div><br></div><div>OK, so you'd require a cast to/from a nontemporal type at the entry/exit of such code? That's probably reasonable, but like Aaron, I'm not really sure what usage patterns will appear in the wild here.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
5. Personally, I find the code using attributes more elegant than using builtins. Compare:<br>
<br>
  void foo(float *__attribute__((nontemporal)) dst,<br>
           float *__attribute__((nontemporal)) src1,<br>
           float *__attribute__((nontemporal)) src2) {<br>
    *dst = *src1 + *src2;<br>
  }<br>
<br>
and<br>
<br>
  void foo(float *dst, float *src1, float *src2) {<br>
    float s1 = __builtin_nontemporal_load(src1);<br>
    float s2 = __builtin_nontemporal_load(src2);<br>
    __builtin_nontemporal_store(s1 + s2, dst);<br>
  }<br>
<br>
But that said, in the end I'm open to other alternatives (including builtins), and this thread is just an attempt to find the best option.</blockquote><div><br></div><div>I think my personal preference here would depend on how important it is that these operations are nontemporal -- the latter formulation makes this a lot more obvious (the reader really can't miss that fact).</div></div></div></div>