[VMVX] Added an implementation of fpowi in vm for vmvx backend (#24608)
We have found some models, which failed to compile to vmvx, due to a
missing conversion for math.fpowi.
This PR includes an implementation for this op, as well as an addition
of VM_ComplexArithmeticOp class, since fpowi has a float and int input.
This case was not covered by the VM_BinaryArithmeticOp class. However,
since we only found fpowi in models, which utilize a i64 const for the
exponent, the op was implemented in such a way that it only accepts i64
as an exponent. Due to this, it was not necessary to implement a
ComplexArithmeticOpConversion in
[MathToVM/Patterns.cpp](https://github.com/iree-org/iree/blob/main/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/Patterns.cpp).
I also expanded the tests in arithmetic_ops.mlir, to include a check for
vm.fpowi.f32.
Signed-off-by: Hakan Eyilmez
[eyilmez@roofline.ai](mailto:eyilmez@roofline.ai)
---------
Signed-off-by: Hakan Eyilmez <eyilmez@roofline.ai>
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/Patterns.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/Patterns.cpp
index 48b8b3a..78ff73d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/Patterns.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/Patterns.cpp
@@ -122,6 +122,11 @@
IREE::VM::Log2F64Op>,
BinaryArithmeticOpConversion<math::PowFOp, IREE::VM::PowF32Op,
IREE::VM::PowF64Op>,
+ // Using BinaryArithmeticOp for fpowi op, since the int is
+ // coded to only be 64 bits, as this has been the only usecase
+ // so far. So a check of lhs (the float value) is sufficient.
+ BinaryArithmeticOpConversion<math::FPowIOp, IREE::VM::FPowI32Op,
+ IREE::VM::FPowI64Op>,
UnaryArithmeticOpConversion<math::RsqrtOp, IREE::VM::RsqrtF32Op,
IREE::VM::RsqrtF64Op>,
UnaryArithmeticOpConversion<math::SqrtOp, IREE::VM::SqrtF32Op,
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/test/arithmetic_ops.mlir b/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/test/arithmetic_ops.mlir
index 209debe..97ec9bc 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/test/arithmetic_ops.mlir
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/MathToVM/test/arithmetic_ops.mlir
@@ -93,3 +93,14 @@
return %20 : f32
}
+
+// -----
+
+// CHECK-LABEL: @arithmetic_f32_i64
+func.func @arithmetic_f32_i64(%arg0: f32, %arg1: i64) -> f32 {
+
+ // CHECK: vm.fpowi.f32
+ %0 = math.fpowi %arg0, %arg1 : f32, i64
+
+ return %0 : f32
+}
diff --git a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
index 740e317..13a1849 100644
--- a/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
+++ b/compiler/src/iree/compiler/Dialect/VM/Conversion/VMToEmitC/ConvertVMToEmitC.cpp
@@ -5120,6 +5120,7 @@
ADD_GENERIC_PATTERN(IREE::VM::OrI32Op, "vm_or_i32");
ADD_GENERIC_PATTERN(IREE::VM::OrI64Op, "vm_or_i64");
ADD_GENERIC_PATTERN(IREE::VM::PowF32Op, "vm_pow_f32");
+ ADD_GENERIC_PATTERN(IREE::VM::FPowI32Op, "vm_fpowi_f32");
ADD_GENERIC_PATTERN(IREE::VM::RemF32Op, "vm_rem_f32");
ADD_GENERIC_PATTERN(IREE::VM::RemI32SOp, "vm_rem_i32s");
ADD_GENERIC_PATTERN(IREE::VM::RemI32UOp, "vm_rem_i32u");
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF32.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF32.td
index 0127acc..2ce466d 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF32.td
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF32.td
@@ -71,6 +71,7 @@
def VM_OPC_SqrtF32 : VM_OPC<0x27, "SqrtF32">;
def VM_OPC_TanhF32 : VM_OPC<0x28, "TanhF32">;
def VM_OPC_ErfF32 : VM_OPC<0x29, "ErfF32">;
+def VM_OPC_FPowI32 : VM_OPC<0x3E, "FPowI32">;
def VM_OPC_CmpEQF32O : VM_OPC<0x2A, "CmpEQF32O">;
def VM_OPC_CmpEQF32U : VM_OPC<0x2B, "CmpEQF32U">;
@@ -148,6 +149,7 @@
VM_OPC_SqrtF32,
VM_OPC_TanhF32,
VM_OPC_ErfF32,
+ VM_OPC_FPowI32,
VM_OPC_CmpEQF32O,
VM_OPC_CmpEQF32U,
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF64.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF64.td
index c1230bd..ab6a1e0 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF64.td
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOpcodesF64.td
@@ -73,6 +73,7 @@
def VM_OPC_SqrtF64 : VM_OPC<0x2D, "SqrtF64">;
def VM_OPC_TanhF64 : VM_OPC<0x2E, "TanhF64">;
def VM_OPC_ErfF64 : VM_OPC<0x2F, "ErfF64">;
+def VM_OPC_FPowI64 : VM_OPC<0x40, "FPowI64">;
def VM_OPC_CmpEQF64O : VM_OPC<0x30, "CmpEQF64O">;
def VM_OPC_CmpEQF64U : VM_OPC<0x31, "CmpEQF64U">;
@@ -153,6 +154,7 @@
VM_OPC_SqrtF64,
VM_OPC_TanhF64,
VM_OPC_ErfF64,
+ VM_OPC_FPowI64,
VM_OPC_CmpEQF64O,
VM_OPC_CmpEQF64U,
diff --git a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
index 1082aea..09b1fab 100644
--- a/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
+++ b/compiler/src/iree/compiler/Dialect/VM/IR/VMOps.td
@@ -2442,6 +2442,32 @@
];
}
+class VM_MixedBinaryArithmeticOp<Type ltype, Type rtype, string mnemonic, VM_OPC opcode,
+ list<Trait> traits = []> :
+ VM_TrivialOp<mnemonic, !listconcat(traits, [
+ DeclareOpInterfaceMethods<VM_SerializableOpInterface>,
+ AllTypesMatch<["lhs", "result"]>,
+ ])> {
+ let arguments = (ins
+ ltype:$lhs,
+ rtype:$rhs
+ );
+ let results = (outs
+ ltype:$result
+ );
+
+ let assemblyFormat = [{
+ operands attr-dict `:` type($result)
+ }];
+
+ let encoding = [
+ VM_EncOpcode<opcode>,
+ VM_EncOperand<"lhs", 0>,
+ VM_EncOperand<"rhs", 1>,
+ VM_EncResult<"result">,
+ ];
+}
+
// Arithmetic ops defined for all inputs which do not exhibit UB.
class VM_TotalUnaryArithmeticOp<Type type, string mnemonic, VM_OPC opcode,
list<Trait> traits = []> :
@@ -2458,6 +2484,11 @@
VM_TernaryArithmeticOp<type, mnemonic, opcode,
!listconcat(traits, [AlwaysSpeculatable])> {}
+class VM_TotalMixedBinaryArithmeticOp<Type ltype, Type rtype, string mnemonic, VM_OPC opcode,
+ list<Trait> traits = []> :
+ VM_MixedBinaryArithmeticOp<ltype, rtype, mnemonic, opcode,
+ !listconcat(traits, [AlwaysSpeculatable])> {}
+
} // OpGroupArithmeticHelperOps
//===----------------------------------------------------------------------===//
@@ -2974,6 +3005,16 @@
let summary = [{Floating point raised to the power of operation.}];
}
+def VM_FPowI32Op :
+ VM_TotalMixedBinaryArithmeticOp<F32, I64, "fpowi.f32", VM_OPC_FPowI32, [VM_ExtF32]> {
+ let summary = [{Floating point raised to the integer power of operation.}];
+}
+
+def VM_FPowI64Op :
+ VM_TotalMixedBinaryArithmeticOp<F64, I64, "fpowi.f64", VM_OPC_FPowI64, [VM_ExtF64]> {
+ let summary = [{Floating point raised to the integer power of operation.}];
+}
+
def VM_RsqrtF32Op :
VM_TotalUnaryArithmeticOp<F32, "rsqrt.f32", VM_OPC_RsqrtF32, [VM_ExtF32]> {
let summary = [{Reciprocal of sqrt (1 / sqrt of the specified value).}];
diff --git a/runtime/src/iree/base/internal/math.h b/runtime/src/iree/base/internal/math.h
index ef07cce..7afffed 100644
--- a/runtime/src/iree/base/internal/math.h
+++ b/runtime/src/iree/base/internal/math.h
@@ -641,4 +641,61 @@
return biased < 0 ? 0 : biased > 0xFF ? 0xFF : biased;
}
+//==============================================================================
+// FpowI support.
+//==============================================================================
+
+// The implementation of fpowi was copied from
+// https://github.com/llvm/llvm-project/blob/c7c340b41e4fe424f0f5f68be2f2812ac6d17b41/flang-rt/lib/runtime/complex-powi.cpp#L21
+// However, since <limits> is not included the min and max of the exponent
+// were coded in hexadecimal format
+#define IREE_MATH_FPOWI(TYPE, base, exp) \
+ if ((exp) == 0) { \
+ return (TYPE)1.0; \
+ } \
+ bool invertResult = (exp) < 0; \
+ bool isMin = ((exp) == 0x8000000000000000); /* -2^63 */ \
+ if (isMin) { \
+ (exp) = 0x7FFFFFFFFFFFFFFF; /* 2^63 - 1 */ \
+ } \
+ if ((exp) < 0) { \
+ (exp) = (exp) * -1; \
+ } \
+ TYPE origBase = (base); \
+ while (((exp) & 1) == 0) { \
+ (base) *= (base); \
+ (exp) >>= 1; \
+ } \
+ TYPE acc = (base); \
+ while ((exp) > 1) { \
+ (exp) >>= 1; \
+ (base) *= (base); \
+ if (((exp) & 1) == 1) { \
+ acc *= (base); \
+ } \
+ } \
+ if (isMin) { \
+ acc *= origBase; \
+ } \
+ if (invertResult) { \
+ acc = (TYPE)1.0 / acc; \
+ } \
+ return acc;
+
+static inline float iree_math_float_powi_i64(float base, int64_t exp) {
+#if defined(IREE_COMPILER_GCC_COMPAT)
+ return __builtin_powif(base, exp);
+#else
+ IREE_MATH_FPOWI(float, base, exp)
+#endif
+}
+
+static inline double iree_math_double_powi_i64(double base, int64_t exp) {
+#if defined(IREE_COMPILER_GCC_COMPAT)
+ return __builtin_powi(base, exp);
+#else
+ IREE_MATH_FPOWI(double, base, exp)
+#endif
+}
+
#endif // IREE_BASE_INTERNAL_MATH_H_
diff --git a/runtime/src/iree/base/internal/math_test.cc b/runtime/src/iree/base/internal/math_test.cc
index 222555d..34118dd 100644
--- a/runtime/src/iree/base/internal/math_test.cc
+++ b/runtime/src/iree/base/internal/math_test.cc
@@ -1080,4 +1080,26 @@
EXPECT_TRUE(isnan(iree_math_f8e8m0fnu_to_f32(0xFF)));
}
+//==============================================================================
+// FpowI support
+//==============================================================================
+
+TEST(FPowITests, iree_math_float_powi_i64) {
+ EXPECT_FLOAT_EQ(1.0f, iree_math_float_powi_i64(12.0f, 0));
+ EXPECT_FLOAT_EQ(1.0f, iree_math_float_powi_i64(1.0f, 4));
+ EXPECT_FLOAT_EQ(27.0f, iree_math_float_powi_i64(3.0f, 3));
+ EXPECT_FLOAT_EQ(0.25f, iree_math_float_powi_i64(2.0f, -2));
+ // No testcase for if iree_math_float_powi_i64 correctly behaves for
+ // exp = -2 ^ 63, since the resulting value is too large.
+}
+
+TEST(FPowITests, iree_math_double_powi_i64) {
+ EXPECT_DOUBLE_EQ(1.0, iree_math_double_powi_i64(12.0, 0));
+ EXPECT_DOUBLE_EQ(1.0, iree_math_double_powi_i64(1.0, 4));
+ EXPECT_DOUBLE_EQ(27.0, iree_math_double_powi_i64(3.0, 3));
+ EXPECT_DOUBLE_EQ(0.25, iree_math_double_powi_i64(2.0, -2));
+ // No testcase for if iree_math_double_powi_i64 correctly behaves for
+ // exp = -2 ^ 63, since the resulting value is too large.
+}
+
} // namespace
diff --git a/runtime/src/iree/vm/bytecode/disassembler.c b/runtime/src/iree/vm/bytecode/disassembler.c
index 811211e..29ce3d7 100644
--- a/runtime/src/iree/vm/bytecode/disassembler.c
+++ b/runtime/src/iree/vm/bytecode/disassembler.c
@@ -409,6 +409,22 @@
break; \
}
+#define IREE_VM_ISA_EMIT_OP_EXT_F32_MIXED_BINARY_F32(op_name, op_mnemonic) \
+ IREE_VM_ISA_EMIT_OP(EXT_F32, op_name) { \
+ IREE_VM_ISA_DECODE_OPERAND_F32(lhs_reg); \
+ IREE_VM_ISA_DECODE_OPERAND_I64(rhs_reg); \
+ IREE_VM_ISA_DECODE_RESULT_F32(result_reg); \
+ IREE_VM_ISA_EMIT_F32_REG_NAME(result_reg); \
+ IREE_RETURN_IF_ERROR( \
+ iree_string_builder_append_format(b, " = %s ", op_mnemonic)); \
+ IREE_VM_ISA_EMIT_F32_REG_NAME(lhs_reg); \
+ IREE_VM_ISA_EMIT_OPTIONAL_VALUE_F32(regs->i32[lhs_reg]); \
+ IREE_RETURN_IF_ERROR(iree_string_builder_append_cstring(b, ", ")); \
+ IREE_VM_ISA_EMIT_I64_REG_NAME(rhs_reg); \
+ IREE_VM_ISA_EMIT_OPTIONAL_VALUE_I64(regs->i32[rhs_reg]); \
+ break; \
+ }
+
#define IREE_VM_ISA_EMIT_OP_EXT_F32_TERNARY_F32(op_name, op_mnemonic) \
IREE_VM_ISA_EMIT_OP(EXT_F32, op_name) { \
IREE_VM_ISA_DECODE_OPERAND_F32(a_reg); \
@@ -457,6 +473,22 @@
break; \
}
+#define IREE_VM_ISA_EMIT_OP_EXT_F64_MIXED_BINARY_F64(op_name, op_mnemonic) \
+ IREE_VM_ISA_EMIT_OP(EXT_F64, op_name) { \
+ IREE_VM_ISA_DECODE_OPERAND_F64(lhs_reg); \
+ IREE_VM_ISA_DECODE_OPERAND_I64(rhs_reg); \
+ IREE_VM_ISA_DECODE_RESULT_F64(result_reg); \
+ IREE_VM_ISA_EMIT_F64_REG_NAME(result_reg); \
+ IREE_RETURN_IF_ERROR( \
+ iree_string_builder_append_format(b, " = %s ", op_mnemonic)); \
+ IREE_VM_ISA_EMIT_F64_REG_NAME(lhs_reg); \
+ IREE_VM_ISA_EMIT_OPTIONAL_VALUE_F64(regs->i32[lhs_reg]); \
+ IREE_RETURN_IF_ERROR(iree_string_builder_append_cstring(b, ", ")); \
+ IREE_VM_ISA_EMIT_I64_REG_NAME(rhs_reg); \
+ IREE_VM_ISA_EMIT_OPTIONAL_VALUE_I64(regs->i32[rhs_reg]); \
+ break; \
+ }
+
#define IREE_VM_ISA_EMIT_OP_EXT_F64_TERNARY_F64(op_name, op_mnemonic) \
IREE_VM_ISA_EMIT_OP(EXT_F64, op_name) { \
IREE_VM_ISA_DECODE_OPERAND_F64(a_reg); \
@@ -2144,6 +2176,7 @@
IREE_VM_ISA_EMIT_OP_EXT_F32_UNARY_F32(Log1pF32, "vm.log1p.f32");
IREE_VM_ISA_EMIT_OP_EXT_F32_UNARY_F32(Log2F32, "vm.log2.f32");
IREE_VM_ISA_EMIT_OP_EXT_F32_BINARY_F32(PowF32, "vm.pow.f32");
+ IREE_VM_ISA_EMIT_OP_EXT_F32_MIXED_BINARY_F32(FPowI32, "vm.fpowi.f32");
IREE_VM_ISA_EMIT_OP_EXT_F32_UNARY_F32(RsqrtF32, "vm.rsqrt.f32");
IREE_VM_ISA_EMIT_OP_EXT_F32_UNARY_F32(SqrtF32, "vm.sqrt.f32");
IREE_VM_ISA_EMIT_OP_EXT_F32_UNARY_F32(TanhF32, "vm.tanh.f32");
@@ -2533,6 +2566,7 @@
IREE_VM_ISA_EMIT_OP_EXT_F64_UNARY_F64(Log1pF64, "vm.log1p.f64");
IREE_VM_ISA_EMIT_OP_EXT_F64_UNARY_F64(Log2F64, "vm.log2.f64");
IREE_VM_ISA_EMIT_OP_EXT_F64_BINARY_F64(PowF64, "vm.pow.f64");
+ IREE_VM_ISA_EMIT_OP_EXT_F64_MIXED_BINARY_F64(FPowI64, "vm.fpowi.f64");
IREE_VM_ISA_EMIT_OP_EXT_F64_UNARY_F64(RsqrtF64, "vm.rsqrt.f64");
IREE_VM_ISA_EMIT_OP_EXT_F64_UNARY_F64(SqrtF64, "vm.sqrt.f64");
IREE_VM_ISA_EMIT_OP_EXT_F64_UNARY_F64(TanhF64, "vm.tanh.f64");
diff --git a/runtime/src/iree/vm/bytecode/dispatch.c b/runtime/src/iree/vm/bytecode/dispatch.c
index b2e50da..4d0a53c 100644
--- a/runtime/src/iree/vm/bytecode/dispatch.c
+++ b/runtime/src/iree/vm/bytecode/dispatch.c
@@ -2541,6 +2541,7 @@
IREE_VM_ISA_DISPATCH_OP_EXT_F32_UNARY_F32(Log1pF32, vm_log1p_f32);
IREE_VM_ISA_DISPATCH_OP_EXT_F32_UNARY_F32(Log2F32, vm_log2_f32);
IREE_VM_ISA_DISPATCH_OP_EXT_F32_BINARY_F32(PowF32, vm_pow_f32);
+ IREE_VM_ISA_DISPATCH_OP_EXT_F32_MIXED_BINARY_F32(FPowI32, vm_fpowi_f32);
IREE_VM_ISA_DISPATCH_OP_EXT_F32_UNARY_F32(RsqrtF32, vm_rsqrt_f32);
IREE_VM_ISA_DISPATCH_OP_EXT_F32_UNARY_F32(SqrtF32, vm_sqrt_f32);
IREE_VM_ISA_DISPATCH_OP_EXT_F32_UNARY_F32(TanhF32, vm_tanh_f32);
@@ -2832,6 +2833,7 @@
IREE_VM_ISA_DISPATCH_OP_EXT_F64_UNARY_F64(Log1pF64, vm_log1p_f64);
IREE_VM_ISA_DISPATCH_OP_EXT_F64_UNARY_F64(Log2F64, vm_log2_f64);
IREE_VM_ISA_DISPATCH_OP_EXT_F64_BINARY_F64(PowF64, vm_pow_f64);
+ IREE_VM_ISA_DISPATCH_OP_EXT_F64_MIXED_BINARY_F64(FPowI64, vm_fpowi_f64);
IREE_VM_ISA_DISPATCH_OP_EXT_F64_UNARY_F64(RsqrtF64, vm_rsqrt_f64);
IREE_VM_ISA_DISPATCH_OP_EXT_F64_UNARY_F64(SqrtF64, vm_sqrt_f64);
IREE_VM_ISA_DISPATCH_OP_EXT_F64_UNARY_F64(TanhF64, vm_tanh_f64);
diff --git a/runtime/src/iree/vm/bytecode/dispatch_util.h b/runtime/src/iree/vm/bytecode/dispatch_util.h
index a10acfb..7936b66 100644
--- a/runtime/src/iree/vm/bytecode/dispatch_util.h
+++ b/runtime/src/iree/vm/bytecode/dispatch_util.h
@@ -327,6 +327,14 @@
*result = op_func(lhs, rhs); \
});
+#define IREE_VM_ISA_DISPATCH_OP_EXT_F32_MIXED_BINARY_F32(op_name, op_func) \
+ IREE_VM_ISA_DISPATCH_OP(EXT_F32, op_name, { \
+ IREE_VM_ISA_DISPATCH_DECODE_OPERAND_F32(lhs); \
+ IREE_VM_ISA_DISPATCH_DECODE_OPERAND_I64(rhs); \
+ IREE_VM_ISA_DISPATCH_DECODE_RESULT_F32(result); \
+ *result = op_func(lhs, rhs); \
+ });
+
#define IREE_VM_ISA_DISPATCH_OP_EXT_F32_TERNARY_F32(op_name, op_func) \
IREE_VM_ISA_DISPATCH_OP(EXT_F32, op_name, { \
IREE_VM_ISA_DISPATCH_DECODE_OPERAND_F32(a); \
@@ -351,6 +359,14 @@
*result = op_func(lhs, rhs); \
});
+#define IREE_VM_ISA_DISPATCH_OP_EXT_F64_MIXED_BINARY_F64(op_name, op_func) \
+ IREE_VM_ISA_DISPATCH_OP(EXT_F64, op_name, { \
+ IREE_VM_ISA_DISPATCH_DECODE_OPERAND_F64(lhs); \
+ IREE_VM_ISA_DISPATCH_DECODE_OPERAND_I64(rhs); \
+ IREE_VM_ISA_DISPATCH_DECODE_RESULT_F64(result); \
+ *result = op_func(lhs, rhs); \
+ });
+
#define IREE_VM_ISA_DISPATCH_OP_EXT_F64_TERNARY_F64(op_name, op_func) \
IREE_VM_ISA_DISPATCH_OP(EXT_F64, op_name, { \
IREE_VM_ISA_DISPATCH_DECODE_OPERAND_F64(a); \
diff --git a/runtime/src/iree/vm/bytecode/isa/isa.json b/runtime/src/iree/vm/bytecode/isa/isa.json
index 207ae63..cb56d10 100644
--- a/runtime/src/iree/vm/bytecode/isa/isa.json
+++ b/runtime/src/iree/vm/bytecode/isa/isa.json
@@ -3305,6 +3305,13 @@
"encoding": "i64_to_f32_conversion"
},
{
+ "opcode_set": "ext_f32",
+ "opcode": 62,
+ "symbol": "FPowI32",
+ "mnemonic": "fpowi.f32",
+ "encoding": "f32_binary"
+ },
+ {
"opcode_set": "ext_f64",
"opcode": 0,
"symbol": "GlobalLoadF64",
@@ -3751,6 +3758,13 @@
"symbol": "RoundF64Even",
"mnemonic": "round.f64.even",
"encoding": "f64_unary"
+ },
+ {
+ "opcode_set": "ext_f64",
+ "opcode": 64,
+ "symbol": "FPowI64",
+ "mnemonic": "fpowi.f64",
+ "encoding": "f64_binary"
}
]
}
diff --git a/runtime/src/iree/vm/bytecode/verifier.c b/runtime/src/iree/vm/bytecode/verifier.c
index 45b6118..496ad88 100644
--- a/runtime/src/iree/vm/bytecode/verifier.c
+++ b/runtime/src/iree/vm/bytecode/verifier.c
@@ -744,6 +744,13 @@
IREE_VM_ISA_DECODE_RESULT_F32(result); \
});
+#define IREE_VM_ISA_VERIFY_OP_EXT_F32_MIXED_BINARY_F32(op_name) \
+ IREE_VM_ISA_VERIFY_OP(EXT_F32, op_name, { \
+ IREE_VM_ISA_DECODE_OPERAND_F32(lhs); \
+ IREE_VM_ISA_DECODE_OPERAND_I64(rhs); \
+ IREE_VM_ISA_DECODE_RESULT_F32(result); \
+ });
+
#define IREE_VM_ISA_VERIFY_OP_EXT_F32_TERNARY_F32(op_name) \
IREE_VM_ISA_VERIFY_OP(EXT_F32, op_name, { \
IREE_VM_ISA_DECODE_OPERAND_F32(a); \
@@ -765,6 +772,13 @@
IREE_VM_ISA_DECODE_RESULT_F64(result); \
});
+#define IREE_VM_ISA_VERIFY_OP_EXT_F64_MIXED_BINARY_F64(op_name) \
+ IREE_VM_ISA_VERIFY_OP(EXT_F64, op_name, { \
+ IREE_VM_ISA_DECODE_OPERAND_F64(lhs); \
+ IREE_VM_ISA_DECODE_OPERAND_I64(rhs); \
+ IREE_VM_ISA_DECODE_RESULT_F64(result); \
+ });
+
#define IREE_VM_ISA_VERIFY_OP_EXT_F64_TERNARY_F64(op_name) \
IREE_VM_ISA_VERIFY_OP(EXT_F64, op_name, { \
IREE_VM_ISA_DECODE_OPERAND_F64(a); \
@@ -1849,6 +1863,7 @@
IREE_VM_ISA_VERIFY_OP_EXT_F32_UNARY_F32(Log1pF32);
IREE_VM_ISA_VERIFY_OP_EXT_F32_UNARY_F32(Log2F32);
IREE_VM_ISA_VERIFY_OP_EXT_F32_BINARY_F32(PowF32);
+ IREE_VM_ISA_VERIFY_OP_EXT_F32_MIXED_BINARY_F32(FPowI32);
IREE_VM_ISA_VERIFY_OP_EXT_F32_UNARY_F32(RsqrtF32);
IREE_VM_ISA_VERIFY_OP_EXT_F32_UNARY_F32(SqrtF32);
IREE_VM_ISA_VERIFY_OP_EXT_F32_UNARY_F32(TanhF32);
@@ -2059,6 +2074,7 @@
IREE_VM_ISA_VERIFY_OP_EXT_F64_UNARY_F64(Log1pF64);
IREE_VM_ISA_VERIFY_OP_EXT_F64_UNARY_F64(Log2F64);
IREE_VM_ISA_VERIFY_OP_EXT_F64_BINARY_F64(PowF64);
+ IREE_VM_ISA_VERIFY_OP_EXT_F64_MIXED_BINARY_F64(FPowI64);
IREE_VM_ISA_VERIFY_OP_EXT_F64_UNARY_F64(RsqrtF64);
IREE_VM_ISA_VERIFY_OP_EXT_F64_UNARY_F64(SqrtF64);
IREE_VM_ISA_VERIFY_OP_EXT_F64_UNARY_F64(TanhF64);
diff --git a/runtime/src/iree/vm/ops.h b/runtime/src/iree/vm/ops.h
index f9c5510..12bc753 100644
--- a/runtime/src/iree/vm/ops.h
+++ b/runtime/src/iree/vm/ops.h
@@ -587,6 +587,9 @@
static inline float vm_log1p_f32(float operand) { return log1pf(operand); }
static inline float vm_log2_f32(float operand) { return log2f(operand); }
static inline float vm_pow_f32(float b, float e) { return powf(b, e); }
+static inline float vm_fpowi_f32(float base, int64_t exp) {
+ return iree_math_float_powi_i64(base, exp);
+}
static inline float vm_rsqrt_f32(float operand) {
return 1.0f / sqrtf(operand);
}
@@ -780,6 +783,9 @@
static inline double vm_log1p_f64(double operand) { return log1p(operand); }
static inline double vm_log2_f64(double operand) { return log2(operand); }
static inline double vm_pow_f64(double b, double e) { return pow(b, e); }
+static inline double vm_fpowi_f64(double base, int64_t exp) {
+ return iree_math_double_powi_i64(base, exp);
+}
static inline double vm_rsqrt_f64(double operand) {
return 1.0 / sqrt(operand);
}
diff --git a/runtime/src/iree/vm/test/arithmetic_ops_f32.vmasm b/runtime/src/iree/vm/test/arithmetic_ops_f32.vmasm
index 8ec3542..4900332 100644
--- a/runtime/src/iree/vm/test/arithmetic_ops_f32.vmasm
+++ b/runtime/src/iree/vm/test/arithmetic_ops_f32.vmasm
@@ -398,6 +398,22 @@
vm.fail %i0, "pow(3.0,2.0)=9.0"
}
+vm.export @test_fpowi_f32
+vm.func @test_fpowi_f32() -> () {
+^bb0:
+ %i0 = vm.const.i32 8 // 0x00000008
+ %i1 = vm.const.f32 8
+ %i2:3 = vm.const.i64 3
+ %i4 = vm.const.f32 2
+ %i5 = vm.fpowi.f32 %i4, %i2
+ %i4 = vm.cmp.ne.f32.o %i5, %i1
+ vm.cond_br %i4, ^bb2(), ^bb1()
+^bb1:
+ vm.return
+^bb2:
+ vm.fail %i0, "fpowi(2.0,3)=8.0"
+}
+
vm.export @test_rsqrt_f32
vm.func @test_rsqrt_f32() -> () {
^bb0:
diff --git a/runtime/src/iree/vm/test/arithmetic_ops_f64.vmasm b/runtime/src/iree/vm/test/arithmetic_ops_f64.vmasm
index ce1a11c..a1e5d70 100644
--- a/runtime/src/iree/vm/test/arithmetic_ops_f64.vmasm
+++ b/runtime/src/iree/vm/test/arithmetic_ops_f64.vmasm
@@ -398,6 +398,22 @@
vm.fail %i0, "pow(3.0,2.0)=9.0"
}
+vm.export @test_fpowi_f64
+vm.func @test_fpowi_f64() -> () {
+^bb0:
+ %i0 = vm.const.i32 8 // 0x00000008
+ %i2:3 = vm.const.f64 8
+ %i4:5 = vm.const.i64 3
+ %i6:7 = vm.const.f64 2
+ %i4:5 = vm.fpowi.f64 %i6:7, %i4:5
+ %i1 = vm.cmp.ne.f64.o %i4:5, %i2:3
+ vm.cond_br %i1, ^bb2(), ^bb1()
+^bb1:
+ vm.return
+^bb2:
+ vm.fail %i0, "fpowi(2.0,3.0)=8.0"
+}
+
vm.export @test_rsqrt_f64
vm.func @test_rsqrt_f64() -> () {
^bb0: