Skip to content

Functions with call.without.effects should preserve their conditions. #8044

@Tacodiva

Description

@Tacodiva

Right now, Binaryen optimizes this:

local.get $condition
if (result i32)
    local.get $argument
    ref.func $my_func ;; my_func (param i32) (result i32)
    call $call.without.effects
else
    i32.const 0
end

Into this:

local.get $condition
local.get $argument
call $my_func  ;; my_func (param i32) (result i32)
i32.const 0
select

Before, the function was only called if $condition but the optimizer has made the call unconditional. I can think of two situations this is harmful:

  1. If the call to the function is expensive. Getting rid of the conditional execution means binaryen will eliminate any faster paths trying to avoid the call.
  2. If the call to the function may have effects when the condition is not kept. For example, a function which crashes for inputs less than 0 might be guarded by a check to make sure the input is less than 0, avoiding the call if so. This call can still be removed if the result is dropped (because it has no other effects), but the condition must not be removed.

I have run into both of these cases trying to implement call.without.effects into my compiler. I was advised to make this into it's own issue from my comment on #7574.

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