#define LLVM_ANALYSIS_VECTORUTILS_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/CheckedArithmetic.h"
/// * x86 (libmvec): https://sourceware.org/glibc/wiki/libmvec and
/// https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt
///
-///
-///
/// \param MangledName -> input string in the format
/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
Optional<VFInfo> tryDemangleForVFABI(StringRef MangledName);
/// Retrieve the `VFParamKind` from a string token.
VFParamKind getVFParamKindFromString(const StringRef Token);
+
+// Name of the attribute where the variant mappings are stored.
+static constexpr char const *MappingsAttrName = "vector-function-abi-variant";
+
+/// Populates a set of strings representing the Vector Function ABI variants
+/// associated to the CallInst CI.
+void getVectorVariantNames(const CallInst &CI,
+ SmallVectorImpl<std::string> &VariantMappings);
} // end namespace VFABI
template <typename T> class ArrayRef;
template <typename InstTy> class InterleaveGroup;
class Loop;
class ScalarEvolution;
-class TargetLibraryInfo;
class TargetTransformInfo;
class Type;
class Value;
#ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
#define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include <utility> // for std::pair
/// unique identifier for this module, so we return the empty string.
std::string getUniqueModuleId(Module *M);
+class TargetLibraryInfo;
+class CallInst;
+namespace VFABI {
+
+/// \defgroup Vector Function ABI (VABI) Module functions.
+///
+/// Utility functions for VFABI data that can modify the module.
+///
+/// @{
+/// Overwrite the Vector Function ABI variants attribute with the names provide
+/// in \p VariantMappings.
+void setVectorVariantNames(CallInst *CI,
+ const SmallVector<std::string, 8> &VariantMappings);
+
+/// @}
+} // End VFABI namespace
+
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/VectorUtils.h"
using namespace llvm;
.Case("d", VFISAKind::AVX2)
.Case("e", VFISAKind::AVX512)
.Default(VFISAKind::Unknown);
-
MangledName = MangledName.drop_front(1);
return ParseRet::OK;
}
} while (ParamFound == ParseRet::OK);
- // A valid MangledName mus have at least one valid entry in the
+ // A valid MangledName must have at least one valid entry in the
// <parameters>.
if (Parameters.empty())
return None;
propagateMetadata(NewInst, VL);
}
}
+
+void VFABI::getVectorVariantNames(
+ const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) {
+ const StringRef S =
+ CI.getAttribute(AttributeList::FunctionIndex, VFABI::MappingsAttrName)
+ .getValueAsString();
+ SmallVector<StringRef, 8> ListAttr;
+ S.split(ListAttr, ",");
+
+ for (auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) {
+#ifndef NDEBUG
+ Optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S);
+ assert(Info.hasValue() && "Invalid name for a VFABI variant.");
+ assert(CI.getModule()->getFunction(Info.getValue().VectorName) &&
+ "Vector function is missing.");
+#endif
+ VariantMappings.push_back(S);
+ }
+}
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
MD5::stringifyResult(R, Str);
return ("$" + Str).str();
}
+
+void VFABI::setVectorVariantNames(
+ CallInst *CI, const SmallVector<std::string, 8> &VariantMappings) {
+ if (VariantMappings.empty())
+ return;
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ for (const std::string &VariantMapping : VariantMappings)
+ Out << VariantMapping << ",";
+ // Get rid of the trailing ','.
+ assert(!Buffer.str().empty() && "Must have at least one char.");
+ Buffer.pop_back();
+
+ Module *M = CI->getModule();
+#ifndef NDEBUG
+ for (const std::string &VariantMapping : VariantMappings) {
+ Optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping);
+ assert(VI.hasValue() && "Canno add an invalid VFABI name.");
+ assert(M->getNamedValue(VI.getValue().VectorName) &&
+ "Cannot add variant to attribute: "
+ "vector function declaration is missing.");
+ }
+#endif
+ CI->addAttribute(
+ AttributeList::FunctionIndex,
+ Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));
+}
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/VectorUtils.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/InstIterator.h"
#include "gtest/gtest.h"
using namespace llvm;
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
EXPECT_EQ(ScalarName, "sin");
}
+
+class VFABIAttrTest : public testing::Test {
+protected:
+ void SetUp() override {
+ M = parseAssemblyString(IR, Err, Ctx);
+ // Get the only call instruction in the block, which is the first
+ // instruction.
+ CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
+ }
+ const char *IR = "define i32 @f(i32 %a) {\n"
+ " %1 = call i32 @g(i32 %a) #0\n"
+ " ret i32 %1\n"
+ "}\n"
+ "declare i32 @g(i32)\n"
+ "declare <2 x i32> @custom_vg(<2 x i32>)"
+ "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
+ "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
+ "attributes #0 = { "
+ "\"vector-function-abi-variant\"=\""
+ "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
+ LLVMContext Ctx;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M;
+ CallInst *CI;
+ SmallVector<std::string, 8> Mappings;
+};
+
+TEST_F(VFABIAttrTest, Read) {
+ VFABI::getVectorVariantNames(*CI, Mappings);
+ SmallVector<std::string, 8> Exp;
+ Exp.push_back("_ZGVnN2v_g(custom_vg)");
+ Exp.push_back("_ZGVnN4v_g");
+ EXPECT_EQ(Mappings, Exp);
+}
SSAUpdaterBulkTest.cpp
UnrollLoopTest.cpp
ValueMapperTest.cpp
+ VFABIUtils.cpp
)
--- /dev/null
+//===------- VFABIUtils.cpp - VFABI Unittests ----------------------------===//
+//
+// 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 "llvm/AsmParser/Parser.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+class VFABIAttrTest : public testing::Test {
+protected:
+ void SetUp() override {
+ M = parseAssemblyString(IR, Err, Ctx);
+ // Get the only call instruction in the block, which is the first
+ // instruction.
+ CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
+ }
+ const char *IR = "define i32 @f(i32 %a) {\n"
+ " %1 = call i32 @g(i32 %a) #0\n"
+ " ret i32 %1\n"
+ "}\n"
+ "declare i32 @g(i32)\n"
+ "declare <2 x i32> @custom_vg(<2 x i32>)"
+ "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
+ "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
+ "attributes #0 = { "
+ "\"vector-function-abi-variant\"=\""
+ "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
+ LLVMContext Ctx;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M;
+ CallInst *CI;
+ SmallVector<std::string, 8> Mappings;
+};
+
+TEST_F(VFABIAttrTest, Write) {
+ Mappings.push_back("_ZGVnN8v_g");
+ Mappings.push_back("_ZGVnN2v_g(custom_vg)");
+ VFABI::setVectorVariantNames(CI, Mappings);
+ const AttributeList Attrs = CI->getAttributes();
+ const AttributeSet FnAttrs = Attrs.getFnAttributes();
+ const StringRef S = CI->getAttribute(AttributeList::FunctionIndex,
+ "vector-function-abi-variant")
+ .getValueAsString();
+ EXPECT_EQ(S, "_ZGVnN8v_g,_ZGVnN2v_g(custom_vg)");
+}