Skip to content

[Unhoisted] [Binary] [Should fallthrough] load & store order affects the constant propagation in binaryOp #7455

Closed
@xuruiyang2002

Description

@xuruiyang2002

Given the following code:

(module
  (type $0 (func))
  (type $1 (func (param i32 i32) (result i32)))
  (type $2 (func (result i32)))
  (type $3 (func (param i32) (result i32)))
  (import "External" "external_function" (func $external_function (type $0)))
  (func $_start (type $3) (param $0 i32) (result i32)
    (local $1 i32) (local $2 i32)
    i32.const 0
    i32.load
    local.set $2
    local.get $1
    i32.const 0
    call $foo
    local.set $1
    local.get $1
    local.get $2
    i32.gt_u
    if (result i32)  ;; label = @1
      call $external_function
      i32.const 0
    else
      i32.const 1
    end)
  (func $foo (type $1) (param $0 i32) (param $1 i32) (result i32)
    i32.const 0
    i32.const 0
    i32.store
    i32.const 0)
  (memory $0 258 258)
  (export "_start" (func $_start)))

The wasm-opt (16dbac1) can eliminate the dead true branch by -all -O2 but cannot by -all -O3.

Analysis

O2 produces the following if statement before inlining-optimizing:

(i32.gt_u
(call $foo) ==> return const 0, and it has side effect
(local.get $0) ;; ==> which is (i32.load $0 (i32.const 0) )
)

After inline, the condition is deduced to be zero, thus the true branch is deleted (call $external_function is in the true branch). (Of course it preserves the side-effect statements in the branch)

O3 produces the following if statement before inlining-optimizing:

(i32.lt_u
(i32.load $0 (i32.const 0) )
(call $foo)
)

After inline, the condition is transformed to

(i32.lt_u
 (i32.load $0 (i32.const 0) )
 (block (result i32)
  (i32.store $0
   (i32.const 0)
   (i32.const 0)
  )
  (i32.const 0)
 )
)

As you can see, the condition is almost the same as O2 produced before inlining-optimizing. However, wasm-opt failed to deduced the condition to be zero after inline -- It should be.

The only difference is the O2 uses gt_u and the O3 uses lt_u. Maybe the reorder of the comparison operands affects the optimization? So weird. (I am not sure about that).

Overall, I think there is a missed optimization in the updateAfterInlining -- wasm-opt may not handle constant propagation properly after inlining. (Similar to the #7454 )

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