3
$\begingroup$

What is the standard way for VMs to deal with 0 *= computationallyHeavyFunction()? Given that once the VM sees that left hand factor is 0, it would know that the result of computationallyHeavyFunction() would not matter, is it standard for VMs to still compute computationallyHeavyFunction() or do they tend to omit that computation and just evaluate as 0?

Edit: After answer, I think I misphrased the question. I'll rephrase a bit and replace computationallyHeavyFunction() that has unknown factors. If VMs see 0 * (1-1/veryLargeNumber)^anotherVeryLargeNumber, do they tend to not compute right factor? Assuming they rely on squaring algorithm, quite computation heavy with O(log2(anotherVeryLargeNumber)).

$\endgroup$
5
$\begingroup$

Optimizing 0 * f(…) is correct only if f has no side effect and its result is known to be finite. If f has side effects, they must be executed even if the result does not matter. If f might return a result such as NaN or infinity then the result of the calculation might be NaN and not 0.

A VM that is optimized for numerical or symbolic calculations and that has access to enough type information to know that f has no side effects and has a finite result would presumably optimize the call away. Any other type of VM would not do this optimization.

$\endgroup$
  • $\begingroup$ Thanks. Did not think of that f() could be doing other things than just return result of arithmetics. If I rephrase a bit and leave out unknown factors, if VMs see 0 * (1-1/veryLargeNumber)^anotherVeryLargeNumber, do they tend to not compute right factor? Assuming they rely on squaring algorithm, quite computation heavy with O(log2(anotherVeryLargeNumber)). $\endgroup$ – Crassus Nov 25 '19 at 21:05
  • 1
    $\begingroup$ If it is in floating-point arithmetic, then in IEE754 multiplying 0.0 by a negative number including -0.0 yields -0.0, which is not the same. So you would also have to prove the second expression is positive, or the way the end result is used, +0 or -0 doesn't make a difference. $\endgroup$ – gnasher729 Nov 26 '19 at 10:05
1
$\begingroup$

Let's ignore the issues of side effects and peculiarities of floating point such as NaN and signed zeros and assume that it is meaningful to avoid the computation.

Let's also ignore the question of why the front end who generated the VM instruction stream did not do that optimization if the 0 is a literal or the result of a constant expression. That's an important assumption, as that optimization is relatively easy to do there.

My first point is that VM implementations varies a lot. I'll simplify that implementation space by considering two cases: interpreter VMs which executes the instruction one by one and compiling VMs which compile the VM instructions to another representation (potentially machine language) before execution. However note that it is common to have both approach in one VM executor, the interpreter used in a first place to collect profiling information to guide the compilation process of hot paths.

In the case of interpreter VMs, you have to look at the language interpreted. Those are usually byte code for a stack or a register machine. That's not a representation suitable for such kind of optimization as the facts first that the complex expression is suitable to be ignored is difficult to extract, then that there is a multiplication and that the value by which the multiplication is a special one and is probably after the description of your complex computation. In summary, I'd be surprised if interpreter VM paid that cost as I doubt the benefits warrant the price and if you are that performance sensitive, you'll have the setup to switch to a compiling VM for hot paths.

In the case of compiling VMs, you can have in practice quite a lot optimizations and they can afford to put back the instruction stream in a representation suitable for optimizations. The optimizations done are in fact the same kind of optimizations done in an optimizing compilers, with a tighter constraint on compilation time and the advantage of easier profiling information to guide the compilation. Reduction of multiplication by a constant (either a true constant or a constant value detected with the help of profile information) is far from being the most complex optimization they do and I'd expect it do be done. The case where the 0 is not a constant but the value of a variable is more complex. You can imagine it to generate code which check for 0 and then completely avoid the costly function, just as it is done for short-circuit boolean operators, but I'd be surprised if it is commonly done.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.