diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -408,6 +408,36 @@ let assemblyFormat = "attr-dict `:` type($res)"; } +/// Create a call to vector.insert intrinsic +def LLVM_vector_insert + : LLVM_Op<"intr.experimental.vector.insert", + [NoSideEffect, AllTypesMatch<["dstvec", "res"]>]> { + let arguments = (ins LLVM_AnyFixedVector:$srcvec, LLVM_AnyVector:$dstvec, + I64Attr:$pos); + let results = (outs LLVM_AnyVector:$res); + let builders = [LLVM_OneResultOpBuilder]; + string llvmBuilder = [{ + $res = builder.CreateInsertVector( + $_resultType, $dstvec, $srcvec, builder.getInt64($pos)); + }]; + let assemblyFormat = "$srcvec `,` $dstvec `[` $pos `]` attr-dict `:` " + "type($srcvec) `into` type($res)"; +} + +/// Create a call to vector.extract intrinsic +def LLVM_vector_extract + : LLVM_Op<"intr.experimental.vector.extract", [NoSideEffect]> { + let arguments = (ins LLVM_AnyVector:$srcvec, I64Attr:$pos); + let results = (outs LLVM_AnyFixedVector:$res); + let builders = [LLVM_OneResultOpBuilder]; + string llvmBuilder = [{ + $res = builder.CreateExtractVector( + $_resultType, $srcvec, builder.getInt64($pos)); + }]; + let assemblyFormat = "$srcvec `[` $pos `]` attr-dict `:` " + "type($res) `from` type($srcvec)"; +} + // // LLVM Vector Predication operations. // diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -157,6 +157,16 @@ def LLVM_AnyVector : Type, "LLVM dialect-compatible vector type">; +// Type constraint accepting any LLVM fixed-length vector type. +def LLVM_AnyFixedVector : Type, + "LLVM dialect-compatible fixed-length vector type">; + +// Type constraint accepting any LLVM scalable vector type. +def LLVM_AnyScalableVector : Type, + "LLVM dialect-compatible scalable vector type">; + // Type constraint accepting an LLVM vector type with an additional constraint // on the vector element type. class LLVM_VectorOf : Type< diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -297,6 +297,23 @@ return } +// CHECK-LABEL: @mixed_vect +func.func @mixed_vect(%arg0: vector<8xf32>, %arg1: vector<4xf32>, %arg2: vector<[4]xf32>) { + // CHECK: = llvm.intr.experimental.vector.insert {{.*}} : vector<8xf32> into vector<[4]xf32> + %0 = llvm.intr.experimental.vector.insert %arg0, %arg2[0] : vector<8xf32> into vector<[4]xf32> + // CHECK: = llvm.intr.experimental.vector.insert {{.*}} : vector<4xf32> into vector<[4]xf32> + %1 = llvm.intr.experimental.vector.insert %arg1, %arg2[0] : vector<4xf32> into vector<[4]xf32> + // CHECK: = llvm.intr.experimental.vector.insert {{.*}} : vector<4xf32> into vector<[4]xf32> + %2 = llvm.intr.experimental.vector.insert %arg1, %1[4] : vector<4xf32> into vector<[4]xf32> + // CHECK: = llvm.intr.experimental.vector.insert {{.*}} : vector<4xf32> into vector<8xf32> + %3 = llvm.intr.experimental.vector.insert %arg1, %arg0[4] : vector<4xf32> into vector<8xf32> + // CHECK: = llvm.intr.experimental.vector.extract {{.*}} : vector<8xf32> from vector<[4]xf32> + %4 = llvm.intr.experimental.vector.extract %2[0] : vector<8xf32> from vector<[4]xf32> + // CHECK: = llvm.intr.experimental.vector.extract {{.*}} : vector<2xf32> from vector<8xf32> + %5 = llvm.intr.experimental.vector.extract %arg0[6] : vector<2xf32> from vector<8xf32> + return +} + // CHECK-LABEL: @alloca func.func @alloca(%size : i64) { // CHECK: llvm.alloca %{{.*}} x i32 : (i64) -> !llvm.ptr diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -680,6 +680,33 @@ llvm.return } +// CHECK-LABEL: @vector_insert_extract +llvm.func @vector_insert_extract(%f256: vector<8xi32>, %f128: vector<4xi32>, + %sv: vector<[4]xi32>) { + // CHECK: call @llvm.experimental.vector.insert.nxv4i32.v8i32 + %0 = llvm.intr.experimental.vector.insert %f256, %sv[0] : + vector<8xi32> into vector<[4]xi32> + // CHECK: call @llvm.experimental.vector.insert.nxv4i32.v4i32 + %1 = llvm.intr.experimental.vector.insert %f128, %sv[0] : + vector<4xi32> into vector<[4]xi32> + // CHECK: call @llvm.experimental.vector.insert.nxv4i32.v4i32 + %2 = llvm.intr.experimental.vector.insert %f128, %1[4] : + vector<4xi32> into vector<[4]xi32> + // CHECK: call <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32 + %3 = llvm.intr.experimental.vector.insert %f128, %f256[4] : + vector<4xi32> into vector<8xi32> + // CHECK: call <8 x i32> @llvm.experimental.vector.extract.v8i32.nxv4i32 + %4 = llvm.intr.experimental.vector.extract %2[0] : + vector<8xi32> from vector<[4]xi32> + // CHECK: call <4 x i32> @llvm.experimental.vector.extract.v4i32.nxv4i32 + %5 = llvm.intr.experimental.vector.extract %2[0] : + vector<4xi32> from vector<[4]xi32> + // CHECK: call <2 x i32> @llvm.experimental.vector.extract.v2i32.v8i32 + %6 = llvm.intr.experimental.vector.extract %f256[6] : + vector<2xi32> from vector<8xi32> + llvm.return +} + // 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 @@ -781,3 +808,9 @@ // CHECK-DAG: declare <8 x i64> @llvm.vp.fptosi.v8i64.v8f64(<8 x double>, <8 x i1>, i32) #2 // CHECK-DAG: declare <8 x i64> @llvm.vp.ptrtoint.v8i64.v8p0(<8 x ptr>, <8 x i1>, i32) #2 // CHECK-DAG: declare <8 x ptr> @llvm.vp.inttoptr.v8p0.v8i64(<8 x i64>, <8 x i1>, i32) #2 +// CHECK-DAG: declare @llvm.experimental.vector.insert.nxv4i32.v8i32(, <8 x i32>, i64 immarg) #2 +// CHECK-DAG: declare @llvm.experimental.vector.insert.nxv4i32.v4i32(, <4 x i32>, i64 immarg) #2 +// CHECK-DAG: declare <8 x i32> @llvm.experimental.vector.insert.v8i32.v4i32(<8 x i32>, <4 x i32>, i64 immarg) #2 +// CHECK-DAG: declare <8 x i32> @llvm.experimental.vector.extract.v8i32.nxv4i32(, i64 immarg) #2 +// CHECK-DAG: declare <4 x i32> @llvm.experimental.vector.extract.v4i32.nxv4i32(, i64 immarg) #2 +// CHECK-DAG: declare <2 x i32> @llvm.experimental.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) #2