|
12 | 12 | #include <utility> |
13 | 13 | #include <vector> |
14 | 14 |
|
| 15 | +#include "lib/Dialect/Kernel/IR/KernelOps.h" |
15 | 16 | #include "lib/Dialect/ModuleAttributes.h" |
16 | 17 | #include "lib/Dialect/Secret/IR/SecretAttributes.h" |
17 | 18 | #include "lib/Dialect/Secret/IR/SecretDialect.h" |
|
26 | 27 | #include "lib/Kernel/KernelImplementation.h" |
27 | 28 | #include "lib/Kernel/KernelName.h" |
28 | 29 | #include "lib/Kernel/Utils.h" |
| 30 | +#include "lib/Target/CompilationTarget/CompilationTarget.h" |
29 | 31 | #include "lib/Transforms/ConvertToCiphertextSemantics/AssignLayout.h" |
30 | 32 | #include "lib/Transforms/ConvertToCiphertextSemantics/TypeConversion.h" |
31 | 33 | #include "lib/Transforms/DropUnitDims/DropUnitDims.h" |
@@ -895,6 +897,125 @@ struct ConvertLinalgMatvecLayout : public ConversionBase<linalg::MatvecOp> { |
895 | 897 | bool unrollKernels; |
896 | 898 | }; |
897 | 899 |
|
| 900 | +struct PreserveLinalgMatvecAsLinearTransform |
| 901 | + : public ConversionBase<linalg::MatvecOp> { |
| 902 | + public: |
| 903 | + using ConversionBase<linalg::MatvecOp>::ConversionBase; |
| 904 | + |
| 905 | + PreserveLinalgMatvecAsLinearTransform( |
| 906 | + const ContextAwareTypeConverter& typeConverter, MLIRContext* context) |
| 907 | + : ConversionBase<linalg::MatvecOp>(typeConverter, context, |
| 908 | + /*benefit=*/20) {} |
| 909 | + |
| 910 | + LogicalResult matchAndRewrite( |
| 911 | + linalg::MatvecOp op, OpAdaptor adaptor, |
| 912 | + ContextAwareConversionPatternRewriter& rewriter) const final { |
| 913 | + auto target = getTargetConfig(op->getParentOfType<ModuleOp>()); |
| 914 | + if (failed(target) || !target->has_kernel_linear_transform) { |
| 915 | + return rewriter.notifyMatchFailure(op, "linear transform not enabled"); |
| 916 | + } |
| 917 | + |
| 918 | + Value matrixOperand = op.getInputs()[0]; |
| 919 | + LayoutAttr matrixLayout = getLayoutAttr(matrixOperand); |
| 920 | + if (!matrixLayout) { |
| 921 | + return rewriter.notifyMatchFailure(op, "missing layout for matrix"); |
| 922 | + } |
| 923 | + |
| 924 | + Value matrix = matrixOperand; |
| 925 | + if (auto assignLayoutOp = |
| 926 | + matrix.getDefiningOp<tensor_ext::AssignLayoutOp>()) { |
| 927 | + matrix = assignLayoutOp.getValue(); |
| 928 | + } |
| 929 | + auto constantMatrixOp = matrix.getDefiningOp<arith::ConstantOp>(); |
| 930 | + if (!constantMatrixOp) { |
| 931 | + return rewriter.notifyMatchFailure(op, "matrix is not a constant"); |
| 932 | + } |
| 933 | + auto denseAttr = dyn_cast<DenseElementsAttr>(constantMatrixOp.getValue()); |
| 934 | + if (!denseAttr) { |
| 935 | + return rewriter.notifyMatchFailure(op, |
| 936 | + "matrix is not a DenseElementsAttr"); |
| 937 | + } |
| 938 | + |
| 939 | + auto matrixType = cast<RankedTensorType>(matrix.getType()); |
| 940 | + auto convertedMatrixType = cast<ShapedType>( |
| 941 | + getTypeConverter()->convertType(matrixType, matrixLayout)); |
| 942 | + if (!convertedMatrixType) { |
| 943 | + return rewriter.notifyMatchFailure(op, "failed to convert matrix type"); |
| 944 | + } |
| 945 | + |
| 946 | + int64_t numDiagonals = convertedMatrixType.getShape()[0]; |
| 947 | + int64_t slots = convertedMatrixType.getShape()[1]; |
| 948 | + auto elementType = matrixType.getElementType(); |
| 949 | + |
| 950 | + Attribute zeroAttr = rewriter.getZeroAttr(elementType); |
| 951 | + std::vector<Attribute> diagonalValues(numDiagonals * slots, zeroAttr); |
| 952 | + |
| 953 | + auto matrixRelation = matrixLayout.getIntegerRelation(); |
| 954 | + PointPairCollector collector(2, 2); |
| 955 | + enumeratePoints(matrixRelation, collector); |
| 956 | + |
| 957 | + int64_t numCols = matrixType.getDimSize(1); |
| 958 | + for (const auto& pointPair : collector.points) { |
| 959 | + int64_t row = pointPair.first[0]; |
| 960 | + int64_t col = pointPair.first[1]; |
| 961 | + int64_t d = pointPair.second[0]; |
| 962 | + int64_t s = pointPair.second[1]; |
| 963 | + |
| 964 | + int64_t flatIndex = row * numCols + col; |
| 965 | + Attribute val = denseAttr.getValues<Attribute>()[flatIndex]; |
| 966 | + diagonalValues[d * slots + s] = val; |
| 967 | + } |
| 968 | + |
| 969 | + std::vector<int64_t> nonZeroDiagonalIndices; |
| 970 | + std::vector<Attribute> nonZeroDiagonalValues; |
| 971 | + for (int64_t d = 0; d < numDiagonals; ++d) { |
| 972 | + bool isZero = true; |
| 973 | + for (int64_t s = 0; s < slots; ++s) { |
| 974 | + if (diagonalValues[d * slots + s] != zeroAttr) { |
| 975 | + isZero = false; |
| 976 | + break; |
| 977 | + } |
| 978 | + } |
| 979 | + if (!isZero) { |
| 980 | + nonZeroDiagonalIndices.push_back(d); |
| 981 | + for (int64_t s = 0; s < slots; ++s) { |
| 982 | + nonZeroDiagonalValues.push_back(diagonalValues[d * slots + s]); |
| 983 | + } |
| 984 | + } |
| 985 | + } |
| 986 | + |
| 987 | + auto diagonalsType = RankedTensorType::get( |
| 988 | + {static_cast<int64_t>(nonZeroDiagonalIndices.size()), slots}, |
| 989 | + elementType); |
| 990 | + auto diagonalsAttr = |
| 991 | + DenseElementsAttr::get(diagonalsType, nonZeroDiagonalValues); |
| 992 | + auto diagonalIndicesAttr = |
| 993 | + rewriter.getDenseI64ArrayAttr(nonZeroDiagonalIndices); |
| 994 | + |
| 995 | + auto resultLayout = findAttributeAssociatedWith( |
| 996 | + op.getResult(0), tensor_ext::TensorExtDialect::kLayoutAttrName); |
| 997 | + if (failed(resultLayout)) { |
| 998 | + return rewriter.notifyMatchFailure(op, "missing output layout"); |
| 999 | + } |
| 1000 | + |
| 1001 | + auto outputType = op.getResult(0).getType(); |
| 1002 | + auto convertedOutputType = |
| 1003 | + getTypeConverter()->convertType(outputType, resultLayout.value()); |
| 1004 | + |
| 1005 | + rewriter.setInsertionPointAfter(op); |
| 1006 | + auto linearTransformOp = rewriter.create<kernel::LinearTransformOp>( |
| 1007 | + op.getLoc(), convertedOutputType, adaptor.getInputs()[1], diagonalsAttr, |
| 1008 | + diagonalIndicesAttr, /*bsgs_ratio=*/nullptr); |
| 1009 | + |
| 1010 | + setMaterializedAttr(linearTransformOp); |
| 1011 | + linearTransformOp->setAttr(kLayoutAttrName, resultLayout.value()); |
| 1012 | + |
| 1013 | + addBiasAndReplace(rewriter, op, linearTransformOp.getResult(), |
| 1014 | + adaptor.getOutputs()[0], resultLayout.value()); |
| 1015 | + return success(); |
| 1016 | + } |
| 1017 | +}; |
| 1018 | + |
898 | 1019 | struct ConvertLinalgConv1D : public ConversionBase<linalg::Conv1DOp> { |
899 | 1020 | public: |
900 | 1021 | using ConversionBase<linalg::Conv1DOp>::ConversionBase; |
@@ -2761,13 +2882,14 @@ struct ConvertToCiphertextSemantics |
2761 | 2882 | return isa<ModuleOp>(op) || hasMaterializedAttr(op); |
2762 | 2883 | }); |
2763 | 2884 |
|
2764 | | - patterns.add<ConvertAnyAddingMaterializedAttr, ConvertConvertLayout, |
2765 | | - ConvertFunc, ConvertLinalgMatmul, ConvertLinalgBatchMatmul, |
2766 | | - ConvertLinalgReduce, ConvertLinalgDot, ConvertSecretGeneric, |
2767 | | - ConvertTensorCollapseShape, ConvertTensorExpandShape, |
2768 | | - ConvertTensorExtractLayout, ConvertTensorExtractSlice, |
2769 | | - ConvertTensorPad, ConvertTensorInsertLayout, |
2770 | | - ConvertTensorInsertSlice>(typeConverter, context); |
| 2885 | + patterns.add< |
| 2886 | + ConvertAnyAddingMaterializedAttr, ConvertConvertLayout, ConvertFunc, |
| 2887 | + ConvertLinalgMatmul, ConvertLinalgBatchMatmul, ConvertLinalgReduce, |
| 2888 | + ConvertLinalgDot, ConvertSecretGeneric, ConvertTensorCollapseShape, |
| 2889 | + ConvertTensorExpandShape, ConvertTensorExtractLayout, |
| 2890 | + ConvertTensorExtractSlice, ConvertTensorPad, ConvertTensorInsertLayout, |
| 2891 | + ConvertTensorInsertSlice, PreserveLinalgMatvecAsLinearTransform>( |
| 2892 | + typeConverter, context); |
2771 | 2893 | patterns.add<ConvertLinalgMatvecLayout, ConvertLinalgConv1D, |
2772 | 2894 | ConvertLinalgConv2D, ConvertLinalgConv2DNchwFchw, |
2773 | 2895 | ConvertLinalgConv1DNcwFcw>(typeConverter, context, |
|
0 commit comments