binaryen icon indicating copy to clipboard operation
binaryen copied to clipboard

Code motion with the same side effects in branches does not always work

Open MaxGraey opened this issue 1 year ago • 4 comments

It seems CodeFolding can't handle such case with side effects (division):

export function not_branchless_ceil_div(x: i32, y: i32): i32 {
  return x >= 0 ? x / y : (x + y - 1) / y;
}

export function branchless_ceil_div(x: i32, y: i32): i32 {
  return (x >= 0 ? x : x + y - 1) / y;
}

Which output:

(module
 (func (export "not_branchless_ceil_div") $a (param $0 i32) (param $1 i32) (result i32)
  local.get $0
  i32.const 0
  i32.ge_s
  if (result i32)
   local.get $0
   local.get $1
   i32.div_s
  else
   local.get $0
   local.get $1
   i32.add
   i32.const 1
   i32.sub
   local.get $1
   i32.div_s
  end
 )
 (func (export "branchless_ceil_div") $b (param $0 i32) (param $1 i32) (result i32)
  local.get $0
  local.get $0
  local.get $1
  i32.add
  i32.const 1
  i32.sub
  local.get $0
  i32.const 0
  i32.ge_s
  select
  local.get $1
  i32.div_s
 )
)

But with CodeFolding both code should be identically branchless. Thought?

MaxGraey avatar Aug 01 '22 19:08 MaxGraey

(The "branchless" option still has ? : so it has a branch?)

I think the /y could be merged, that is true. CodeFolding might not be the pass that does it, though - OptimizeInstructions has logic for that, see the optimizeTernary function (see comment Identical code on both arms can be folded out).

kripken avatar Aug 02 '22 18:08 kripken

But optimizeTernary only applies for select which can't be produced by selectify due to side effect (division). That's why I think it should be done by CodeFolding pass which operate on block-level

MaxGraey avatar Aug 02 '22 19:08 MaxGraey

optimizeTernary can run on both select and if.

kripken avatar Aug 02 '22 19:08 kripken

Ah, now I see. Thanks! Will create a PR

MaxGraey avatar Aug 02 '22 19:08 MaxGraey