[Mlir-commits] [mlir] [MLIR] Add sincos intrinsic to LLVM dialect (PR #160561)
Asher Mancinelli
llvmlistbot at llvm.org
Wed Sep 24 12:05:45 PDT 2025
https://github.com/ashermancinelli updated https://github.com/llvm/llvm-project/pull/160561
>From 8853d5f1a9ad331db32b64e0162ce261c26164d8 Mon Sep 17 00:00:00 2001
From: Asher Mancinelli <ashermancinelli at gmail.com>
Date: Wed, 24 Sep 2025 08:56:44 -0700
Subject: [PATCH 1/2] [MLIR] Add sincos intrinsic to LLVM dialect
Adds llvm.intr.sincos operation using LLVM_TwoResultIntrOp in the mold
of the frexp intrinsic.
---
.../mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td | 9 ++++++++
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 18 ++++++++++++++++
mlir/test/Dialect/LLVMIR/invalid.mlir | 21 +++++++++++++++++++
.../test/Target/LLVMIR/llvmir-intrinsics.mlir | 7 +++++++
4 files changed, 55 insertions(+)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index e12b8ac84ba23..398388bd720be 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -184,6 +184,15 @@ def LLVM_UMinOp : LLVM_BinarySameArgsIntrOpI<"umin">;
def LLVM_SinOp : LLVM_UnaryIntrOpF<"sin">;
def LLVM_CosOp : LLVM_UnaryIntrOpF<"cos">;
def LLVM_TanOp : LLVM_UnaryIntrOpF<"tan">;
+def LLVM_SincosOp : LLVM_TwoResultIntrOp<"sincos", [], [0],
+ [Pure], /*requiresFastmath=*/1> {
+ let arguments =
+ (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$val,
+ DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags);
+ let assemblyFormat = "`(` operands `)` 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 a3d5d25b96ec2..0d5e9e87070df 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -4085,6 +4085,24 @@ printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType,
p << "]";
}
+//===----------------------------------------------------------------------===//
+// SincosOp (intrinsic)
+//===----------------------------------------------------------------------===//
+
+LogicalResult LLVM::SincosOp::verify() {
+ auto operandType = getOperand().getType();
+ auto resultType = getResult().getType();
+ 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");
+ }
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// AssumeOp (intrinsic)
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index 1adecf264e8f6..627abd0665d8c 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -2014,3 +2014,24 @@ llvm.mlir.alias external @alias_resolver : !llvm.ptr {
}
// expected-error at +1 {{'llvm.mlir.ifunc' op must have a function resolver}}
llvm.mlir.ifunc external @foo : !llvm.func<void (ptr, i32)>, !llvm.ptr @alias_resolver {dso_local}
+
+// -----
+
+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}}
+ 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}}
+ 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}}
+ llvm.intr.sincos(%f) : (f32) -> !llvm.struct<(f32, f32, f32)>
+}
diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
index cf3e129879d09..d63584e5e03ab 100644
--- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
@@ -146,6 +146,11 @@ llvm.func @trig_test(%arg0: f32, %arg1: vector<8xf32>) {
llvm.intr.tan(%arg0) : (f32) -> f32
// CHECK: call <8 x float> @llvm.tan.v8f32
llvm.intr.tan(%arg1) : (vector<8xf32>) -> vector<8xf32>
+
+ // CHECK: call { float, float } @llvm.sincos.f32
+ llvm.intr.sincos(%arg0) : (f32) -> !llvm.struct<(f32, f32)>
+ // CHECK: call { <8 x float>, <8 x float> } @llvm.sincos.v8f32
+ llvm.intr.sincos(%arg1) : (vector<8xf32>) -> !llvm.struct<(vector<8xf32>, vector<8xf32>)>
llvm.return
}
@@ -1302,6 +1307,8 @@ llvm.func @experimental_constrained_fpext(%s: f32, %v: vector<4xf32>) {
// CHECK-DAG: declare <8 x float> @llvm.ceil.v8f32(<8 x float>) #0
// CHECK-DAG: declare float @llvm.cos.f32(float)
// CHECK-DAG: declare <8 x float> @llvm.cos.v8f32(<8 x float>) #0
+// CHECK-DAG: declare { float, float } @llvm.sincos.f32(float)
+// CHECK-DAG: declare { <8 x float>, <8 x float> } @llvm.sincos.v8f32(<8 x float>) #0
// CHECK-DAG: declare float @llvm.copysign.f32(float, float)
// CHECK-DAG: declare float @llvm.rint.f32(float)
// CHECK-DAG: declare double @llvm.rint.f64(double)
>From b692b77cd13943a8f351997fda27d81359377579 Mon Sep 17 00:00:00 2001
From: Asher Mancinelli <ashermancinelli at gmail.com>
Date: Wed, 24 Sep 2025 12:04:49 -0700
Subject: [PATCH 2/2] format
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 0d5e9e87070df..5d08cccb4faab 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -4098,7 +4098,8 @@ LogicalResult LLVM::SincosOp::verify() {
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");
+ "two elements matching the operand type, but got ")
+ << resultType;
}
return success();
}
More information about the Mlir-commits
mailing list