0
uint f = 0;
f *= computationallyHeavyFunction();

Does EVM run computationallyHeavyFunction(), or does it evaluate f = 0 and then omit further computation?

1

It runs it.

The first line casts f as uint. =0 is pointess because it defaults to 0.

The second line invokes a function and assigns the response to f.

It would also be okay to:

uint f = 0 * computationallyHeavyFunction();

Of course, f is 0 in any case.

Hope it helps.

  • was just wondering if it paid the gas for it or not, since the EVM would, once it sees "f = 0" know that the result of computationallyHeavyFunction() would not matter – Crassus Nov 25 '19 at 16:49
  • could I also ask, is it standard for VMs to run *= if the left hand side is 0? – Crassus Nov 25 '19 at 17:00
  • Q1: I don't think so, but you could have "computationallyHeavy" emit an event to be sure. Q2: The previous assignment is unimportant. I thought the 0 * phrasing looked a little weird, but it might be a way to silence warnings about ignoring a returned value. Otherwise, the function could be invoked without f existing at all and it would be cheaper. Maybe there should be no returned value if callers just ignore it/it is useless. – Rob Hitchens - B9lab Nov 25 '19 at 19:11
1

Indeed it does run it. First point, though, is that this is a property of the Solidity compiler, not the EVM itself - it could, if it thought it was correct, just not generate the EVM bytecode, so it wouldn't be run.

However, there is an issue of side-effects. The result of computationallyHeavyFunction() might not matter, but the function could modify storage or generate an exception. Consider this code:


contract optimisationTest{

    bool public flag;
    uint public foo;

    function setFlag() internal returns (uint256) {
        flag = true;

        return 1;
    }

    function complexCode() internal pure returns (uint256) {
        uint256 j;

        for (uint256 i = 0; i < 100; i ++) {
            j += i;
        }

        return j;
    }

    function test() public {
        foo = 0 * setFlag();
        foo = 0 * complexCode();
    }
}

Unless it's specifically mentioned in the language definition that right-hand-side functions aren't called in this case, then it's down to the optimiser to work it out using static analysis or similar.

I compiled this with optimisations on. Both setFlag() and complexCode() are called in Solidity 5.11 - I checked the latter with the debugger. The second one could indeed be eliminated in the optimiser but this does not appear to be the case with Solidity today.

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.