diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -351,24 +351,8 @@ PM.add(createStackSafetyGlobalInfoWrapperPass(/*SetMetadata=*/true)); } -static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, - const CodeGenOptions &CodeGenOpts) { - TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple); - - switch (CodeGenOpts.getVecLib()) { - case CodeGenOptions::Accelerate: - TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate); - break; - case CodeGenOptions::MASSV: - TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::MASSV); - break; - case CodeGenOptions::SVML: - TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML); - break; - default: - break; - } - return TLII; +static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple) { + return new TargetLibraryInfoImpl(TargetTriple); } static void addSymbolRewriterPass(const CodeGenOptions &Opts, @@ -561,8 +545,7 @@ // are inserted before PMBuilder ones - they'd get the default-constructed // TLI with an unknown target otherwise. Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr TLII( - createTLII(TargetTriple, CodeGenOpts)); + std::unique_ptr TLII(createTLII(TargetTriple)); // If we reached here with a non-empty index file name, then the index file // was empty and we are not performing ThinLTO backend compilation (used in @@ -804,8 +787,7 @@ raw_pwrite_stream *DwoOS) { // Add LibraryInfo. llvm::Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr TLII( - createTLII(TargetTriple, CodeGenOpts)); + std::unique_ptr TLII(createTLII(TargetTriple)); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII)); // Normal mode, emit a .s or .o file by running the code generator. Note, @@ -1141,8 +1123,7 @@ // Register the target library analysis directly and give it a customized // preset TLI. Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr TLII( - createTLII(TargetTriple, CodeGenOpts)); + std::unique_ptr TLII(createTLII(TargetTriple)); FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); // Register all the basic analyses with the managers. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1868,6 +1868,24 @@ llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr); } +static void addVectLibAttributes(llvm::AttrBuilder &FuncAttrs, + const CodeGenOptions &CodeGenOpts) { + StringRef AttributeName = "veclib"; + switch (CodeGenOpts.getVecLib()) { + case CodeGenOptions::Accelerate: + FuncAttrs.addAttribute(AttributeName, "Accelerate"); + break; + case CodeGenOptions::MASSV: + FuncAttrs.addAttribute(AttributeName, "MASSV"); + break; + case CodeGenOptions::SVML: + FuncAttrs.addAttribute(AttributeName, "SVML"); + break; + case CodeGenOptions::NoLibrary: + break; + } +} + void CodeGenModule::ConstructAttributeList( StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) { @@ -1966,6 +1984,9 @@ // * FunctionDecl attributes: __attribute__((no_builtin(...))) addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA); + // Attach "veclib" attribute to function based on '-fveclib' setting. + addVectLibAttributes(FuncAttrs, getCodeGenOpts()); + ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs); // This must run after constructing the default function attribute list diff --git a/clang/test/CodeGen/libcalls-veclib.c b/clang/test/CodeGen/libcalls-veclib.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/libcalls-veclib.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -S -emit-llvm -fveclib=SVML -o - %s | FileCheck --check-prefixes=SVML %s +// RUN: %clang_cc1 -S -emit-llvm -fveclib=Accelerate -o - %s | FileCheck --check-prefixes=ACCELERATE %s +// RUN: %clang_cc1 -S -emit-llvm -fveclib=MASSV -o - %s | FileCheck --check-prefixes=MASSV %s +// RUN: %clang_cc1 -S -emit-llvm -fveclib=none -o - %s | FileCheck --check-prefixes=NOLIB %s +// RUN: %clang_cc1 -S -emit-llvm -o - %s | FileCheck --check-prefixes=NOLIB %s + +int main() { + return 0; +} + +// SVML: "veclib"="SVML" +// ACCELERATE: "veclib"="Accelerate" +// MASSV: "veclib"="MASSV" +// NOLIB-NOT: "veclib" \ No newline at end of file diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -48,6 +48,23 @@ class TargetLibraryInfoImpl { friend class TargetLibraryInfo; +public: + /// List of known vector-functions libraries. + /// + /// The vector-functions library defines, which functions are vectorizable + /// and with which factor. The library can be specified by either frontend, + /// or a commandline option, and then used by + /// addVectorizableFunctionsFromVecLib for filling up the tables of + /// vectorizable functions. + enum VectorLibrary { + Accelerate, // Use Accelerate framework. + MASSV, // IBM MASS vector library. + SVML, // Intel short vector math library. + NumVecLibs, // Number of supported vector libraries. + NoLibrary // Don't use any vector library. + }; + +private: unsigned char AvailableArray[(NumLibFuncs+3)/4]; llvm::DenseMap CustomNames; static StringLiteral const StandardNames[NumLibFuncs]; @@ -66,32 +83,31 @@ return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); } - /// Vectorization descriptors - sorted by ScalarFnName. - std::vector VectorDescs; - /// Scalarization descriptors - same content as VectorDescs but sorted based - /// on VectorFnName rather than ScalarFnName. - std::vector ScalarDescs; + /// Vector library descriptor for all supported ones. + struct VectorLibraryDescriptors { + /// Vectorization descriptors - sorted by ScalarFnName. + std::vector VectorDescs; + /// Scalarization descriptors - same content as VectorDescs but sorted based + /// on VectorFnName rather than ScalarFnName. + std::vector ScalarDescs; + } VecLibDescs[NumVecLibs]; /// Return true if the function type FTy is valid for the library function /// F, regardless of whether the function is available. bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, const DataLayout *DL) const; -public: - /// List of known vector-functions libraries. - /// - /// The vector-functions library defines, which functions are vectorizable - /// and with which factor. The library can be specified by either frontend, - /// or a commandline option, and then used by - /// addVectorizableFunctionsFromVecLib for filling up the tables of - /// vectorizable functions. - enum VectorLibrary { - NoLibrary, // Don't use any vector library. - Accelerate, // Use Accelerate framework. - MASSV, // IBM MASS vector library. - SVML // Intel short vector math library. - }; + /// Add a set of scalar -> vector mappings, queryable via + /// getVectorizedFunction and getScalarizedFunction. + void addVectorizableFunctions(ArrayRef Fns, + VectorLibraryDescriptors &VetLibDescs); + /// Calls addVectorizableFunctionsFromVecLib with a known preset of functions + /// for the given vector library. + void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib, + VectorLibraryDescriptors &VetLibDesc); + +public: TargetLibraryInfoImpl(); explicit TargetLibraryInfoImpl(const Triple &T); @@ -141,39 +157,38 @@ /// This can be used for options like -fno-builtin. void disableAllFunctions(); - /// Add a set of scalar -> vector mappings, queryable via - /// getVectorizedFunction and getScalarizedFunction. - void addVectorizableFunctions(ArrayRef Fns); - - /// Calls addVectorizableFunctions with a known preset of functions for the - /// given vector library. - void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib); + /// Populate VectorLibraryDescriptors for all supported vector libraries. + void addAllVectorizableFunctions(); /// Return true if the function F has a vector equivalent with vectorization /// factor VF. - bool isFunctionVectorizable(StringRef F, unsigned VF) const { - return !getVectorizedFunction(F, VF).empty(); + bool isFunctionVectorizable(StringRef F, unsigned VF, + VectorLibrary vecLib) const { + return !getVectorizedFunction(F, VF, vecLib).empty(); } /// Return true if the function F has a vector equivalent with any /// vectorization factor. - bool isFunctionVectorizable(StringRef F) const; + bool isFunctionVectorizable(StringRef F, VectorLibrary vecLib) const; /// Return the name of the equivalent of F, vectorized with factor VF. If no /// such mapping exists, return the empty string. - StringRef getVectorizedFunction(StringRef F, unsigned VF) const; + StringRef getVectorizedFunction(StringRef F, unsigned VF, + VectorLibrary vecLib) const; /// Return true if the function F has a scalar equivalent, and set VF to be /// the vectorization factor. - bool isFunctionScalarizable(StringRef F, unsigned &VF) const { - return !getScalarizedFunction(F, VF).empty(); + bool isFunctionScalarizable(StringRef F, unsigned &VF, + VectorLibrary vecLib) const { + return !getScalarizedFunction(F, VF, vecLib).empty(); } /// Return the name of the equivalent of F, scalarized. If no such mapping /// exists, return the empty string. /// /// Set VF to the vectorization factor. - StringRef getScalarizedFunction(StringRef F, unsigned &VF) const; + StringRef getScalarizedFunction(StringRef F, unsigned &VF, + VectorLibrary vecLib) const; /// Set to true iff i32 parameters to library functions should have signext /// or zeroext attributes if they correspond to C-level int or unsigned int, @@ -201,7 +216,7 @@ /// Returns the largest vectorization factor used in the list of /// vector functions. - unsigned getWidestVF(StringRef ScalarF) const; + unsigned getWidestVF(StringRef ScalarF, VectorLibrary vecLib) const; }; /// Provides information about what library functions are available for @@ -216,63 +231,66 @@ /// The global (module level) TLI info. const TargetLibraryInfoImpl *Impl; + /// Vector library available for vectorization. + TargetLibraryInfoImpl::VectorLibrary VectLibrary = + TargetLibraryInfoImpl::NoLibrary; + /// Support for -fno-builtin* options as function attributes, overrides /// information in global TargetLibraryInfoImpl. BitVector OverrideAsUnavailable; + TargetLibraryInfoImpl::VectorLibrary + getVecLibFromName(const StringRef &VecLibName) { + if (VecLibName == "Accelerate") + return TargetLibraryInfoImpl::Accelerate; + else if (VecLibName == "MASSV") + return TargetLibraryInfoImpl::MASSV; + else if (VecLibName == "SVML") + return TargetLibraryInfoImpl::SVML; + return TargetLibraryInfoImpl::NoLibrary; + } + public: explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl, - Optional F = None) - : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) { - if (!F) - return; - if ((*F)->hasFnAttribute("no-builtins")) - disableAllFunctions(); - else { - // Disable individual libc/libm calls in TargetLibraryInfo. - LibFunc LF; - AttributeSet FnAttrs = (*F)->getAttributes().getFnAttributes(); - for (const Attribute &Attr : FnAttrs) { - if (!Attr.isStringAttribute()) - continue; - auto AttrStr = Attr.getKindAsString(); - if (!AttrStr.consume_front("no-builtin-")) - continue; - if (getLibFunc(AttrStr, LF)) - setUnavailable(LF); - } - } - } + Optional F = None); // Provide value semantics. TargetLibraryInfo(const TargetLibraryInfo &TLI) - : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} + : Impl(TLI.Impl), VectLibrary(TLI.VectLibrary), + OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} TargetLibraryInfo(TargetLibraryInfo &&TLI) - : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} + : Impl(TLI.Impl), VectLibrary(TLI.VectLibrary), + OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { Impl = TLI.Impl; + VectLibrary = TLI.VectLibrary; OverrideAsUnavailable = TLI.OverrideAsUnavailable; return *this; } TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { Impl = TLI.Impl; + VectLibrary = TLI.VectLibrary; OverrideAsUnavailable = TLI.OverrideAsUnavailable; return *this; } /// Determine whether a callee with the given TLI can be inlined into - /// caller with this TLI, based on 'nobuiltin' attributes. When requested, - /// allow inlining into a caller with a superset of the callee's nobuiltin - /// attributes, which is conservatively correct. + /// caller with this TLI, based on 'nobuiltin', `veclib` attributes. + /// When requested, allow inlining into a caller with a superset of the + /// callee's attributes, which is conservatively correct. bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI, bool AllowCallerSuperset) const { if (!AllowCallerSuperset) - return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable; + return VectLibrary == CalleeTLI.VectLibrary && + OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable; BitVector B = OverrideAsUnavailable; B |= CalleeTLI.OverrideAsUnavailable; - // We can inline if the union of the caller and callee's nobuiltin - // attributes is no stricter than the caller's nobuiltin attributes. - return B == OverrideAsUnavailable; + // We can inline if the union of the caller and callee's attributes + // is no stricter than the caller's attributes. + bool VecLibCompatible = + (VectLibrary == CalleeTLI.VectLibrary) || + CalleeTLI.VectLibrary == TargetLibraryInfoImpl::NoLibrary; + return B == OverrideAsUnavailable && VecLibCompatible; } /// Searches for a particular function name. @@ -317,13 +335,13 @@ return getState(F) != TargetLibraryInfoImpl::Unavailable; } bool isFunctionVectorizable(StringRef F, unsigned VF) const { - return Impl->isFunctionVectorizable(F, VF); + return Impl->isFunctionVectorizable(F, VF, VectLibrary); } bool isFunctionVectorizable(StringRef F) const { - return Impl->isFunctionVectorizable(F); + return Impl->isFunctionVectorizable(F, VectLibrary); } StringRef getVectorizedFunction(StringRef F, unsigned VF) const { - return Impl->getVectorizedFunction(F, VF); + return Impl->getVectorizedFunction(F, VF, VectLibrary); } /// Tests if the function is both available and a candidate for optimized code @@ -408,7 +426,7 @@ /// Returns the largest vectorization factor used in the list of /// vector functions. unsigned getWidestVF(StringRef ScalarF) const { - return Impl->getWidestVF(ScalarF); + return Impl->getWidestVF(ScalarF, VectLibrary); } /// Check if the function "F" is listed in a library known to LLVM. diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -104,10 +104,9 @@ cl::desc("Compute the full inline cost of a call site even when the cost " "exceeds the threshold.")); -static cl::opt InlineCallerSupersetNoBuiltin( - "inline-caller-superset-nobuiltin", cl::Hidden, cl::init(true), - cl::ZeroOrMore, - cl::desc("Allow inlining when caller has a superset of callee's nobuiltin " +static cl::opt InlineCallerSupersetTLI( + "inline-caller-superset-tli", cl::Hidden, cl::init(true), cl::ZeroOrMore, + cl::desc("Allow inlining when caller has a superset of callee's TLI " "attributes.")); namespace { @@ -2163,7 +2162,7 @@ auto CalleeTLI = GetTLI(*Callee); return TTI.areInlineCompatible(Caller, Callee) && GetTLI(*Caller).areInlineCompatible(CalleeTLI, - InlineCallerSupersetNoBuiltin) && + InlineCallerSupersetTLI) && AttributeFuncs::areInlineCompatible(*Caller, *Callee); } diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -550,7 +550,7 @@ TLI.setUnavailable(LibFunc_nvvm_reflect); } - TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); + TLI.addAllVectorizableFunctions(); } TargetLibraryInfoImpl::TargetLibraryInfoImpl() { @@ -572,8 +572,8 @@ ShouldExtI32Return(TLI.ShouldExtI32Return), ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); - VectorDescs = TLI.VectorDescs; - ScalarDescs = TLI.ScalarDescs; + for (unsigned i = 0; i < NumVecLibs; i++) + VecLibDescs[i] = TLI.VecLibDescs[i]; } TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) @@ -583,8 +583,8 @@ ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); - VectorDescs = TLI.VectorDescs; - ScalarDescs = TLI.ScalarDescs; + for (unsigned i = 0; i < NumVecLibs; i++) + VecLibDescs[i] = TLI.VecLibDescs[i]; } TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoImpl &TLI) { @@ -1520,7 +1520,16 @@ return LHS.VectorFnName < S; } -void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef Fns) { +void TargetLibraryInfoImpl::addAllVectorizableFunctions() { + addVectorizableFunctionsFromVecLib(Accelerate, VecLibDescs[Accelerate]); + addVectorizableFunctionsFromVecLib(MASSV, VecLibDescs[MASSV]); + addVectorizableFunctionsFromVecLib(SVML, VecLibDescs[SVML]); +} + +void TargetLibraryInfoImpl::addVectorizableFunctions( + ArrayRef Fns, VectorLibraryDescriptors &VecLibDesc) { + auto &VectorDescs = VecLibDesc.VectorDescs; + auto &ScalarDescs = VecLibDesc.ScalarDescs; VectorDescs.insert(VectorDescs.end(), Fns.begin(), Fns.end()); llvm::sort(VectorDescs, compareByScalarFnName); @@ -1529,14 +1538,14 @@ } void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib( - enum VectorLibrary VecLib) { + enum VectorLibrary VecLib, VectorLibraryDescriptors &VetLibDesc) { switch (VecLib) { case Accelerate: { const VecDesc VecFuncs[] = { #define TLI_DEFINE_ACCELERATE_VECFUNCS #include "llvm/Analysis/VecFuncs.def" }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs, VetLibDesc); break; } case MASSV: { @@ -1544,7 +1553,7 @@ #define TLI_DEFINE_MASSV_VECFUNCS #include "llvm/Analysis/VecFuncs.def" }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs, VetLibDesc); break; } case SVML: { @@ -1552,29 +1561,34 @@ #define TLI_DEFINE_SVML_VECFUNCS #include "llvm/Analysis/VecFuncs.def" }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs, VetLibDesc); break; } - case NoLibrary: + default: + llvm_unreachable("Unexpected vector library"); break; } } -bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const { +bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName, + VectorLibrary vecLib) const { funcName = sanitizeFunctionName(funcName); - if (funcName.empty()) + if (funcName.empty() || vecLib >= NumVecLibs) return false; + auto &VectorDescs = VecLibDescs[vecLib].VectorDescs; std::vector::const_iterator I = llvm::lower_bound(VectorDescs, funcName, compareWithScalarFnName); return I != VectorDescs.end() && StringRef(I->ScalarFnName) == funcName; } -StringRef TargetLibraryInfoImpl::getVectorizedFunction(StringRef F, - unsigned VF) const { +StringRef +TargetLibraryInfoImpl::getVectorizedFunction(StringRef F, unsigned VF, + VectorLibrary vecLib) const { F = sanitizeFunctionName(F); - if (F.empty()) + if (F.empty() || vecLib >= NumVecLibs) return F; + auto &VectorDescs = VecLibDescs[vecLib].VectorDescs; std::vector::const_iterator I = llvm::lower_bound(VectorDescs, F, compareWithScalarFnName); while (I != VectorDescs.end() && StringRef(I->ScalarFnName) == F) { @@ -1585,12 +1599,15 @@ return StringRef(); } -StringRef TargetLibraryInfoImpl::getScalarizedFunction(StringRef F, - unsigned &VF) const { +StringRef +TargetLibraryInfoImpl::getScalarizedFunction(StringRef F, unsigned &VF, + VectorLibrary vecLib) const { F = sanitizeFunctionName(F); - if (F.empty()) + if (F.empty() || vecLib >= NumVecLibs) return F; + auto &VectorDescs = VecLibDescs[vecLib].VectorDescs; + auto &ScalarDescs = VecLibDescs[vecLib].ScalarDescs; std::vector::const_iterator I = llvm::lower_bound(ScalarDescs, F, compareWithVectorFnName); if (I == VectorDescs.end() || StringRef(I->VectorFnName) != F) @@ -1599,6 +1616,36 @@ return I->ScalarFnName; } +TargetLibraryInfo::TargetLibraryInfo(const TargetLibraryInfoImpl &Impl, + Optional F) + : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) { + if (!F) + return; + + StringRef VectLib = (*F)->getFnAttribute("veclib").getValueAsString(); + if (!VectLib.empty()) + VectLibrary = getVecLibFromName(VectLib); + else + VectLibrary = ClVectorLibrary; + + if ((*F)->hasFnAttribute("no-builtins")) + disableAllFunctions(); + else { + // Disable individual libc/libm calls in TargetLibraryInfo. + LibFunc LF; + AttributeSet FnAttrs = (*F)->getAttributes().getFnAttributes(); + for (const Attribute &Attr : FnAttrs) { + if (!Attr.isStringAttribute()) + continue; + auto AttrStr = Attr.getKindAsString(); + if (!AttrStr.consume_front("no-builtin-")) + continue; + if (getLibFunc(AttrStr, LF)) + setUnavailable(LF); + } + } +} + TargetLibraryInfo TargetLibraryAnalysis::run(const Function &F, FunctionAnalysisManager &) { if (!BaselineInfoImpl) @@ -1639,12 +1686,14 @@ void TargetLibraryInfoWrapperPass::anchor() {} -unsigned TargetLibraryInfoImpl::getWidestVF(StringRef ScalarF) const { +unsigned TargetLibraryInfoImpl::getWidestVF(StringRef ScalarF, + VectorLibrary vecLib) const { ScalarF = sanitizeFunctionName(ScalarF); - if (ScalarF.empty()) + if (ScalarF.empty() || vecLib >= NumVecLibs) return 1; unsigned VF = 1; + auto &VectorDescs = VecLibDescs[vecLib].VectorDescs; std::vector::const_iterator I = llvm::lower_bound(VectorDescs, ScalarF, compareWithScalarFnName); while (I != VectorDescs.end() && StringRef(I->ScalarFnName) == ScalarF) { diff --git a/llvm/test/Transforms/Inline/inline-no-builtin-compatible.ll b/llvm/test/Transforms/Inline/inline-no-builtin-compatible.ll --- a/llvm/test/Transforms/Inline/inline-no-builtin-compatible.ll +++ b/llvm/test/Transforms/Inline/inline-no-builtin-compatible.ll @@ -3,8 +3,8 @@ ; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s ; Make sure we don't inline callees into a caller with a superset of the -; no builtin attributes when -inline-caller-superset-nobuiltin=false. -; RUN: opt < %s -inline-caller-superset-nobuiltin=false -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s --check-prefix=NOSUPERSET +; no builtin attributes when -inline-caller-superset-tli=false. +; RUN: opt < %s -inline-caller-superset-tli=false -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s --check-prefix=NOSUPERSET target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Transforms/Inline/veclib-compat.ll b/llvm/test/Transforms/Inline/veclib-compat.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Inline/veclib-compat.ll @@ -0,0 +1,50 @@ +; RUN: opt < %s -inline -inline-caller-superset-tli=true -S | FileCheck %s --check-prefixes=SUPERSET,COMMON +; RUN: opt < %s -passes='cgscc(inline)' -inline-caller-superset-tli=true -S | FileCheck %s --check-prefixes=SUPERSET,COMMON +; RUN: opt < %s -inline -inline-caller-superset-tli=false -S | FileCheck %s --check-prefixes=NOSUPERSET,COMMON +; RUN: opt < %s -passes='cgscc(inline)' -inline-caller-superset-tli=false -S | FileCheck %s --check-prefixes=NOSUPERSET,COMMON + + + +define i32 @callee_svml(i8 %X) #0 { +entry: + ret i32 1 +} + +define i32 @callee_massv(i8 %X) #1 { +entry: + ret i32 1 +} + +define i32 @callee_nolibrary(i8 %X) { +entry: + ret i32 1 +} + +define i32 @caller_svml() #0 { +; SUPERSET-LABEL: define i32 @caller_svml() +; NOSUPERSET-LABEL: define i32 @caller_svml() +entry: + %rslt = call i32 @callee_massv(i8 123) +; SUPERSET: call i32 @callee_massv + %tmp1 = call i32 @callee_nolibrary(i8 123) +; NOSUPERSET: call i32 @callee_nolibrary + %tmp2 = call i32 @callee_svml(i8 123) +; SUPERSET-NOT: call +; NOSUPERSET-NOT: call + ret i32 %rslt +} + +define i32 @caller_nolibrary() { +; COMMON-LABEL: define i32 @caller_nolibrary() +entry: + %rslt = call i32 @callee_svml(i8 123) +; COMMON: call i32 @callee_svml + %tmp1 = call i32 @callee_massv(i8 123) +; COMMON: call i32 @callee_massv + %tmp2 = call i32 @callee_nolibrary(i8 123) +; COMMON-NOT: call + ret i32 %rslt +} + +attributes #0 = { "veclib"="SVML" } +attributes #1 = { "veclib"="MASSV" } \ No newline at end of file