Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitwise shifting instructions in EVM #215

Merged
merged 12 commits into from
Sep 22, 2017
94 changes: 94 additions & 0 deletions EIPS/eip-145.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
## Preamble

EIP: 145
Title: Bitwise shifting instructions in EVM
Author: Alex Beregszaszi, Paweł Bylica
Type: Standard Track
Category: Core
Status: Draft
Created: 2017-02-13


## Simple Summary

To provide native bitwise shifting with cost on par with other arithmetic operations.

## Abstract

Native bitwise shifting instructions are introduced, which are more efficient processing wise on the host and are cheaper to use by a contract.

## Motivation

EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetics cost each 35 gas, while the proposed instructions take 3 gas.

## Specification

The following instructions are introduced:

### `0x1b`: `SHL` (shift left)

The `SHL` instruction (shift left) pops 2 values from the stack, `arg1` and `arg2`, and pushes on the stack the second popped value `arg2` shifted to the left by the number of bits in the first popped value `arg1`. The result is equal to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would skip "second popped" / "first popped". If the order is not clear, it should be clarified in the first part of the sentence.

How about

... pushes on the stack the result of the arg2 shifted to the left by the number of bits in arg1.

Copy link
Member Author

@axic axic Sep 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually:

shifted to the left by arg1 number of bits

wouldn't be more readable?


```
(arg2 * 2^arg1) mod 2^256
```

Notes:
- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP MUL`.

### `0x1c`: `SHR` (logical shift right)

The `SHR` instruction (logical shift right) pops 2 values from the stack, `arg1` and `arg2`, and pushes on the stack the second popped value `arg2` shifted to the right by the number of bits in the first popped value `arg1` with zero fill. The result is equal to

```
floor(arg2 / 2^arg1)
```

Notes:
- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP DIV`.

### `0x1d`: `SAR` (arithmetic shift right)

The `SAR` instruction (arithmetic shift right) pops 2 values from the stack, `arg1` and `arg2`, and pushes on the stack the second popped value `arg2` shifted to the right by the number of bits in the first popped value `arg1` with sign extension. The result is equal to

```
floor(arg2 / 2^arg1)
```

Notes:
- The value (`arg2`) is interpreted as a signed number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0 if `arg2` is non-negative or -1 if `arg2` is negative.
- This is **not** equivalent to `PUSH1 2 EXP SDIV`, since it rounds differently. See `SDIV(-1, 2) == 0`, while `SAR(-1, 1) == -1`.

The cost of the shift instructions is set at `verylow` tier (3 gas).

## Rationale

Instruction operands were chosen to fit the more natural use case of shifting a value already on the stack. This means the operand order is swapped compared to most arithmetic insturctions.

## Backwards Compatibility

The newly introduced instructions have no effect on bytecode created in the past.

## Test Cases

TBA

## Implementation

Client support:
- cpp-ethereum: https://github.com/ethereum/cpp-ethereum/pull/4054

Compiler support:
- Solidity/LLL: https://github.com/ethereum/solidity/pull/2541

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).