diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td index 490130fde8550..e31e46124faf0 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -181,6 +181,18 @@ def LLVM_SMinOp : LLVM_BinarySameArgsIntrOpI<"smin">; def LLVM_UMaxOp : LLVM_BinarySameArgsIntrOpI<"umax">; def LLVM_UMinOp : LLVM_BinarySameArgsIntrOpI<"umin">; +class LLVM_CmpIntrOp + : LLVM_OneResultIntrOp { + let arguments = (ins LLVM_ScalarOrVectorOf:$a, + LLVM_ScalarOrVectorOf:$b); + let results = (outs LLVM_ScalarOrVectorOf:$res); + let assemblyFormat = "`(` operands `)` attr-dict `:` " + "functional-type(operands, results)"; +} + +def LLVM_SCmpOp : LLVM_CmpIntrOp<"scmp">; +def LLVM_UCmpOp : LLVM_CmpIntrOp<"ucmp">; + def LLVM_SinOp : LLVM_UnaryIntrOpF<"sin">; def LLVM_CosOp : LLVM_UnaryIntrOpF<"cos">; def LLVM_TanOp : LLVM_UnaryIntrOpF<"tan">; diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll index d2bb80982bb3d..2381d7acae44b 100644 --- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -1128,6 +1128,34 @@ define void @experimental_constrained_fpext(float %s, <4 x float> %v) { ret void } +; CHECK-LABEL: llvm.func @ucmp +define i2 @ucmp(i32 %a, i32 %b) { + ; CHECK: %{{.*}} = llvm.intr.ucmp(%{{.*}}, %{{.*}}) : (i32, i32) -> i2 + %r = call i2 @llvm.ucmp.i2.i32(i32 %a, i32 %b) + ret i2 %r +} + +; CHECK-LABEL: llvm.func @vector_ucmp +define <4 x i32> @vector_ucmp(<4 x i32> %a, <4 x i32> %b) { + ; CHECK: %{{.*}} = llvm.intr.ucmp(%{{.*}}, %{{.*}}) : (vector<4xi32>, vector<4xi32>) -> vector<4xi32> + %r = call <4 x i32> @llvm.ucmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %r +} + +; CHECK-LABEL: llvm.func @scmp +define i2 @scmp(i32 %a, i32 %b) { + ; CHECK: %{{.*}} = llvm.intr.scmp(%{{.*}}, %{{.*}}) : (i32, i32) -> i2 + %r = call i2 @llvm.scmp.i2.i32(i32 %a, i32 %b) + ret i2 %r +} + +; CHECK-LABEL: llvm.func @vector_scmp +define <4 x i32> @vector_scmp(<4 x i32> %a, <4 x i32> %b) { + ; CHECK: %{{.*}} = llvm.intr.scmp(%{{.*}}, %{{.*}}) : (vector<4xi32>, vector<4xi32>) -> vector<4xi32> + %r = call <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %r +} + declare float @llvm.fmuladd.f32(float, float, float) declare <8 x float> @llvm.fmuladd.v8f32(<8 x float>, <8 x float>, <8 x float>) declare float @llvm.fma.f32(float, float, float) @@ -1382,3 +1410,7 @@ declare <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f64(<4 x doubl declare float @llvm.experimental.constrained.fptrunc.f32.f64(double, metadata, metadata) declare <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f32(<4 x float>, metadata) declare double @llvm.experimental.constrained.fpext.f64.f32(float, metadata) +declare i2 @llvm.ucmp.i2.i32(i32, i32) +declare <4 x i32> @llvm.ucmp.v4i32.v4i32(<4 x i32>, <4 x i32>) +declare i2 @llvm.scmp.i2.i32(i32, i32) +declare <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32>, <4 x i32>) diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir index 60bd24a27868e..993f6f7ea2902 100644 --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -1276,6 +1276,34 @@ llvm.func @experimental_constrained_fpext(%s: f32, %v: vector<4xf32>) { llvm.return } +// CHECK-LABEL: @ucmp +llvm.func @ucmp(%a: i32, %b: i32) -> i2 { + // CHECK: call i2 @llvm.ucmp.i2.i32 + %r = llvm.intr.ucmp(%a, %b) : (i32, i32) -> i2 + llvm.return %r : i2 +} + +// CHECK-LABEL: @vector_ucmp +llvm.func @vector_ucmp(%a: vector<4 x i32>, %b: vector<4 x i32>) -> vector<4 x i32> { + // CHECK: call <4 x i32> @llvm.ucmp.v4i32.v4i32 + %0 = llvm.intr.ucmp(%a, %b) : (vector<4 x i32>, vector<4 x i32>) -> vector<4 x i32> + llvm.return %0 : vector<4 x i32> +} + +// CHECK-LABEL: @scmp +llvm.func @scmp(%a: i32, %b: i32) -> i2 { + // CHECK: call i2 @llvm.scmp.i2.i32 + %r = llvm.intr.scmp(%a, %b) : (i32, i32) -> i2 + llvm.return %r : i2 +} + +// CHECK-LABEL: @vector_scmp +llvm.func @vector_scmp(%a: vector<4 x i32>, %b: vector<4 x i32>) -> vector<4 x i32> { + // CHECK: call <4 x i32> @llvm.scmp.v4i32.v4i32 + %0 = llvm.intr.scmp(%a, %b) : (vector<4 x i32>, vector<4 x i32>) -> vector<4 x i32> + llvm.return %0 : vector<4 x i32> +} + // Check that intrinsics are declared with appropriate types. // CHECK-DAG: declare float @llvm.fma.f32(float, float, float) // CHECK-DAG: declare <8 x float> @llvm.fma.v8f32(<8 x float>, <8 x float>, <8 x float>) #0 @@ -1464,3 +1492,7 @@ llvm.func @experimental_constrained_fpext(%s: f32, %v: vector<4xf32>) { // CHECK-DAG: declare <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f32(<4 x float>, metadata, metadata) // CHECK-DAG: declare double @llvm.experimental.constrained.fpext.f64.f32(float, metadata) // CHECK-DAG: declare <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f32(<4 x float>, metadata) +// CHECK-DAG: declare range(i2 -1, -2) i2 @llvm.ucmp.i2.i32(i32, i32) +// CHECK-DAG: declare range(i32 -1, 2) <4 x i32> @llvm.ucmp.v4i32.v4i32(<4 x i32>, <4 x i32>) +// CHECK-DAG: declare range(i2 -1, -2) i2 @llvm.scmp.i2.i32(i32, i32) +// CHECK-DAG: declare range(i32 -1, 2) <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32>, <4 x i32>)