// |jit-test| skip-if: wasmCompileMode() != "ion"

// Tests that unrolling actually transforms a loop into something new, by
// unrolling a loop with just one FP mul and one FP add in it and checking that
// the resulting assembly contains 4 FP muls and 4 FP adds.  Matching bits of
// text in the disassembly is necessarily platform-dependent, but we don't care
// about that since unrolling is done at the MIR level, so if it works for one
// target, it works for all.
//
// Test inspired by simd/pmaddubsw-x64-ion-codegen.js.

const isX64 = getBuildConfiguration("x64") && !getBuildConfiguration("simulator");

if (hasDisassembler() && isX64) {
  let t = `
  (module
    (memory 1)
    (func (export "dot_product")
          (param $startA i32) (param $startB i32) (param $count i32)
      (local $sum f64)
      (if (i32.gt_u (local.get $count) (i32.const 0))
        (then
          (loop $cont
            (local.set $sum (f64.add (local.get $sum)
              (f64.mul (f64.load (local.get $startA))
                       (f64.load (local.get $startB)))))
            (local.set $startA (i32.add (local.get $startA) (i32.const 8)))
            (local.set $startB (i32.add (local.get $startB) (i32.const 8)))
            (local.set $count (i32.sub (local.get $count) (i32.const 1)))
            (br_if $cont (i32.gt_u (local.get $count) (i32.const 0)))
          )
        )
      )
    )
  )`;

  let i = new WebAssembly.Instance(
             new WebAssembly.Module(wasmTextToBinary(t)));

  const output = wasmDis(i.exports.dot_product, {tier:"ion", asString:true})
                 .replace(/^[0-9a-f]{8}  (?:[0-9a-f]{2} )+\n?\s+/gmi, "");

  // Find four "mulsd .. addsd" bits of text.  One pair for the peeled
  // iteration and 3 pairs for the 3 unrolled iterations.

  const re = /\bv?mulsd[^\n]+\nv?addsd /g;
  assertEq(re.exec(output) != null, true);
  assertEq(re.exec(output) != null, true);
  assertEq(re.exec(output) != null, true);
  assertEq(re.exec(output) != null, true);
  assertEq(re.exec(output) == null, true);
}
