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,33 @@ 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 available for vectorization from '-vector-library'. + VectorLibrary ClVectorLibrary = NoLibrary; + /// 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); @@ -124,6 +142,12 @@ setState(F, StandardName); } + /// Set that vector library selection from '-vector-library'. Note that this + /// is only for testing opt, etc., as a side channel for passing veclib setting. + void setClVectorLibrary(VectorLibrary VecLib) { + ClVectorLibrary = VecLib; + } + /// Forces a function to be marked as available and provide an alternate name /// that must be used. void setAvailableWithName(LibFunc F, StringRef Name) { @@ -141,39 +165,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 +224,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,16 +239,38 @@ /// 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; + + StringRef VectLib = (*F)->getFnAttribute("veclib").getValueAsString(); + if (!VectLib.empty()) + VectLibrary = getVecLibFromName(VectLib); + else + VectLibrary = Impl.ClVectorLibrary; + if ((*F)->hasFnAttribute("no-builtins")) disableAllFunctions(); else { @@ -246,33 +291,41 @@ // 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 +370,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 +461,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/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -550,7 +550,8 @@ TLI.setUnavailable(LibFunc_nvvm_reflect); } - TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary); + TLI.addAllVectorizableFunctions(); + TLI.setClVectorLibrary(ClVectorLibrary); } TargetLibraryInfoImpl::TargetLibraryInfoImpl() { @@ -570,21 +571,25 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) : CustomNames(TLI.CustomNames), ShouldExtI32Param(TLI.ShouldExtI32Param), ShouldExtI32Return(TLI.ShouldExtI32Return), - ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { + ShouldSignExtI32Param(TLI.ShouldSignExtI32Param), + ClVectorLibrary(TLI.ClVectorLibrary) { memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); - VectorDescs = TLI.VectorDescs; - ScalarDescs = TLI.ScalarDescs; + for (unsigned i = 0; i < sizeof(TLI.VecLibDescs) / sizeof(TLI.VecLibDescs[0]); + i++) + VecLibDescs[i] = TLI.VecLibDescs[i]; } TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) : CustomNames(std::move(TLI.CustomNames)), ShouldExtI32Param(TLI.ShouldExtI32Param), ShouldExtI32Return(TLI.ShouldExtI32Return), - ShouldSignExtI32Param(TLI.ShouldSignExtI32Param) { + ShouldSignExtI32Param(TLI.ShouldSignExtI32Param), + ClVectorLibrary(TLI.ClVectorLibrary) { std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); - VectorDescs = TLI.VectorDescs; - ScalarDescs = TLI.ScalarDescs; + for (unsigned i = 0; i < sizeof(TLI.VecLibDescs) / sizeof(TLI.VecLibDescs[0]); + i++) + VecLibDescs[i] = TLI.VecLibDescs[i]; } TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoImpl &TLI) { @@ -1520,7 +1525,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 +1543,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 +1558,7 @@ #define TLI_DEFINE_MASSV_VECFUNCS #include "llvm/Analysis/VecFuncs.def" }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs, VetLibDesc); break; } case SVML: { @@ -1552,29 +1566,33 @@ #define TLI_DEFINE_SVML_VECFUNCS #include "llvm/Analysis/VecFuncs.def" }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs, VetLibDesc); break; } case NoLibrary: + case NumVecLibs: 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 +1603,14 @@ 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) @@ -1639,12 +1659,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/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,43 @@ +; RUN: opt < %s -inline -S | FileCheck %s +; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s + +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 { +; CHECK-LABEL: define i32 @caller_svml() +entry: + %rslt = call i32 @callee_massv(i8 123) +; CHECK: call i32 @callee_massv + %tmp1 = call i32 @callee_svml(i8 123) + %tmp2 = call i32 @callee_nolibrary(i8 123) +; CHECK-NOT: call + ret i32 %rslt +} + +define i32 @caller_nolibrary() { +; CHECK-LABEL: define i32 @caller_nolibrary() +entry: + %rslt = call i32 @callee_svml(i8 123) +; CHECK: call i32 @callee_svml + %tmp1 = call i32 @callee_massv(i8 123) +; CHECK: call i32 @callee_massv + %tmp2 = call i32 @callee_nolibrary(i8 123) +; CHECK-NOT: call + ret i32 %rslt +} + +attributes #0 = { "veclib"="SVML" } +attributes #1 = { "veclib"="MASSV" } \ No newline at end of file