Issue 6620 - argument evaluation order inversed for extern(C)#4035
Issue 6620 - argument evaluation order inversed for extern(C)#40359rnsr wants to merge 5 commits intodlang:masterfrom
Conversation
3688cb9 to
5d75378
Compare
|
Ready to merge. |
|
Thanks, looks like we'll finally get ARM + x86 working alike. :) |
|
ping @WalterBright @andralex |
src/arrayop.c
Outdated
There was a problem hiding this comment.
It means "the head of argument list". Please teach me a better comment if you have.
|
This does much more than the evaluation order for function arguments. It is also changing the order of array operations. Array operations are currently left-to-right, except for assignments, which are right-to-left. This is not an accident. It turns out that faster code usually results from this, because fewer registers and temporaries are required to evaluate assignment right-to-left. |
|
@WalterBright Sorry, I'm really not sure what is the expected behavior. Today, vector operation behavior depends on issue 6620, because: int[] a, b, c;
a[] = b[] + c[];is lowered to: And the array op is evaluated with the order And after the glue-layer fix, the evaluation order will be changed to |
In case the meaning is still lost on people. In its current state, for all other architectures, the order is |
I think Walter is saying that the explicit order tests in arrayop.d are the correct behavior. The fact that the entire array op is lowered to an extern(C) function is an implementation detail. i.e. All those tests should be unchanged, only explicit calls to extern(C) functions should have any noticeable change. |
Unfortunately, even if a test suite tests the behavior of compiler generated code, but I sometimes doubt that the behavior is not actually designed, especially when the test case is not connected to a bugzilla issue. From some reasons I thought that the current
So I'd question to @WalterBright here: Which is the expected behavior and we should go? |
And even if it was designed, that doesn't necessarily mean it is desirable.
"The vector assignment operators are evaluated right to left, and the other binary operators are evaluated left to right." |
|
If we should really keep current array-op evaluation order, we need to modify front-end and inliner code drastically to handle the special evaluation order, to distinguish a function call is really a lowering of array-op or not. I cannot feel it would be worth to implement it. |
It doesn't have to be that bad, array-ops can survive intact to the glue layer and be transformed into a call there. |
I will never implement it. |
Haha fair enough. While it's on my radar it's not exactly high on my priority list. |
|
@WalterBright I have still question.
Is that generic opinion, or dmd backend specific? In this PR, I'm reorder |
|
I don't have any objections to changing the order of evaluation for array-ops, so we'll have to see if Walter can be convinced. |
|
OK, I'll wait Walter's answer. |
Actually, you could also do it by explicitly evaluating the arguments to temp variables in the frontend. eg Lowering a[] = b[] + c[];to auto tmpb = b[];
auto tmpc = c[];
auto tmpa = a[];
__arrayOpImp(tmpa, tmpc, tmpb); |
Of course it can. But it would add "more temporaries" and might slow down vector-ops. So I need to ask another question: "Current RTL evaluation order is really necessary?" |
Any reasonable optimizer would have no problem. Even dmd might be able to handle it.
Yeah I dunno. I suspect nobody every bothered to benchmark it. |
|
Consider: Minimizing register usage has a large impact on performance. This is why assignments are evaluated R-L, while other expressions are L-R. Yes, there are a lot of special case optimizations which will reduce the number of registers required, but in the general case, it remains. The issue with order of evaluation is not, from the user's perspective, really about whether it is L-R or R-L. It is about it being an essentially unpredictable order. Making it consistent in D is where we need to go. For example, should have repeatable results. What that result is doesn't really matter, it just needs to be repeatable across compiles and compilers. |
|
@WalterBright To me your argument sound reasonable for normal arithmetic operations. But there's still questions.
OT: Currently normal assignment is evaluated left to right. Maybe is it a bug? import core.stdc.stdio;
ref int a() { static int x; printf("a\n"); return x; }
int b() { printf("b\n"); return 1; }
int c() { printf("c\n"); return 2; }
void main() { a() = b() + c(); } // evaluation order is: a->b->c |
|
@9rnsr ,
as in, saying that assignments are L-R, and not erratic based on the operand types.
It's certainly not consistent. That leads to the question - how far do we want to go with this? There will be some level of performance penalty for making this all consistent, is it worth it? Does this really cause significant problems? I know I myself out of habit never write code that relies on order of evaluation. |
Yes. But the underlying reason is not array ops per say, just the way they happen to be lowered.
Should this evaluate LTR regardless of the |
It would be vulnerable for the small code modification. int[] a(); int[] b();
a()[] = b()[]; // a - >bIf you modify the code to add offset number with array operation, evaluation order will be suddenly changed. a()[] = b()[] + 1; // b -> aAs I explained, array operation does not have performance issue depending on the evaluation order. OTOH, from Walter's explanation, evaluating plain assignment I think all assignments (AssignExp, BinAssinExp, including any array operations) should have same evaluation order. Therefore now I have only one question: which is the correct evaluation order on all assignments, LTR or RTL? If the answer is LTR, I'll revert the |
|
Then isn't the best order for |
|
I'm just wondering when this x86-specific special case will be removed. |
|
2a67e56 to
b4c3d9a
Compare
|
I fully updated this PR. Now, array operation keeps existing evaluation order with AST adjustment in But unfortunately, Phobos unittest is failing in win32, because of a backend regression introduced from 2.069: |
9c92996 to
ac9a8a2
Compare
|
Regression 15898 has fixed in stable branch, and the bugfix change has merged into master. |
|
As far as I'm aware, array operations are still evaluated in a different order between x86 and every other cpu. Even if this isn't an ideal patch. |
|
As per #4895 - no point pursuing. The old x86-centric (and they only semantically work on x86) library functions need to die or be made |
https://issues.dlang.org/show_bug.cgi?id=6620