Skip to content

[Unhoisted] [Binary] [Might not fallthrough] load & store order affects the constant propagation in binaryOp #7489

@xuruiyang2002

Description

@xuruiyang2002

Given the following code:

(module
  (import "External" "external_function" (func $external_function))
  (func $_start 
    i32.const 0
    i32.const 0
    call $foo)
  (func $foo (param $0 i32) (param $2 i32) 
    block ;; label = @1
      i32.const 0
      i32.load
      drop
      i32.const 1
      i32.load
      local.set $2
      i32.const 1
      local.set $0
      local.get $2
      br_if 0 (;@1;)
      i32.const 1
      local.set $0
      local.get $0
      br_if 0 (;@1;)
      i32.const 0
      local.set $0
    end
    block ;; label = @1
      local.get $0
      br_if 0 (;@1;)
      call $external_function
    end)
  (memory $0 258 258)
  (export "_start" (func $_start)))

wasm-opt (c528c7e) can deduce the condition of branch (in the second block) to true by -all -O2, but cannot by -all -O3.

Below is the optimized code by -all -O3:

  (if
   (i32.eqz
    (block $block (result i32)
     (drop
      (i32.load (i32.const 0))
     )
     (drop
      (br_if $block
       (i32.const 1)
       (i32.load (i32.const 1))
      )
     )
     (i32.const 1)
    )
   )
   (then (call $external_function))
  )

It appears that the constant 1 is "buried" within the blocks and should be hoisted out so it can be recognized by i32.eqz.

This is similar to #7455 (where a constant value should be hoisted out in a binary operation). The same principle could be apply to unary operations. However, the key difference here is that these blocks here have names thus preventing them from being "fallthrough".

Here is the relevant code in getImmediateFallthroughPtr:

} else if (auto* block = curr->dynCast<Block>()) {
// if no name, we can't be broken to, and then can look at the fallthrough
if (!block->name.is() && block->list.size() > 0) {
return &block->list.back();
}

What do you think? Is there any better way to resolve it?

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