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

performance: Peephole optimise (128 : Word8 & x == 0) resp. (128 : Word8 >= x) #177

Open
ggreif opened this issue Sep 17, 2020 · 6 comments
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@ggreif
Copy link
Contributor

ggreif commented Sep 17, 2020

to bitShiftRight 31

These happen frequently in the Random.mo code.

Note: this issue should be in motoko proper, but it ended up here by mistake. I cannot move it there.

@ggreif ggreif self-assigned this Sep 17, 2020
@ggreif ggreif added enhancement New feature or request good first issue Good for newcomers labels Sep 17, 2020
@ggreif
Copy link
Contributor Author

ggreif commented Sep 17, 2020

To give a concrete example, this Motoko

func upperMask(a : Word8) : Bool = a & (0x80 : Word8) != (0 : Word8);

compiles currently to this Wasm:

  (func $upperMask (type 5) (param $clos i32) (param $a i32) (result i32)
    local.get $a
    i32.const -2147483648 // 0x80000000
    i32.and
    i32.eqz
    i32.eqz
    i32.const 1
    i32.shl)

We could have (unverified)

  (func $upperMask (type 5) (param $clos i32) (param $a i32) (result i32)
    local.get $a
    i32.const 31
    i32.shr
    i32.const 1
    i32.shl)

@ggreif
Copy link
Contributor Author

ggreif commented Sep 17, 2020

Something like

func upperBitGe(a : Word8) : Bool = a >= (0x80 : Word8);
func upperBitGt(a : Word8) : Bool = a > (0x7F : Word8);

with upperBitGt will likely not work out of the box:

  (func $upperBitGt (type 5) (param $clos i32) (param $a i32) (result i32)
    local.get $a
    i32.const 2130706432 // 0x7f000000
    i32.gt_u
    i32.const 1
    i32.shl)
  (func $upperBitGe (type 5) (param $clos i32) (param $a i32) (result i32)
    local.get $a
    i32.const -2147483648 // 0x80000000
    i32.ge_u
    i32.const 1
    i32.shl)

unless we insert redundant hint instructions into the Wasm:

  (func $upperBitGt (type 5) (param $clos i32) (param $a i32) (result i32)
    local.get $a
    hint (i32.const 0xFF000000; i32.and) -- adds some info about the TOS: 24 lower bits are zeroed
    i32.const 2130706432 // 0x7f000000
    i32.gt_u
    i32.const 1
    i32.shl)

With such hints we can perform the i32.const 31; i32.shr trick.

I envision the hint meta-instruction (never emitted) to operate on top-of-stack asserting a semantic nop. This part is probably not beginner-friendly, though.

@ggreif
Copy link
Contributor Author

ggreif commented Sep 18, 2020

eqz; eqz; if --> if this is already performing: double swapping of the if legs.

@ggreif
Copy link
Contributor Author

ggreif commented Sep 18, 2020

Also note that after a 1-bit masking shr 31; shl 1 is just shr 30. Free tagging! Of course that is a different optimisation, since it needs the and to be preserved.

@ggreif
Copy link
Contributor Author

ggreif commented Sep 18, 2020

See motoko/gabor/peephole-177 for an implementation sketch (very WIP).

@ggreif
Copy link
Contributor Author

ggreif commented Sep 29, 2020

Another reduction path:

    block (result i32)  ;; label = @1
      i32.const 1
    end
    drop

block --> const --> eliminated by drop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant