<html>
<head>
<base href="http://bugzilla.gdcproject.org/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Wrong codegen is used for <OP>= expressions when there is a function as part of the rvalue."
href="http://bugzilla.gdcproject.org/show_bug.cgi?id=185">185</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Wrong codegen is used for <OP>= expressions when there is a function as part of the rvalue.
</td>
</tr>
<tr>
<th>Product</th>
<td>GDC
</td>
</tr>
<tr>
<th>Version</th>
<td>4.9.x
</td>
</tr>
<tr>
<th>Hardware</th>
<td>x86_64
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>blocker
</td>
</tr>
<tr>
<th>Priority</th>
<td>Normal
</td>
</tr>
<tr>
<th>Component</th>
<td>gdc
</td>
</tr>
<tr>
<th>Assignee</th>
<td>ibuclaw@gdcproject.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>liran@weka.io
</td>
</tr></table>
<p>
<div>
<pre>Initially issue was found in a large Fiber based application, and narrowed down
to use the += operation around functions that later call yield.
The code was:
-----------------
import std.stdio;
import core.thread;
enum numAddition = 3;
long globalSum = 0;
class DerivedFiber : Fiber
{
int index;
this(int _index)
{
index = _index;
super( &run );
}
private :
void run()
{
foreach(int k; 0 .. numAddition) {
globalSum += otherFunc();
writefln("DerivedFiber(%d) iteration %d globalSum is %d", index, k,
globalSum);
}
}
long otherFunc() {
yield();
return index;
}
}
int main()
{
Fiber derived1 = new DerivedFiber(1);
Fiber derived2 = new DerivedFiber(2);
foreach(j; 0 .. (numAddition+1)) {
derived1.call();
derived2.call();
}
assert(globalSum == (1+2)*numAddition);
return 0;
}
-------------------------
And the problem was that the compiler cached the globalSum value before the
yield, so concurrent changes were not possible.
Later, Johannes Pfau showed that generally <OP>= caches the "origin" even if
calling functions from other modules that may change the value without use of
fibers and yield at all.
"""
Iain: I think our codegen might be wrong. -fdump-tree-original:
@61 var_decl name: @76 mngl: @77 type: @60
scpe: @54 srcp: test.d:5
size: @39 algn: 64 used: 1
@62 plus_expr type: @60 op 0: @61 op 1: @78
@78 call_expr type: @60 fn : @96 0 : @23
Does GCC guarantee an evaluation order for plus_expr? This is
kinda weird btw. The rewrite might already happen in the frontend. If we
rewrite
globalSum += otherFunc();
to
globalSum = globalSum + otherFunc();
and follow strict LTR evaluation the code we generate is correct and
the code DMD generates is incorrect.
OTOH I don't know the exact rules for += but intuitively it should
first evaluate the RHS, then load the LHS.
"""
Then Iain Buclaw added:
"""
I can confirm that C codegen does infact emit 'foo += bar()' as 'foo
= bar() + foo'
Which only strengthens the reasoning to change it.
.
.
.
For commutative operations we can simply change the operands. For
non-commutative operations we'll have to explicitly evaluate the side
effects of the RHS before assigning. (-=, ...)
"""</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are watching all bug changes.</li>
</ul>
</body>
</html>