///|
// Keep the raw constant-fold shortcut consistent with the HOT power-of-two
// rules. Only the literal and its consuming operator change; the preceding
// dividend or multiplicand and all of its effects remain in place.
fn oi_sign_bit_raw_pair(
  rhs : @lib.Instruction,
  op : @lib.Instruction,
) -> (@lib.Instruction, @lib.Instruction)? {
  match (rhs, op) {
    (@lib.I32Const(@lib.I32(-2147483648)), @lib.I32DivU) =>
      Some(
        (
          @lib.Instruction::i32_const(@lib.I32(31)),
          @lib.Instruction::i32_shr_u(),
        ),
      )
    (@lib.I32Const(@lib.I32(-2147483648)), @lib.I32Mul) =>
      Some(
        (@lib.Instruction::i32_const(@lib.I32(31)), @lib.Instruction::i32_shl()),
      )
    (@lib.I32Const(@lib.I32(-2147483648)), @lib.I32RemU) =>
      Some(
        (
          @lib.Instruction::i32_const(@lib.I32(2147483647)),
          @lib.Instruction::i32_and(),
        ),
      )
    (@lib.I64Const(@lib.I64(-9223372036854775808L)), @lib.I64DivU) =>
      Some(
        (
          @lib.Instruction::i64_const(@lib.I64(63L)),
          @lib.Instruction::i64_shr_u(),
        ),
      )
    (@lib.I64Const(@lib.I64(-9223372036854775808L)), @lib.I64Mul) =>
      Some(
        (
          @lib.Instruction::i64_const(@lib.I64(63L)),
          @lib.Instruction::i64_shl(),
        ),
      )
    (@lib.I64Const(@lib.I64(-9223372036854775808L)), @lib.I64RemU) =>
      Some(
        (
          @lib.Instruction::i64_const(@lib.I64(9223372036854775807L)),
          @lib.Instruction::i64_and(),
        ),
      )
    _ => None
  }
}

///|
test "raw sign-bit matcher excludes zero and non-power bit patterns" {
  // These literals are outside this exact rule's domain. This does not limit
  // other division rules; replacing them with a fixed shift would be wrong.
  for value in [0, -2] {
    @debug.assert_eq(
      oi_sign_bit_raw_pair(
        @lib.Instruction::i32_const(@lib.I32(value)),
        @lib.Instruction::i32_div_u(),
      ),
      None,
    )
  }
  for value in [0L, -2L] {
    @debug.assert_eq(
      oi_sign_bit_raw_pair(
        @lib.Instruction::i64_const(@lib.I64(value)),
        @lib.Instruction::i64_div_u(),
      ),
      None,
    )
  }
}