Skip to content

Flaky const expression optimizations #2153

Closed
@lexaknyazev

Description

@lexaknyazev

Consider this snippet:

let w = 42 >> 1;
w = (w & 0xFC) | (w >> 1);

export const x = w;

The only exported value is x and it's a constant, so the compiled output should likely be

 (global $module/x i32 (i32.const 30))
 (export "x" (global $module/x))

Instead, the compiler produces the following (with -O3):

 (global $module/w (mut i32) (i32.const 0))
 (global $module/x (mut i32) (i32.const 0))
 (export "x" (global $module/x))
 (start $~start)
 (func $~start
  i32.const 21
  global.set $module/w
  i32.const 30
  global.set $module/w
  i32.const 30
  global.set $module/x
 )

This output shows several issues:

  • x is exported as a mutable global;
  • w exists as an internal global despite being used only for setting the x value once (fixed by -O3z);
  • two consecutive global.set calls are used on w (also fixed by -O3z).

What's more interesting is that simplifying the first line leads to even more complex output.

let w = 21;
w = (w & 0xFC) | (w >> 1);

export const x = w;
 (global $module/w (mut i32) (i32.const 21))
 (global $module/x (mut i32) (i32.const 0))
 (export "x" (global $module/x))
 (start $~start)
 (func $~start
  (local $0 i32)
  global.get $module/w
  local.tee $0
  i32.const 252
  i32.and
  local.get $0
  i32.const 1
  i32.shr_s
  i32.or
  global.set $module/w
  global.get $module/w
  global.set $module/x
 )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions