era-compiler-llvm icon indicating copy to clipboard operation
era-compiler-llvm copied to clipboard

Use add!, sub!, mul! for overflow flag setting

Open akiramenai opened this issue 10 months ago • 2 comments

The goal is to fix and restore the reverted patches:

  • https://github.com/matter-labs/era-compiler-llvm/commit/f31aa85caee7ccb207d66807cb6792cb7b8fa60b
  • https://github.com/matter-labs/era-compiler-llvm/commit/67627c680fe56c5d3b07923f90980b1e804add28

The patches introduce selection DAG patterns that fold uaddo, umulo, usubo into add!, mul!, sub! correspondingly. However, as it explained in the bug report, and another one [change to public links] this selection is incorrect as the original nodes create flags that persist while EraVM instructions set flags that can be overwritten. The rest of the logic in original patches could be kept as it is modulo to porting to LLVM 17.

== Bug reproducers ==

  1. cargo run --verbose --release --bin compiler-tester -- --path tests/solidity/simple/modular/addmod_complex.sol --mode='Y+M*B* 0.8.21' --load-system-contracts system-contracts-stable-build
  2. Add the test below as compiler-tester/tests/solidity/simple/bug.sol:
//! { "cases": [ {
//!     "name": "default",
//!     "inputs": [
//!         {
//!             "method": "balanceAtTime",
//!             "calldata": [
//!                 "1702053600",
//!                 "1702053600",
//!                 "100",
//!                 "1",
//!                 "1",
//!                 "1702053600",
//!                 "1702053610"
//!             ]
//!         }
//!     ],
//!     "expected": [
//!         "10",
//!         "90",
//!         "1702053610"
//!     ]
//! } ] }

// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.8.17;

contract Test {
    function min(uint256 a, uint256 b) public pure returns (uint256 _min) {
        _min = (a <= b) ? a : b;
    }

    function balanceAtTime(
        uint256 start,
        uint256 cliffDate,
        uint256 amount,
        uint256 rate,
        uint256 period,
        uint256 currentTime,
        uint256 redemptionTime
    )
        public
        pure
        returns (
            uint256 unlockedBalance,
            uint256 lockedBalance,
            uint256 unlockTime
        )
    {
        if (
            start > currentTime ||
            cliffDate > currentTime ||
            redemptionTime <= start
        ) {
            lockedBalance = amount;
            unlockTime = start;
        } else {
            uint256 periodsElapsed = (redemptionTime - start) / period;
            uint256 calculatedBalance = periodsElapsed * rate;
            unlockedBalance = min(calculatedBalance, amount);
            lockedBalance = amount - unlockedBalance;
            unlockTime = start + (period * periodsElapsed);
        }
    }
}

cargo run --verbose --release --bin compiler-tester -- --path tests/solidity/simple/bug.sol --mode='Y+M*B* 0.8.23'

akiramenai avatar Apr 22 '24 08:04 akiramenai