llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Chi-Chun, Chen (chichunchen) <details> <summary>Changes</summary> --- Patch is 41.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/185333.diff 7 Files Affected: - (modified) clang/lib/CodeGen/CGOpenMPRuntime.cpp (+35-141) - (modified) llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h (+86) - (modified) llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp (+155) - (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+25-28) - (modified) mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp (+173) - (added) mlir/test/Target/LLVMIR/openmp-declare-simd-aarch64.mlir (+19) - (added) mlir/test/Target/LLVMIR/openmp-declare-simd-x86.mlir (+213) ``````````diff diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 09cc8c25538e2..c0727194a4607 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11828,27 +11828,8 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( } } -namespace { - /// Kind of parameter in a function with 'declare simd' directive. -enum ParamKindTy { - Linear, - LinearRef, - LinearUVal, - LinearVal, - Uniform, - Vector, -}; -/// Attribute set of the parameter. -struct ParamAttrTy { - ParamKindTy Kind = Vector; - llvm::APSInt StrideOrArg; - llvm::APSInt Alignment; - bool HasVarStride = false; -}; -} // namespace - static unsigned evaluateCDTSize(const FunctionDecl *FD, - ArrayRef<ParamAttrTy> ParamAttrs) { + ArrayRef<llvm::DeclareSimdAttrTy> ParamAttrs) { // Every vector variant of a SIMD-enabled function has a vector length (VLEN). // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument // of that clause. The VLEN value must be power of 2. @@ -11878,13 +11859,13 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD, } else { unsigned Offset = 0; if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { - if (ParamAttrs[Offset].Kind == Vector) + if (ParamAttrs[Offset].Kind == llvm::DeclareSimdKindTy::Vector) CDT = C.getPointerType(C.getCanonicalTagType(MD->getParent())); ++Offset; } if (CDT.isNull()) { for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { - if (ParamAttrs[I + Offset].Kind == Vector) { + if (ParamAttrs[I + Offset].Kind == llvm::DeclareSimdKindTy::Vector) { CDT = FD->getParamDecl(I)->getType(); break; } @@ -11899,107 +11880,6 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD, return C.getTypeSize(CDT); } -/// Mangle the parameter part of the vector function name according to -/// their OpenMP classification. The mangling function is defined in -/// section 4.5 of the AAVFABI(2021Q1). -static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - for (const auto &ParamAttr : ParamAttrs) { - switch (ParamAttr.Kind) { - case Linear: - Out << 'l'; - break; - case LinearRef: - Out << 'R'; - break; - case LinearUVal: - Out << 'U'; - break; - case LinearVal: - Out << 'L'; - break; - case Uniform: - Out << 'u'; - break; - case Vector: - Out << 'v'; - break; - } - if (ParamAttr.HasVarStride) - Out << "s" << ParamAttr.StrideOrArg; - else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef || - ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) { - // Don't print the step value if it is not present or if it is - // equal to 1. - if (ParamAttr.StrideOrArg < 0) - Out << 'n' << -ParamAttr.StrideOrArg; - else if (ParamAttr.StrideOrArg != 1) - Out << ParamAttr.StrideOrArg; - } - - if (!!ParamAttr.Alignment) - Out << 'a' << ParamAttr.Alignment; - } - - return std::string(Out.str()); -} - -static void -emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, - const llvm::APSInt &VLENVal, - ArrayRef<ParamAttrTy> ParamAttrs, - OMPDeclareSimdDeclAttr::BranchStateTy State) { - struct ISADataTy { - char ISA; - unsigned VecRegSize; - }; - ISADataTy ISAData[] = { - { - 'b', 128 - }, // SSE - { - 'c', 256 - }, // AVX - { - 'd', 256 - }, // AVX2 - { - 'e', 512 - }, // AVX512 - }; - llvm::SmallVector<char, 2> Masked; - switch (State) { - case OMPDeclareSimdDeclAttr::BS_Undefined: - Masked.push_back('N'); - Masked.push_back('M'); - break; - case OMPDeclareSimdDeclAttr::BS_Notinbranch: - Masked.push_back('N'); - break; - case OMPDeclareSimdDeclAttr::BS_Inbranch: - Masked.push_back('M'); - break; - } - for (char Mask : Masked) { - for (const ISADataTy &Data : ISAData) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - Out << "_ZGV" << Data.ISA << Mask; - if (!VLENVal) { - unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); - assert(NumElts && "Non-zero simdlen/cdtsize expected"); - Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); - } else { - Out << VLENVal; - } - Out << mangleVectorParameters(ParamAttrs); - Out << '_' << Fn->getName(); - Fn->addFnAttr(Out.str()); - } - } -} - // This are the Functions that are needed to mangle the name of the // vector functions generated by the compiler, according to the rules // defined in the "Vector Function ABI specifications for AArch64", @@ -12007,19 +11887,21 @@ emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. /// Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1). -static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { +static bool getAArch64MTV(QualType QT, llvm::DeclareSimdKindTy Kind) { QT = QT.getCanonicalType(); if (QT->isVoidType()) return false; - if (Kind == ParamKindTy::Uniform) + if (Kind == llvm::DeclareSimdKindTy::Uniform) return false; - if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef) + if (Kind == llvm::DeclareSimdKindTy::LinearUVal || + Kind == llvm::DeclareSimdKindTy::LinearRef) return false; - if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) && + if ((Kind == llvm::DeclareSimdKindTy::Linear || + Kind == llvm::DeclareSimdKindTy::LinearVal) && !QT->isReferenceType()) return false; @@ -12052,7 +11934,8 @@ static bool getAArch64PBV(QualType QT, ASTContext &C) { /// Computes the lane size (LS) of a return type or of an input parameter, /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. /// TODO: Add support for references, section 3.2.1, item 1. -static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { +static unsigned getAArch64LS(QualType QT, llvm::DeclareSimdKindTy Kind, + ASTContext &C) { if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { QualType PTy = QT.getCanonicalType()->getPointeeType(); if (getAArch64PBV(PTy, C)) @@ -12068,7 +11951,8 @@ static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { // signature of the scalar function, as defined in 3.2.2 of the // AAVFABI. static std::tuple<unsigned, unsigned, bool> -getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { +getNDSWDS(const FunctionDecl *FD, + ArrayRef<llvm::DeclareSimdAttrTy> ParamAttrs) { QualType RetType = FD->getReturnType().getCanonicalType(); ASTContext &C = FD->getASTContext(); @@ -12077,7 +11961,7 @@ getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { llvm::SmallVector<unsigned, 8> Sizes; if (!RetType->isVoidType()) { - Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); + Sizes.push_back(getAArch64LS(RetType, llvm::DeclareSimdKindTy::Vector, C)); if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) OutputBecomesInput = true; } @@ -12156,7 +12040,7 @@ static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, /// Emit vector function attributes for AArch64, as defined in the AAVFABI. static void emitAArch64DeclareSimdFunction( CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, - ArrayRef<ParamAttrTy> ParamAttrs, + ArrayRef<llvm::DeclareSimdAttrTy> ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { @@ -12189,8 +12073,10 @@ static void emitAArch64DeclareSimdFunction( } } + llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); + // Sort out parameter sequence. - const std::string ParSeq = mangleVectorParameters(ParamAttrs); + const std::string ParSeq = OMPBuilder.mangleVectorParameters(ParamAttrs); StringRef Prefix = "_ZGV"; // Generate simdlen from user input (if any). if (UserVLEN) { @@ -12266,7 +12152,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, ++ParamPos; } for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { - llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); + llvm::SmallVector<llvm::DeclareSimdAttrTy, 8> ParamAttrs( + ParamPositions.size()); // Mark uniform parameters. for (const Expr *E : Attr->uniforms()) { E = E->IgnoreParenImpCasts(); @@ -12280,7 +12167,7 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, assert(It != ParamPositions.end() && "Function parameter not found"); Pos = It->second; } - ParamAttrs[Pos].Kind = Uniform; + ParamAttrs[Pos].Kind = llvm::DeclareSimdKindTy::Uniform; } // Get alignment info. auto *NI = Attr->alignments_begin(); @@ -12341,15 +12228,15 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, .getQuantity(); } } - ParamAttrTy &ParamAttr = ParamAttrs[Pos]; + llvm::DeclareSimdAttrTy &ParamAttr = ParamAttrs[Pos]; if (*MI == OMPC_LINEAR_ref) - ParamAttr.Kind = LinearRef; + ParamAttr.Kind = llvm::DeclareSimdKindTy::LinearRef; else if (*MI == OMPC_LINEAR_uval) - ParamAttr.Kind = LinearUVal; + ParamAttr.Kind = llvm::DeclareSimdKindTy::LinearUVal; else if (IsReferenceType) - ParamAttr.Kind = LinearVal; + ParamAttr.Kind = llvm::DeclareSimdKindTy::LinearVal; else - ParamAttr.Kind = Linear; + ParamAttr.Kind = llvm::DeclareSimdKindTy::Linear; // Assuming a stride of 1, for `linear` without modifiers. ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); if (*SI) { @@ -12374,7 +12261,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, // rescale the value of linear_step with the byte size of the // pointee type. if (!ParamAttr.HasVarStride && - (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef)) + (ParamAttr.Kind == llvm::DeclareSimdKindTy::Linear || + ParamAttr.Kind == llvm::DeclareSimdKindTy::LinearRef)) ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; ++SI; ++MI; @@ -12387,8 +12275,14 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, ExprLoc = VLENExpr->getExprLoc(); } OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); + llvm::OpenMPIRBuilder &OMPBuilder = + CGM.getOpenMPRuntime().getOMPBuilder(); if (CGM.getTriple().isX86()) { - emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); + unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); + assert(NumElts && "Non-zero simdlen/cdtsize expected"); + OMPBuilder.emitX86DeclareSimdFunction( + Fn, NumElts, VLENVal, ParamAttrs, + static_cast<llvm::DeclareSimdBranch>(State)); } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { unsigned VLEN = VLENVal.getExtValue(); StringRef MangledName = Fn->getName(); diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index 9885ffc8b2065..266e19058998d 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -14,6 +14,7 @@ #ifndef LLVM_FRONTEND_OPENMP_OMPIRBUILDER_H #define LLVM_FRONTEND_OPENMP_OMPIRBUILDER_H +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/SetVector.h" #include "llvm/Frontend/Atomic/Atomic.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -498,6 +499,31 @@ class OffloadEntriesInfoManager { OffloadEntriesDeviceGlobalVarTy OffloadEntriesDeviceGlobalVar; }; +/// Kind of parameter in a function with 'declare simd' directive. +enum class DeclareSimdKindTy { + Linear, + LinearRef, + LinearUVal, + LinearVal, + Uniform, + Vector, +}; + +/// Attribute set of the `declare simd` parameter. +struct DeclareSimdAttrTy { + DeclareSimdKindTy Kind = DeclareSimdKindTy::Vector; + llvm::APSInt StrideOrArg; + llvm::APSInt Alignment; + bool HasVarStride = false; +}; + +/// Type of branch clause of the `declare simd` directive. +enum class DeclareSimdBranch { + Undefined, + Inbranch, + Notinbranch, +}; + /// An interface to create LLVM-IR for OpenMP directives. /// /// Each OpenMP directive has a corresponding public generator method. @@ -1484,6 +1510,66 @@ class OpenMPIRBuilder { Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen); + /// Mangle the parameter portion of a vector function name according to the + /// OpenMP declare simd rules. + /// + /// The mangling follows the Vector Function ABI (AAVFABI) specification and + /// encodes, for each function parameter, its OpenMP classification + /// (vector, uniform, linear, etc.), optional linear step information, and + /// optional alignment. + /// + /// This helper produces only the parameter-encoding suffix; the caller is + /// responsible for adding ISA, masking, VLEN, and the base function name. + /// + /// \param ParamAttrs A list of per-parameter attributes describing how each + /// argument participates in SIMD execution. + /// + /// \returns A string encoding the parameter attributes suitable for inclusion + /// in a vector function name. + LLVM_ABI std::string + mangleVectorParameters(llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs); + + /// Emit x86-specific vector function attributes for an OpenMP `declare simd` + /// directive. + /// + /// This function attaches one or more mangled vector-function-name attributes + /// to the given LLVM function, following the x86 Vector Function ABI. + /// + /// Depending on the branch clause, masked and/or unmasked variants are + /// emitted. The vector length is either taken from the explicit `simdlen` + /// clause or derived from the characteristic data type (CDT). + /// + /// \param Fn The LLVM function corresponding to the scalar version. + /// \param NumElements The number of SIMD lanes derived from the target ISA. + /// \param VLENVal Optional explicit SIMD length from the `simdlen` + /// clause. + /// \param ParamAttrs Per-parameter SIMD attributes (uniform, linear, etc.). + /// \param Branch The branch behavior specified by the `inbranch` or + /// `notinbranch` clause. + LLVM_ABI void emitX86DeclareSimdFunction( + llvm::Function *Fn, unsigned NumElements, const llvm::APSInt &VLENVal, + llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs, DeclareSimdBranch Branch); + + /// Emit vector function attributes for an OpenMP `declare simd` directive. + /// + /// This is the target-independent entry point used by frontends and IR + /// translation layers. It dispatches to a target-specific implementation + /// based on the module target triple. + /// + /// If the target does not support `declare simd` lowering, this function + /// reports an error and performs no emission. + /// + /// \param Fn The LLVM function corresponding to the scalar version. + /// \param VLENVal Optional explicit SIMD length from the `simdlen` + /// clause. + /// \param ParamAttrs Per-parameter SIMD attributes (uniform, linear, etc.). + /// \param Branch The branch behavior specified by the `inbranch` or + /// `notinbranch` clause. + LLVM_ABI void + emitDeclareSimdFunction(llvm::Function *Fn, const llvm::APSInt &VLENVal, + llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs, + llvm::DeclareSimdBranch Branch); + /// Generator for '#omp flush' /// /// \param Loc The location where the flush directive was encountered diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index 1d522e9b14c7a..b96e991a999a4 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -6956,6 +6956,161 @@ void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop, addLoopMetadata(CanonicalLoop, LoopMDList); } +/// Return type size in bits for `Ty` using DL. +/// If scalable, return known-min as a conservative approximation. +static unsigned getTypeSizeInBits(llvm::Type *Ty, const llvm::DataLayout &DL) { + if (!Ty) + return 0; + llvm::TypeSize TS = DL.getTypeSizeInBits(Ty); + + if (TS.isScalable()) + return (unsigned)TS.getKnownMinValue(); + return (unsigned)TS.getFixedValue(); +} + +/// Returns size in *bits* of the Characteristic Data Type (CDT). +static unsigned evaluateCDTSize(const llvm::Function *Fn, + llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs) { + const llvm::DataLayout &DL = Fn->getParent()->getDataLayout(); + + llvm::Type *RetTy = Fn->getReturnType(); + llvm::Type *CDT = nullptr; + + // Non-void return => CDT = return type + if (RetTy && !RetTy->isVoidTy()) { + CDT = RetTy; + } else { + // First "Vector" param (ParamAttrs aligned with function params) + // If ParamAttrs is shorter than the parameter list, treat missing as Vector + // (matches the idea "default Kind is Vector"). + unsigned NumParams = Fn->getFunctionType()->getNumParams(); + for (unsigned I = 0; I < NumParams; ++I) { + bool IsVector = (I < ParamAttrs.size()) + ? ParamAttrs[I].Kind == DeclareSimdKindTy::Vector + : true; + if (!IsVector) + continue; + CDT = Fn->getFunctionType()->getParamType(I); + break; + } + } + + llvm::Type *IntTy = llvm::Type::getInt32Ty(Fn->getContext()); + if (!CDT || CDT->isStructTy() || CDT->isArrayTy()) + CDT = IntTy; + + return getTypeSizeInBits(CDT, DL); +} + +/// Mangle the parameter part of the vector function name according to +/// their OpenMP classification. The mangling function is defined in +/// section 4.5 of the AAVFABI(2021Q1). +std::string OpenMPIRBuilder::mangleVectorParameters( + llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs) { + llvm::SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + for (const auto &ParamAttr : ParamAttrs) { + switch (ParamAttr.Kind) { + case llvm::DeclareSimdKindTy::Linear: + Out << 'l'; + break; + case llvm::DeclareSimdKindTy::LinearRef: + Out << 'R'; + break; + case llvm::DeclareSimdKindTy::LinearUVal: + Out << 'U'; + break; + case llvm::DeclareSimdKindTy::LinearVal: + Out << 'L'; + break; + case llvm::DeclareSimdKindTy::Uniform: + Out << 'u'; + break; + case llvm::DeclareSimdKindTy::Vector: + Out << 'v'; + break; + } + if (ParamAttr.HasVarStride) + Out << "s" << ParamAttr.StrideOrArg; + else if (ParamAttr.Kind == llvm::DeclareSimdKindTy::Linear || + ParamAttr.Kind == llvm::DeclareSimdKindTy::LinearRef || + ParamAttr.Kind == llvm::DeclareSimdKindTy::LinearUVal || + ParamAttr.Kind == llvm::DeclareSimdKindTy::LinearVal) { + // Don't print the step value if it is not present or if it is + // equal to 1. + if (ParamAttr.StrideOrArg < 0) + Out << 'n' << -ParamAttr.StrideOrArg; + else if (ParamAttr.StrideOrArg != 1) + Out << ParamAttr.StrideOrArg; + } + + if (!!ParamAttr.Alignment) + Out << 'a' << ParamAttr.Alignment; + } + + return std::string(Out.str()); +} + +void OpenMPIRBuilder::emitX86DeclareSimdFunction( + llvm::Function *Fn, unsigned NumElts, const llvm::APSInt &VLENVal, + llvm::ArrayRef<DeclareSimdAttrTy> ParamAttrs, DeclareSimdBranch Branch) { + struct ISA... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/185333 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
