<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, May 6, 2016 at 1:56 PM, Ettore Speziale 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">Hello,<br>
<span class=""><br>
> In the case of foo, there could be a problem.<br>
> If you do not mark it convergent, the LLVM sink pass push the call to foo to the then branch of the ternary operator, hence the program has been incorrectly optimized.<br>
><br>
> Really? It looks like the problem is that you lied to the compiler by marking the function as 'pure'. The barrier is a side-effect that cannot be removed or duplicated, so it's not correct to mark this function as pure.<br>
<br>
</span>I was trying to write a very small example to trick LLVM and trigger the optimization. It is based on Transforms/Sink/convergent.ll:<br>
<br>
define i32 @foo(i1 %arg) {<br>
entry:<br>
  %c = call i32 @bar() readonly convergent<br>
  br i1 %arg, label %then, label %end<br>
<br>
then:<br>
  ret i32 %c<br>
<br>
end:<br>
  ret i32 0<br>
}<br>
<br>
declare i32 @bar() readonly convergent<br></blockquote><div><br></div><div>This example looks wrong to me. It doesn't seem meaningful for a function to be both readonly and convergent, because convergent means the call has some side-effect visible to other threads and readonly means the call has no side-effects visible outside the function.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Here is another example:<br>
<br>
void foo0(void);<br>
void foo1(void);<br>
<br>
__attribute__((convergent)) void baz() {<br>
  barrier(CLK_GLOBAL_MEM_FENCE);<br>
}<br>
<br>
void bar(int x, global int *y) {<br>
  if (x < 5)<br>
    foo0();<br>
  else<br>
    foo1();<br>
<br>
  baz();<br>
<br>
  if (x < 5)<br>
    foo0();<br>
  else<br>
    foo1();<br>
}<br></blockquote><div><br></div><div>This one looks a lot more interesting. It looks like 'convergent' is a way of informing LLVM that the call cannot be duplicated, yes? That being the case, how is this attribute different from the existing [[clang::noduplicate]] / __attribute__((noduplicate)) attribute?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Based on Transforms/JumpThreading/basic.ll:<br>
<br>
define void @h_con(i32 %p) {<br>
  %x = icmp ult i32 %p, 5<br>
  br i1 %x, label %l1, label %l2<br>
<br>
l1:<br>
  call void @j()<br>
  br label %l3<br>
<br>
l2:<br>
  call void @k()<br>
  br label %l3<br>
<br>
l3:<br>
; CHECK: call void @g() [[CON:#[0-9]+]]<br>
; CHECK-NOT: call void @g() [[CON]]<br>
  call void @g() convergent<br>
  %y = icmp ult i32 %p, 5<br>
  br i1 %y, label %l4, label %l5<br>
<br>
l4:<br>
  call void @j()<br>
  ret void<br>
<br>
l5:<br>
  call void @k()<br>
  ret void<br>
; CHECK: }<br>
}<br>
<br>
If you do not mark baz convergent, you get this:<br>
<br>
clang -x cl -emit-llvm -S -o - test.c -O0 | opt -mem2reg -jump-threading -S<br>
<br>
define void @bar(i32 %x) #0 {<br>
entry:<br>
  %cmp = icmp slt i32 %x, 5<br>
  br i1 %cmp, label %if.then2, label %if.else3<br>
<br>
if.then2:                                         ; preds = %entry<br>
  call void @foo0()<br>
  call void @baz()<br>
  call void @foo0()<br>
  br label %if.end4<br>
<br>
if.else3:                                         ; preds = %entry<br>
  call void @foo1()<br>
  call void @baz()<br>
  call void @foo1()<br>
  br label %if.end4<br>
<br>
if.end4:                                          ; preds = %if.else3, %if.then2<br>
  ret void<br>
}<br>
<br>
Which is illegal, as the value of x might not be the same for all work-items.<br>
<br>
I’ll update the patch such as:<br>
<br>
* it uses the example about jump-threading<br>
* it marks the attribute available in OpenCL/Cuda<br>
* it provides the [[clang::convergent]] attribute<br>
<br>
Thanks,<br>
Ettore Speziale<br>
<div class="HOEnZb"><div class="h5"><br>
--------------------------------------------------<br>
Ettore Speziale — Compiler Engineer<br>
<a href="mailto:speziale.ettore@gmail.com">speziale.ettore@gmail.com</a><br>
<a href="mailto:espeziale@apple.com">espeziale@apple.com</a><br>
--------------------------------------------------<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div></div>