//===- LegalizeForLLVMExport.cpp - Prepare ArmSVE for LLVM translation ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Dialect/ArmSVE/IR/ArmSVEDialect.h" #include "mlir/Dialect/ArmSVE/Transforms/Transforms.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/PatternMatch.h" usingnamespacemlir; usingnamespacemlir::arm_sve; template <typename OpTy> class ForwardOperands : public OpConversionPattern<OpTy> { … }; SdotOpLowering; SmmlaOpLowering; UdotOpLowering; UmmlaOpLowering; ScalableMaskedAddIOpLowering; ScalableMaskedAddFOpLowering; ScalableMaskedSubIOpLowering; ScalableMaskedSubFOpLowering; ScalableMaskedMulIOpLowering; ScalableMaskedMulFOpLowering; ScalableMaskedSDivIOpLowering; ScalableMaskedUDivIOpLowering; ScalableMaskedDivFOpLowering; namespace { /// Unrolls a conversion to/from equivalent vector types, to allow using a /// conversion intrinsic that only supports 1-D vector types. /// /// Example: /// ``` /// %result = arm_sve.convert_to_svbool %source : vector<2x[4]xi1> /// ``` /// is rewritten into: /// ``` /// %cst = arith.constant dense<false> : vector<2x[16]xi1> /// %1 = vector.extract %source[0] : vector<[4]xi1> from vector<2x[4]xi1> /// %2 = "arm_sve.intr.convert.to.svbool"(%1) /// : (vector<[4]xi1>) -> vector<[16]xi1> /// %3 = vector.insert %2, %cst[0] : vector<[16]xi1> into vector<2x[16]xi1> /// %4 = vector.extract %source[1] : vector<[4]xi1> from vector<2x[4]xi1> /// %5 = "arm_sve.intr.convert.to.svbool"(%4) /// : (vector<[4]xi1>) -> vector<[16]xi1> /// %result = vector.insert %5, %3[1] : vector<[16]xi1> into vector<2x[16]xi1> /// ``` template <typename Op, typename IntrOp> struct SvboolConversionOpLowering : public ConvertOpToLLVMPattern<Op> { … }; ConvertToSvboolOpLowering; ConvertFromSvboolOpLowering; ZipX2OpLowering; ZipX4OpLowering; /// Lower `arm_sve.psel` to LLVM intrinsics. This is almost a 1-to-1 conversion /// but first input (P1) and result predicates need conversion to/from svbool. struct PselOpLowering : public ConvertOpToLLVMPattern<PselOp> { … }; /// Converts `vector.create_mask` ops that match the size of an SVE predicate /// to the `whilelt` intrinsic. This produces more canonical codegen than the /// generic LLVM lowering, see https://github.com/llvm/llvm-project/issues/81840 /// for more details. Note that we can't use (the more general) active.lane.mask /// as its semantics don't neatly map on to `vector.create_mask`, as it does an /// unsigned comparison (whereas `create_mask` is signed), and is UB/posion if /// `n` is zero (whereas `create_mask` just returns an all-false mask). struct CreateMaskOpLowering : public ConvertOpToLLVMPattern<vector::CreateMaskOp> { … }; } // namespace /// Populate the given list with patterns that convert from ArmSVE to LLVM. void mlir::populateArmSVELegalizeForLLVMExportPatterns( const LLVMTypeConverter &converter, RewritePatternSet &patterns) { … } void mlir::configureArmSVELegalizeForExportTarget( LLVMConversionTarget &target) { … }