[Mlir-commits] [mlir] ee33e90 - [mlir][llvm] Add llvm.intr.modf intrinsic (#222355)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Sep 14 23:46:48 PDT 2026
Author: Letu Ren
Date: 2026-09-15T08:46:43+02:00
New Revision: ee33e90d1a1a064a0e21d28a27fbdb450490686c
URL: https://github.com/llvm/llvm-project/commit/ee33e90d1a1a064a0e21d28a27fbdb450490686c
DIFF: https://github.com/llvm/llvm-project/commit/ee33e90d1a1a064a0e21d28a27fbdb450490686c.diff
LOG: [mlir][llvm] Add llvm.intr.modf intrinsic (#222355)
Assisted-by: grok-4.6 and gpt-5.6-sol
---------
Signed-off-by: Letu Ren <fantasquex at gmail.com>
Added:
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/test/Dialect/LLVMIR/invalid.mlir
mlir/test/Dialect/LLVMIR/roundtrip.mlir
mlir/test/Target/LLVMIR/Import/fastmath.ll
mlir/test/Target/LLVMIR/Import/intrinsic.ll
mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index d185260126abe..785dd40a174ff 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -231,6 +231,16 @@ def LLVM_SincosOp : LLVM_TwoResultIntrOp<"sincos", [], [0],
"functional-type(operands, results)";
let hasVerifier = 1;
}
+def LLVM_ModfOp : LLVM_TwoResultIntrOp<"modf", [], [0],
+ [Pure], /*requiresFastmath=*/1> {
+ let arguments =
+ (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$val,
+ DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags);
+ let assemblyFormat = "`(` operands `)` (`fastmath` `` $fastmathFlags^)? "
+ "attr-dict `:` "
+ "functional-type(operands, results)";
+ let hasVerifier = 1;
+}
def LLVM_ASinOp : LLVM_UnaryIntrOpF<"asin">;
def LLVM_ACosOp : LLVM_UnaryIntrOpF<"acos">;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 52cd73f521326..114800058f7e6 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -4444,24 +4444,35 @@ void mlir::LLVM::printIndirectBrOpSucessors(
}
//===----------------------------------------------------------------------===//
-// SincosOp (intrinsic)
+// SincosOp and ModfOp (intrinsics)
//===----------------------------------------------------------------------===//
-LogicalResult LLVM::SincosOp::verify() {
- auto operandType = getOperand().getType();
- auto resultType = getResult().getType();
+static LogicalResult verifyHomogeneousStructResult(Operation *op,
+ Type operandType,
+ Type resultType) {
auto resultStructType =
mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
if (!resultStructType || resultStructType.getBody().size() != 2 ||
resultStructType.getBody()[0] != operandType ||
resultStructType.getBody()[1] != operandType) {
- return emitOpError("expected result type to be an homogeneous struct with "
- "two elements matching the operand type, but got ")
+ return op->emitOpError(
+ "expected result type to be a homogeneous struct with "
+ "two elements matching the operand type, but got ")
<< resultType;
}
return success();
}
+LogicalResult LLVM::SincosOp::verify() {
+ return verifyHomogeneousStructResult(getOperation(), getVal().getType(),
+ getResult().getType());
+}
+
+LogicalResult LLVM::ModfOp::verify() {
+ return verifyHomogeneousStructResult(getOperation(), getVal().getType(),
+ getResult().getType());
+}
+
//===----------------------------------------------------------------------===//
// AssumeOp (intrinsic)
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index 4ac160aa9f0fb..c2d59c1564a42 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -2299,26 +2299,47 @@ llvm.mlir.ifunc external @foo : !llvm.func<void (ptr, i32)>, !llvm.ptr @alias_re
// -----
llvm.func @invalid_sincos_nonhomogeneous_return_type(%f: f32) -> () {
- // expected-error at +1 {{op expected result type to be an homogeneous struct with two elements matching the operand type}}
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
llvm.intr.sincos(%f) : (f32) -> !llvm.struct<(f32, f64)>
}
// -----
llvm.func @invalid_sincos_non_struct_return_type(%f: f32) -> () {
- // expected-error at +1 {{op expected result type to be an homogeneous struct with two elements matching the operand type}}
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
llvm.intr.sincos(%f) : (f32) -> f32
}
// -----
llvm.func @invalid_sincos_gt_2_element_struct_return_type(%f: f32) -> () {
- // expected-error at +1 {{op expected result type to be an homogeneous struct with two elements matching the operand type}}
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
llvm.intr.sincos(%f) : (f32) -> !llvm.struct<(f32, f32, f32)>
}
// -----
+llvm.func @invalid_modf_nonhomogeneous_return_type(%f: f32) -> () {
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
+ llvm.intr.modf(%f) : (f32) -> !llvm.struct<(f32, f64)>
+}
+
+// -----
+
+llvm.func @invalid_modf_non_struct_return_type(%f: f32) -> () {
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
+ llvm.intr.modf(%f) : (f32) -> f32
+}
+
+// -----
+
+llvm.func @invalid_modf_gt_2_element_struct_return_type(%f: f32) -> () {
+ // expected-error at +1 {{op expected result type to be a homogeneous struct with two elements matching the operand type}}
+ llvm.intr.modf(%f) : (f32) -> !llvm.struct<(f32, f32, f32)>
+}
+
+// -----
+
module {
// expected-error at +1 {{'llvm.blockaddress' op expects an existing block label target in the referenced function}}
%0 = llvm.blockaddress <function = @missing_func, tag = <id = 1>> : !llvm.ptr
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 59a810116a040..f33cce1b8928e 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -770,6 +770,8 @@ func.func @fastmathFlags(%arg0: f32, %arg1: f32, %arg2: i32, %arg3: vector<2 x f
%11 = llvm.intr.sin(%arg0) fastmath<fast> : (f32) -> f32
// CHECK: {{.*}} = llvm.intr.sin(%arg0) fastmath<afn> : (f32) -> f32
%12 = llvm.intr.sin(%arg0) fastmath<afn> : (f32) -> f32
+// CHECK: {{.*}} = llvm.intr.modf(%arg0) fastmath<ninf> : (f32) -> !llvm.struct<(f32, f32)>
+ %modf = llvm.intr.modf(%arg0) fastmath<ninf> : (f32) -> !llvm.struct<(f32, f32)>
// CHECK: {{.*}} = llvm.intr.vector.reduce.fmin(%arg3) fastmath<nnan> : (vector<2xf32>) -> f32
%13 = llvm.intr.vector.reduce.fmin(%arg3) fastmath<nnan> : (vector<2xf32>) -> f32
diff --git a/mlir/test/Target/LLVMIR/Import/fastmath.ll b/mlir/test/Target/LLVMIR/Import/fastmath.ll
index 03d028d491615..89dc10b9b9814 100644
--- a/mlir/test/Target/LLVMIR/Import/fastmath.ll
+++ b/mlir/test/Target/LLVMIR/Import/fastmath.ll
@@ -58,6 +58,7 @@ declare float @llvm.vector.reduce.fmin.v2f32(<2 x float>)
declare float @llvm.vector.reduce.fmax.v2f32(<2 x float>)
declare float @llvm.vector.reduce.fminimum.v2f32(<2 x float>)
declare float @llvm.vector.reduce.fmaximum.v2f32(<2 x float>)
+declare { float, float } @llvm.modf.f32(float)
; CHECK-LABEL: @fastmath_intr
define void @fastmath_intr(float %arg1, i32 %arg2, <2 x float> %arg3) {
@@ -77,6 +78,8 @@ define void @fastmath_intr(float %arg1, i32 %arg2, <2 x float> %arg3) {
%7 = call nnan float @llvm.vector.reduce.fminimum.v2f32(<2 x float> %arg3)
; CHECK: %{{.*}} = llvm.intr.vector.reduce.fmaximum({{.*}}) fastmath<nnan> : (vector<2xf32>) -> f32
%8 = call nnan float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> %arg3)
+ ; CHECK: llvm.intr.modf(%{{.*}}) fastmath<ninf> : (f32) -> !llvm.struct<(f32, f32)>
+ %9 = call ninf { float, float } @llvm.modf.f32(float %arg1)
ret void
}
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll
index 694d21c2f9f53..dbc124b339169 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll
@@ -69,6 +69,15 @@ define void @frexp_test(float %0, <8 x float> %1) {
ret void
}
+; CHECK-LABEL: llvm.func @modf_test
+define void @modf_test(float %0, <8 x float> %1) {
+ ; CHECK: llvm.intr.modf(%{{.*}}) : (f32) -> !llvm.struct<(f32, f32)>
+ %3 = call { float, float } @llvm.modf.f32(float %0)
+ ; CHECK: llvm.intr.modf(%{{.*}}) : (vector<8xf32>) -> !llvm.struct<(vector<8xf32>, vector<8xf32>)>
+ %4 = call { <8 x float>, <8 x float> } @llvm.modf.v8f32(<8 x float> %1)
+ ret void
+}
+
; CHECK-LABEL: llvm.func @log_test
define void @log_test(float %0, <8 x float> %1) {
; CHECK: llvm.intr.log(%{{.*}}) : (f32) -> f32
@@ -1757,6 +1766,8 @@ declare float @llvm.ldexp.f32.i32(float, i32)
declare <8 x float> @llvm.ldexp.v8f32.i32(<8 x float>, i32)
declare { float, i32 } @llvm.frexp.f32.i32(float)
declare { <8 x float>, i32 } @llvm.frexp.v8f32.i32(<8 x float>)
+declare { float, float } @llvm.modf.f32(float)
+declare { <8 x float>, <8 x float> } @llvm.modf.v8f32(<8 x float>)
declare float @llvm.log.f32(float)
declare <8 x float> @llvm.log.v8f32(<8 x float>)
declare float @llvm.log10.f32(float)
diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
index 5268a2772a506..e5a7ec566268e 100644
--- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
@@ -67,6 +67,17 @@ llvm.func @frexp_test(%arg0: f32, %arg1: vector<8xf32>) {
llvm.return
}
+// CHECK-LABEL: @modf_test
+llvm.func @modf_test(%arg0: f32, %arg1: vector<8xf32>) {
+ // CHECK: call { float, float } @llvm.modf.f32(float %{{.*}})
+ llvm.intr.modf(%arg0) : (f32) -> !llvm.struct<(f32, f32)>
+ // CHECK: call { <8 x float>, <8 x float> } @llvm.modf.v8f32(<8 x float> %{{.*}})
+ llvm.intr.modf(%arg1) : (vector<8xf32>) -> !llvm.struct<(vector<8xf32>, vector<8xf32>)>
+ // CHECK: call ninf { float, float } @llvm.modf.f32(float %{{.*}})
+ llvm.intr.modf(%arg0) fastmath<ninf> : (f32) -> !llvm.struct<(f32, f32)>
+ llvm.return
+}
+
// CHECK-LABEL: @log_test
llvm.func @log_test(%arg0: f32, %arg1: vector<8xf32>) {
// CHECK: call float @llvm.log.f32
@@ -2014,6 +2025,8 @@ llvm.func @vector_scmp(%a: vector<4 x i32>, %b: vector<4 x i32>) -> vector<4 x i
// CHECK-DAG: declare <8 x float> @llvm.ldexp.v8f32.i32(<8 x float>, i32)
// CHECK-DAG: declare { float, i32 } @llvm.frexp.f32.i32(float)
// CHECK-DAG: declare { <8 x float>, i32 } @llvm.frexp.v8f32.i32(<8 x float>)
+// CHECK-DAG: declare { float, float } @llvm.modf.f32(float)
+// CHECK-DAG: declare { <8 x float>, <8 x float> } @llvm.modf.v8f32(<8 x float>)
// CHECK-DAG: declare float @llvm.log.f32(float)
// CHECK-DAG: declare <8 x float> @llvm.log.v8f32(<8 x float>)
// CHECK-DAG: declare float @llvm.log10.f32(float)
More information about the Mlir-commits
mailing list