@@ -61,6 +61,13 @@ class Scalable1DVectorOfLength<int length, list<Type> elementTypes> : ShapedCont
6161 "a 1-D scalable vector with length " # length,
6262 "::mlir::VectorType">;
6363
64+ def SVEVector : AnyTypeOf<[
65+ Scalable1DVectorOfLength<2, [I64, F64]>,
66+ Scalable1DVectorOfLength<4, [I32, F32]>,
67+ Scalable1DVectorOfLength<8, [I16, F16, BF16]>,
68+ Scalable1DVectorOfLength<16, [I8]>],
69+ "an SVE vector with element size <= 64-bit">;
70+
6471//===----------------------------------------------------------------------===//
6572// ArmSVE op definitions
6673//===----------------------------------------------------------------------===//
@@ -72,14 +79,22 @@ class ArmSVE_IntrOp<string mnemonic,
7279 list<Trait> traits = [],
7380 list<int> overloadedOperands = [],
7481 list<int> overloadedResults = [],
75- int numResults = 1> :
82+ int numResults = 1,
83+ list<int> immArgPositions = [],
84+ list<string> immArgAttrNames = []> :
7685 LLVM_IntrOpBase</*Dialect dialect=*/ArmSVE_Dialect,
7786 /*string opName=*/"intr." # mnemonic,
7887 /*string enumName=*/"aarch64_sve_" # !subst(".", "_", mnemonic),
7988 /*list<int> overloadedResults=*/overloadedResults,
8089 /*list<int> overloadedOperands=*/overloadedOperands,
8190 /*list<Trait> traits=*/traits,
82- /*int numResults=*/numResults>;
91+ /*int numResults=*/numResults,
92+ /*bit requiresAccessGroup=*/0,
93+ /*bit requiresAliasAnalysis=*/0,
94+ /*bit requiresFastmath=*/0,
95+ /*bit requiresOpBundles=*/0,
96+ /*list<int> immArgPositions=*/immArgPositions,
97+ /*list<string> immArgAttrNames=*/immArgAttrNames>;
8398
8499class ArmSVE_IntrBinaryOverloadedOp<string mnemonic,
85100 list<Trait> traits = []>:
@@ -509,6 +524,42 @@ def ScalableMaskedUDivIOp : ScalableMaskedIOp<"masked.divi_unsigned",
509524
510525def ScalableMaskedDivFOp : ScalableMaskedFOp<"masked.divf", "division">;
511526
527+ def DupQLaneOp : ArmSVE_Op<"dupq_lane", [Pure, AllTypesMatch<["src", "dst"]>]> {
528+ let summary = "Broadcast indexed 128-bit segment to vector";
529+
530+ let description = [{
531+ This operation fills each 128-bit segment of a vector with the elements
532+ from the indexed 128-bit segment of the source vector. If the VL is
533+ 128 bits the operation is a NOP. If the index exceeds the number of
534+ 128-bit segments in a vector the result is an all-zeroes vector.
535+
536+ Example:
537+ ```mlir
538+ // VL == 256
539+ // %X = [A B C D x x x x]
540+ %Y = arm_sve.dupq_lane %X[0] : vector<[4]xi32>
541+ // Y = [A B C D A B C D]
542+
543+ // %U = [x x x x x x x x A B C D E F G H]
544+ %V = arm_sve.dupq_lane %U[1] : vector<[8]xf16>
545+ // %V = [A B C D E F H A B C D E F H]
546+ ```
547+ }];
548+
549+ let arguments = (ins SVEVector:$src,
550+ I64Attr:$lane);
551+ let results = (outs SVEVector:$dst);
552+
553+ let builders = [
554+ OpBuilder<(ins "Value":$src, "int64_t":$lane), [{
555+ build($_builder, $_state, src.getType(), src, lane);
556+ }]>];
557+
558+ let assemblyFormat = [{
559+ $src `[` $lane `]` attr-dict `:` type($dst)
560+ }];
561+ }
562+
512563def UmmlaIntrOp :
513564 ArmSVE_IntrBinaryOverloadedOp<"ummla">,
514565 Arguments<(ins AnyScalableVectorOfAnyRank, AnyScalableVectorOfAnyRank, AnyScalableVectorOfAnyRank)>;
@@ -610,4 +661,14 @@ def WhileLTIntrOp :
610661 /*overloadedResults=*/[0]>,
611662 Arguments<(ins I64:$base, I64:$n)>;
612663
664+ def DupQLaneIntrOp : ArmSVE_IntrOp<"dupq_lane",
665+ /*traits=*/[],
666+ /*overloadedOperands=*/[0],
667+ /*overloadedResults=*/[],
668+ /*numResults=*/1,
669+ /*immArgPositions*/[1],
670+ /*immArgAttrNames*/["lane"]>,
671+ Arguments<(ins Arg<ScalableVectorOfRank<[1]>, "v">:$v,
672+ Arg<I64Attr, "lane">:$lane)>;
673+
613674#endif // ARMSVE_OPS
0 commit comments