<p dir="ltr">Unlike C++, LLVM IR has defined semantics in the case of data races. Your load may return undef (<a href="http://llvm.org/docs/Atomics.html#optimization-outside-atomic">http://llvm.org/docs/Atomics.html#optimization-outside-atomic</a>), but the program doesn't have undefined behavior.</p>
<div class="gmail_quote">On Jan 27, 2015 6:20 AM,  <<a href="mailto:sohachak@mpi-sws.org">sohachak@mpi-sws.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I agree that the earlier example was already racy due to shared flag<br>
variable. Sorry for the wrong example. Please ignore it.<br>
<br>
I have modified the program as follows. The only shared variable is 'a'<br>
and the following is a non-racy program.<br>
<br>
int a;<br>
<br>
int readA(bool flag) {<br>
 int r=0;<br>
  if(flag) {<br>
    r = a;<br>
 }<br>
return r;<br>
}<br>
<br>
void writeA(){<br>
  a = 42;<br>
}<br>
<br>
int main() {<br>
<br>
 bool flag = false;<br>
 thread first (writeA);<br>
 thread second (readA, flag);<br>
<br>
 first.join();<br>
 second.join();<br>
<br>
 return 0;<br>
}<br>
<br>
The generated LLVM IR<br>
<br>
; Function Attrs: nounwind readonly uwtable<br>
define i32 @_Z5readAb(i1 zeroext %flag) #3 {<br>
entry:<br>
  %0 = load i32* @a, align 4<br>
  %. = select i1 %flag, i32 %0, i32 0<br>
  ret i32 %.<br>
}<br>
<br>
; Function Attrs: nounwind uwtable<br>
define void @_Z6writeAv() #4 {<br>
entry:<br>
  store i32 42, i32* @a, align 4<br>
  ret void<br>
}<br>
<br>
:<br>
<br>
In the generated IR load(a) is independent of flag value which is not the<br>
case in the source program. Hence there is an introduced race between<br>
load(a) and store(a) operations when readA() and writeA() runs<br>
concurrently.<br>
<br>
Regards,<br>
soham<br>
<br>
<br>
> On 26 Jan 2015, at 15:22, <a href="mailto:sohachak@mpi-sws.org">sohachak@mpi-sws.org</a> wrote:<br>
>><br>
>> The source program has no data race if flag=false. But the target<br>
>> program<br>
>> is racy due to the introduced load(a) operation.<br>
>><br>
>> This is a benign race since the load(a) is used only when flag=true.<br>
>><br>
>> However, according to the C11/C++11 consistency model the semantics of a<br>
>> racy program is undefined and may have arbitrary behavior.<br>
><br>
> It's not clear to me that this is correct.  Neither variable is atomic and<br>
> so loads do not establish happens-before edges.  The load of a is not<br>
> observable and so is safe to hoist.  According to the C[++]11 model the<br>
> transformed version appears correct.  There is no guarantee of<br>
> serialisation of the loads of flag and a, because neither is atomic.<br>
><br>
> It's not actually clear to me that the original is race-free.  If flag<br>
> ever transitions from false to true without something else that<br>
> establishes a happens-before relationship between these two threads then<br>
> this is racy.  If flag is always false, then this is not racy and the LLVM<br>
> output is not *observably* racy (the IR does not permit this load to have<br>
> observable side effects, and its result is never used).  If flag is always<br>
> true then this is racy.  If flag transitions from true to false without a<br>
> happens-before edge, then this is also racy.<br>
><br>
> David<br>
><br>
><br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
</blockquote></div>