| ▲ | 14113 3 hours ago | |||||||
Representing code in a compiler is not precisely trivial, and the two statements are actually quite different from a compiler or AST perspective. Just looking at the first branch:
This could be be represented with something like this (and this is a very vague approximation of an AST):
The second form, that looks this in the source:
might look like this in the AST:
If these two ASTs are to take the same form in the compilation pipeline, there needs to be some kind of pass that transforms one into the other.As for why the second form is faster (or rather, why the compiler can generate faster code): There is likely an optimisation pass somewhere in llvm that recognises a pattern that this fits into, which allows it to generate branchless instructions. For instance, in the second form, there is a pattern of:
that might be recognised by a pass. In the former form, the two operators are far apart in the tree, so a pass would have to "look further" to match them up. A single pass likely won't do this, either for (compiler) performance reasons, or for correctness reasons.Finding which pass that is can be non-trivial, as it's more than a matter of enabling individual passes until one works. It might be that an earlier pass does some code reshaping that allows the relevant pass to work. My suggestion would be to dump the llvm ir at the end, and find the rough pattern that you're looking for, then re-run the compilation with `-mllvm -print-after-all` to see what the IR looks like after each pass, and then manually "look back" until you can't see the pattern any more. | ||||||||
| ▲ | jimaway123 3 hours ago | parent [-] | |||||||
I don't think this could possibly be a valid AST for '*lwr++ = x' because the increment is not an operation on the dereferenced value, its an operation on the pointer. So in this case I don't see how it could help but be transformed into a form similar to the "beginner friendly" case.Or perhaps I am wrong and it would generate an AST like you describe and rely on later passes to actually create a proper dependency graph. My mental model of how these kinds of postfix operators work always assumed it must very early on turn it into two separate statements. Thank you for the suggestions. | ||||||||
| ||||||||