<div dir="ltr">Would you guys be open to supporting a new hint with the right semantics, like e.g. llvm.loop.noalias_accesses?! I would need to find support in clang however and the main point of support would be the loop unroller behaving as stated in the OP.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, May 14, 2020 at 3:04 PM Michael Kruse <<a href="mailto:llvmdev@meinersbur.de">llvmdev@meinersbur.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Trivial example:<br>
<br>
#pragma clang loop vectorize(assume_safety)<br>
for (int i = 0; i < n; i+=1) {<br>
(void)A[0];<br>
}<br>
<br>
I hope it is obvious that the loop is parallel and can be vectorized,<br>
but A[0] from iteration 0 will alias with A[0] from iteration 1.<br>
Replace `0` by `i*c` where c is a variable that can be 0 at runtime to<br>
make the fact non-obvious to the compiler.<br>
<br>
We had discussions about implementing "#pragma ivdep", but it's<br>
semantics are not defined independently of the implementation. Anyway,<br>
even with #pragma omp ivdep, a compiler is not required to vectorize<br>
the loop.<br>
<br>
In LLVM, runtime/partial unrolling only takes place after<br>
vectorization, so there is less of an issue there.<br>
<br>
Michael<br>
<br>
<br>
Am Do., 14. Mai 2020 um 16:16 Uhr schrieb Hendrik Greving <<a href="mailto:hgreving@google.com" target="_blank">hgreving@google.com</a>>:<br>
><br>
> This is interesting! So are you saying that loop.parallel_accesses strictly loop parallel, and says nothing about aliasing? I see, I guess we may have been "abusing" the hint and re-purposed it. But isn't llvm's vectorizer using loop.parallel_accesses to vectorize loops including vectorize memory accesses that if you ignore loop-carried dependencies, usually means effectively re-ordering the accesses? I guess this still does not imply "noalias"? What about icc/gcc's #pragma ivdep? Again here, it means no loop-carried dependencies, yet still doesn't say anything about noalias? Another way indeed would be to propagate noalias data and indeed rely on the future fix that Hal mentions above.<br>
><br>
><br>
><br>
> On Thu, May 14, 2020 at 1:33 PM Michael Kruse <<a href="mailto:llvmdev@meinersbur.de" target="_blank">llvmdev@meinersbur.de</a>> wrote:<br>
>><br>
>> llvm.loop.parallel_accesses does not imply that these accesses from<br>
>> different iterations are not aliasing. Examples where an access are<br>
>> parallel are that the accesses are atomic or read-only from a specific<br>
>> location.<br>
>><br>
>> The LoopUnrollPass might deduce that non-atomic stores are necessarily<br>
>> not aliasing (when not using transactional memory), but I don't think<br>
>> we can do this for all the read accesses. Would that be sufficiently<br>
>> useful?<br>
>><br>
>> Michael<br>
>><br>
>><br>
>> Am Do., 14. Mai 2020 um 15:11 Uhr schrieb Hendrik Greving via llvm-dev<br>
>> <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>:<br>
>> ><br>
>> > Hi, in our backend, which is unfortunately not upstreamed, we are relying on llvm.loop.parallel_accesses metadata for certain passes like software pipelining so we can re-order instructions. Ideally, we would want the loop unroller to support the notion of the loop's parallelism in its pre-unrolled version. This probably should happen by propagating !alias.scope and !alias metadata. Is there any plan or open patch for supporting this?<br>
>> ><br>
>> > Simplified example:<br>
>> ><br>
>> > for.body:<br>
>> > %0 = load [..]<br>
>> > store %0 [..]<br>
>> > br label %for.cond, !llvm.loop !2<br>
>> ><br>
>> > !1 = distinct !{}<br>
>> > !2 = distinct !{!2, !3, !4, !5, !6, !7}<br>
>> > !3 = !{!"llvm.loop.parallel_accesses", !1}<br>
>> > !4 = !{!"llvm.loop.vectorize.width", i32 1}<br>
>> > !5 = !{!"llvm.loop.interleave.count", i32 1}<br>
>> > !6 = !{!"llvm.loop.vectorize.enable", i1 true}<br>
>> > !7 = !{!"llvm.loop.vectorize.followup_all", !8}<br>
>> > !8 = !{!"llvm.loop.unroll.count", i32 2}<br>
>> ><br>
>> > (unroll by 2) =><br>
>> ><br>
>> > for.body:<br>
>> > %0 = load [..] !alias.scope !9 !noalias !11<br>
>> > store %0 [..] !alias.scope !9 !noalias !11<br>
>> > %1 = load [..] !alias.scope !10 !noalias !12<br>
>> > store %1 [..] !alias.scope !10 !noalias !12<br>
>> > br label %for.cond, !llvm.loop !2<br>
>> ><br>
>> > [..]<br>
>> ><br>
>> > !9 = distinct !{!9, !"iteration0"}<br>
>> > !10 = distinct !{!10, !"iteration1"}<br>
>> > !11 = !{!10}<br>
>> > !12 = !{!9}<br>
>> ><br>
>> > Thanks, Hendrik<br>
>> > _______________________________________________<br>
>> > LLVM Developers mailing list<br>
>> > <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
>> > <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>