diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-05 13:41:58 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-03-05 13:41:58 +0000 |
commit | 1ff3a73c1ece7a0a4b7a8457eb4d5c47334b1526 (patch) | |
tree | cd1708b84ab6918d8a39f879def9bdd12c71c9e6 | |
parent | 7eff647615f93a9aaff1997e1880b195dc3aabe6 (diff) |
Vendor import of llvm-project branch release/14.x llvmorg-14.0.0-rc2-12-g09546e1b5103.vendor/llvm-project/llvmorg-14.0.0-rc2-12-g09546e1b5103
48 files changed, 575 insertions, 323 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index d216b359816e..319e605a8a1c 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -2461,10 +2461,10 @@ private: SourceLocation FriendLoc; FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, - MutableArrayRef<TemplateParameterList *> Params, + TemplateParameterList **Params, unsigned NumParams, FriendUnion Friend, SourceLocation FriendLoc) - : Decl(Decl::FriendTemplate, DC, Loc), NumParams(Params.size()), - Params(Params.data()), Friend(Friend), FriendLoc(FriendLoc) {} + : Decl(Decl::FriendTemplate, DC, Loc), NumParams(NumParams), + Params(Params), Friend(Friend), FriendLoc(FriendLoc) {} FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {} diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 223f06b9db1c..d9ff3517a589 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -1098,7 +1099,13 @@ FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, SourceLocation L, MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend, SourceLocation FLoc) { - return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc); + TemplateParameterList **TPL = nullptr; + if (!Params.empty()) { + TPL = new (Context) TemplateParameterList *[Params.size()]; + llvm::copy(Params, TPL); + } + return new (Context, DC) + FriendTemplateDecl(DC, L, TPL, Params.size(), Friend, FLoc); } FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 6364cd133e0b..dfcef2304040 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -756,7 +756,7 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, return false; } -static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) { +const char *tools::getAsNeededOption(const ToolChain &TC, bool as_needed) { assert(!TC.getTriple().isOSAIX() && "AIX linker does not support any form of --as-needed option yet."); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 646fa76949b7..23012dc247e4 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -117,6 +117,8 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, bool ForceStaticHostRuntime = false, bool IsOffloadingHost = false, bool GompNeedsRT = false); +const char *getAsNeededOption(const ToolChain &TC, bool as_needed); + llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args); llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp index 9568b47e89e6..8cfec6a6c4e0 100644 --- a/clang/lib/Driver/ToolChains/DragonFly.cpp +++ b/clang/lib/Driver/ToolChains/DragonFly.cpp @@ -91,7 +91,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, assert(Output.isNothing() && "Invalid output."); } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back( @@ -119,7 +120,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, + options::OPT_r)) { CmdArgs.push_back("-L/usr/lib/gcc80"); if (!Args.hasArg(options::OPT_static)) { @@ -158,7 +160,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp index 37b1fc5215ff..d1eda14a51f0 100644 --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -236,7 +236,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, assert(Output.isNothing() && "Invalid output."); } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back( Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); @@ -294,7 +295,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, + options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Args.hasArg(options::OPT_static); @@ -330,7 +332,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back( Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); diff --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h index 95c10cc62316..9d668711b91b 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.h +++ b/clang/lib/Driver/ToolChains/OpenBSD.h @@ -82,6 +82,10 @@ public: std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, FileType Type = ToolChain::FT_Static) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override { + return true; + } + LangOptions::StackProtectorMode GetDefaultStackProtectorLevel(bool KernelOrKext) const override { return LangOptions::SSPStrong; diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp index 4d1af094f481..24f18b92dd66 100644 --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -132,6 +132,13 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lssp_nonshared"); CmdArgs.push_back("-lssp"); } + // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so + // forcibly link with libatomic as a workaround. + if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) { + CmdArgs.push_back(getAsNeededOption(getToolChain(), true)); + CmdArgs.push_back("-latomic"); + CmdArgs.push_back(getAsNeededOption(getToolChain(), false)); + } CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("-lc"); if (!Args.hasArg(options::OPT_shared)) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 1ab26e58a404..5d63a26132b7 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2103,7 +2103,7 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { VisitDecl(D); unsigned NumParams = Record.readInt(); D->NumParams = NumParams; - D->Params = new TemplateParameterList*[NumParams]; + D->Params = new (Reader.getContext()) TemplateParameterList *[NumParams]; for (unsigned i = 0; i != NumParams; ++i) D->Params[i] = Record.readTemplateParameterList(); if (Record.readInt()) // HasFriendDecl diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h index 6cc6405686f5..0802d2496f5c 100644 --- a/libcxx/include/__algorithm/comp_ref_type.h +++ b/libcxx/include/__algorithm/comp_ref_type.h @@ -28,11 +28,11 @@ template <class _Compare> struct __debug_less { _Compare &__comp_; - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 __debug_less(_Compare& __c) : __comp_(__c) {} template <class _Tp, class _Up> - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _Tp& __x, const _Up& __y) { bool __r = __comp_(__x, __y); @@ -42,7 +42,7 @@ struct __debug_less } template <class _Tp, class _Up> - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(_Tp& __x, _Up& __y) { bool __r = __comp_(__x, __y); @@ -52,7 +52,7 @@ struct __debug_less } template <class _LHS, class _RHS> - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 inline _LIBCPP_INLINE_VISIBILITY decltype((void)declval<_Compare&>()( declval<_LHS &>(), declval<_RHS &>())) @@ -62,7 +62,7 @@ struct __debug_less } template <class _LHS, class _RHS> - _LIBCPP_CONSTEXPR_AFTER_CXX17 + _LIBCPP_CONSTEXPR_AFTER_CXX11 inline _LIBCPP_INLINE_VISIBILITY void __do_compare_assert(long, _LHS &, _RHS &) {} }; diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp index 7aeeffaae8f3..39fb5739739b 100644 --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -1414,12 +1414,14 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) { if (fd != -1) { // If that worked, iterate over the contents of the directory and // remove everything in it, recursively. - scope_exit close_fd([=] { ::close(fd); }); DIR* stream = ::fdopendir(fd); if (stream == nullptr) { + ::close(fd); ec = detail::capture_errno(); return 0; } + // Note: `::closedir` will also close the associated file descriptor, so + // there should be no call to `close(fd)`. scope_exit close_stream([=] { ::closedir(stream); }); uintmax_t count = 0; diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index 9566bb0335fe..b39489235ce6 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -603,9 +603,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stw 30,128(3) stw 31,132(3) +#if defined(__ALTIVEC__) // save VRSave register mfspr 0, 256 stw 0, 156(3) +#endif // save CR registers mfcr 0 stw 0, 136(3) diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h index 978f6bd619bd..89293a555bfc 100644 --- a/libunwind/src/assembly.h +++ b/libunwind/src/assembly.h @@ -15,7 +15,7 @@ #ifndef UNWIND_ASSEMBLY_H #define UNWIND_ASSEMBLY_H -#if (defined(__i386__) || defined(__x86_64__)) && defined(__linux__) +#if defined(__linux__) && defined(__CET__) #include <cet.h> #define _LIBUNWIND_CET_ENDBR _CET_ENDBR #else diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 9e857d590684..add819ff5a80 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -199,6 +199,11 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const { return read64(buf + 8); case R_AARCH64_NONE: return 0; + case R_AARCH64_PREL32: + return SignExtend64<32>(read32(buf)); + case R_AARCH64_ABS64: + case R_AARCH64_PREL64: + return read64(buf); default: internalLinkerError(getErrorLocation(buf), "cannot read addend for relocation " + toString(type)); diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 315ac7df608d..47c31e3a3b94 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -280,6 +280,9 @@ int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const { switch (type) { case R_PPC_NONE: return 0; + case R_PPC_ADDR32: + case R_PPC_REL32: + return SignExtend64<32>(read32(buf)); default: internalLinkerError(getErrorLocation(buf), "cannot read addend for relocation " + toString(type)); diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 7d051c43af0d..871e19262ae7 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -1064,6 +1064,11 @@ int64_t PPC64::getImplicitAddend(const uint8_t *buf, RelType type) const { switch (type) { case R_PPC64_NONE: return 0; + case R_PPC64_REL32: + return SignExtend64<32>(read32(buf)); + case R_PPC64_ADDR64: + case R_PPC64_REL64: + return read64(buf); default: internalLinkerError(getErrorLocation(buf), "cannot read addend for relocation " + toString(type)); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 986c1308cbaf..7778ae5f78e6 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1231,6 +1231,7 @@ StringTableSection::StringTableSection(StringRef name, bool dynamic) dynamic(dynamic) { // ELF string tables start with a NUL byte. strings.push_back(""); + stringMap.try_emplace(CachedHashStringRef(""), 0); size = 1; } @@ -2698,6 +2699,8 @@ size_t IBTPltSection::getSize() const { return 16 + in.plt->getNumEntries() * target->pltEntrySize; } +bool IBTPltSection::isNeeded() const { return in.plt->getNumEntries() > 0; } + // The string hash function for .gdb_index. static uint32_t computeGdbHash(StringRef s) { uint32_t h = 0; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 1b63a5d29d10..e609b3d7982a 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -762,6 +762,7 @@ class IBTPltSection : public SyntheticSection { public: IBTPltSection(); void writeTo(uint8_t *Buf) override; + bool isNeeded() const override; size_t getSize() const override; }; diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index d5b60ee540e0..ce4413682bdc 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -210,7 +210,6 @@ public: SizeOffsetType visitConstantPointerNull(ConstantPointerNull&); SizeOffsetType visitExtractElementInst(ExtractElementInst &I); SizeOffsetType visitExtractValueInst(ExtractValueInst &I); - SizeOffsetType visitGEPOperator(GEPOperator &GEP); SizeOffsetType visitGlobalAlias(GlobalAlias &GA); SizeOffsetType visitGlobalVariable(GlobalVariable &GV); SizeOffsetType visitIntToPtrInst(IntToPtrInst&); @@ -221,6 +220,7 @@ public: SizeOffsetType visitInstruction(Instruction &I); private: + SizeOffsetType computeImpl(Value *V); bool CheckedZextOrTrunc(APInt &I); }; diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h index e7dde986784f..016fe0289406 100644 --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -731,6 +731,10 @@ inline bool isReservedSectionNumber(int32_t SectionNumber) { return SectionNumber <= 0; } +/// Encode section name based on string table offset. +/// The size of Out must be at least COFF::NameSize. +bool encodeSectionName(char *Out, uint64_t Offset); + } // End namespace COFF. } // End namespace llvm. diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def index 814d8b113ec4..ae25ec53813c 100644 --- a/llvm/include/llvm/BinaryFormat/DynamicTags.def +++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -209,6 +209,7 @@ MIPS_DYNAMIC_TAG(MIPS_RWPLT, 0x70000034) // Points to the base // of a writable PLT. MIPS_DYNAMIC_TAG(MIPS_RLD_MAP_REL, 0x70000035) // Relative offset of run time loader // map, used for debugging. +MIPS_DYNAMIC_TAG(MIPS_XHASH, 0x70000036) // GNU-style hash table with xlat. // PPC specific dynamic table entries. PPC_DYNAMIC_TAG(PPC_GOT, 0x70000000) // Uses Secure PLT ABI. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h index 92de5882bafe..354984b540a9 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h @@ -148,7 +148,7 @@ private: std::mutex EPCUIMutex; ExecutorProcessControl &EPC; std::unique_ptr<ABISupport> ABI; - JITTargetAddress ResolverBlockAddr; + JITTargetAddress ResolverBlockAddr = 0; FinalizedAlloc ResolverBlock; std::unique_ptr<TrampolinePool> TP; std::unique_ptr<LazyCallThroughManager> LCTM; diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 7eee16f71d64..8677a0ba62f2 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -192,6 +192,7 @@ bool getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, SmallVectorImpl<Value *> &Objects, const AbstractAttribute &QueryingAA, const Instruction *CtxI, + bool &UsedAssumedInformation, bool Intraprocedural = false); /// Collect all potential values of the one stored by \p SI into @@ -1824,23 +1825,24 @@ public: /// This method will evaluate \p Pred on call sites and return /// true if \p Pred holds in every call sites. However, this is only possible /// all call sites are known, hence the function has internal linkage. - /// If true is returned, \p AllCallSitesKnown is set if all possible call - /// sites of the function have been visited. + /// If true is returned, \p UsedAssumedInformation is set if assumed + /// information was used to skip or simplify potential call sites. bool checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, - bool RequireAllCallSites, bool &AllCallSitesKnown); + bool RequireAllCallSites, + bool &UsedAssumedInformation); /// Check \p Pred on all call sites of \p Fn. /// /// This method will evaluate \p Pred on call sites and return /// true if \p Pred holds in every call sites. However, this is only possible /// all call sites are known, hence the function has internal linkage. - /// If true is returned, \p AllCallSitesKnown is set if all possible call - /// sites of the function have been visited. + /// If true is returned, \p UsedAssumedInformation is set if assumed + /// information was used to skip or simplify potential call sites. bool checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const Function &Fn, bool RequireAllCallSites, const AbstractAttribute *QueryingAA, - bool &AllCallSitesKnown); + bool &UsedAssumedInformation); /// Check \p Pred on all values potentially returned by \p F. /// diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 7cf69f613c66..f6b955162fa5 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -589,14 +589,17 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy, if (BytesLoaded > 32 || BytesLoaded == 0) return nullptr; - int64_t InitializerSize = DL.getTypeAllocSize(C->getType()).getFixedSize(); - // If we're not accessing anything in this constant, the result is undefined. if (Offset <= -1 * static_cast<int64_t>(BytesLoaded)) return UndefValue::get(IntType); + // TODO: We should be able to support scalable types. + TypeSize InitializerSize = DL.getTypeAllocSize(C->getType()); + if (InitializerSize.isScalable()) + return nullptr; + // If we're not accessing anything in this constant, the result is undefined. - if (Offset >= InitializerSize) + if (Offset >= (int64_t)InitializerSize.getFixedValue()) return UndefValue::get(IntType); unsigned char RawBytes[32] = {0}; diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp index 44b1d94ebdc8..74b0d6751023 100644 --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -1428,10 +1428,14 @@ bool InductionDescriptor::isInductionPHI( ConstantInt *CV = ConstStep->getValue(); const DataLayout &DL = Phi->getModule()->getDataLayout(); - int64_t Size = static_cast<int64_t>(DL.getTypeAllocSize(ElementType)); - if (!Size) + TypeSize TySize = DL.getTypeAllocSize(ElementType); + // TODO: We could potentially support this for scalable vectors if we can + // prove at compile time that the constant step is always a multiple of + // the scalable type. + if (TySize.isZero() || TySize.isScalable()) return false; + int64_t Size = static_cast<int64_t>(TySize.getFixedSize()); int64_t CVSize = CV->getSExtValue(); if (CVSize % Size) return false; diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 4775340b3438..60895d3ced1a 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2588,8 +2588,14 @@ computePointerICmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, // numerous hazards. AliasAnalysis and its utilities rely on special rules // governing loads and stores which don't apply to icmps. Also, AliasAnalysis // doesn't need to guarantee pointer inequality when it says NoAlias. - Constant *LHSOffset = stripAndComputeConstantOffsets(DL, LHS); - Constant *RHSOffset = stripAndComputeConstantOffsets(DL, RHS); + + // Even if an non-inbounds GEP occurs along the path we can still optimize + // equality comparisons concerning the result. + bool AllowNonInbounds = ICmpInst::isEquality(Pred); + Constant *LHSOffset = + stripAndComputeConstantOffsets(DL, LHS, AllowNonInbounds); + Constant *RHSOffset = + stripAndComputeConstantOffsets(DL, RHS, AllowNonInbounds); // If LHS and RHS are related via constant offsets to the same base // value, we can replace it with an icmp which just compares the offsets. @@ -2659,17 +2665,6 @@ computePointerICmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, !CmpInst::isTrueWhenEqual(Pred)); } - // Even if an non-inbounds GEP occurs along the path we can still optimize - // equality comparisons concerning the result. We avoid walking the whole - // chain again by starting where the last calls to - // stripAndComputeConstantOffsets left off and accumulate the offsets. - Constant *LHSNoBound = stripAndComputeConstantOffsets(DL, LHS, true); - Constant *RHSNoBound = stripAndComputeConstantOffsets(DL, RHS, true); - if (LHS == RHS) - return ConstantExpr::getICmp(Pred, - ConstantExpr::getAdd(LHSOffset, LHSNoBound), - ConstantExpr::getAdd(RHSOffset, RHSNoBound)); - // If one side of the equality comparison must come from a noalias call // (meaning a system memory allocation function), and the other side must // come from a pointer that cannot overlap with dynamically-allocated diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 208f93aa1ac6..9e26f292b789 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -573,18 +573,48 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL, } SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { + unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType()); + + // Stripping pointer casts can strip address space casts which can change the + // index type size. The invariant is that we use the value type to determine + // the index type size and if we stripped address space casts we have to + // readjust the APInt as we pass it upwards in order for the APInt to match + // the type the caller passed in. + APInt Offset(InitialIntTyBits, 0); + V = V->stripAndAccumulateConstantOffsets( + DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true); + + // Later we use the index type size and zero but it will match the type of the + // value that is passed to computeImpl. IntTyBits = DL.getIndexTypeSizeInBits(V->getType()); Zero = APInt::getZero(IntTyBits); - V = V->stripPointerCasts(); + bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits; + if (!IndexTypeSizeChanged && Offset.isZero()) + return computeImpl(V); + + // We stripped an address space cast that changed the index type size or we + // accumulated some constant offset (or both). Readjust the bit width to match + // the argument index type size and apply the offset, as required. + SizeOffsetType SOT = computeImpl(V); + if (IndexTypeSizeChanged) { + if (knownSize(SOT) && !::CheckedZextOrTrunc(SOT.first, InitialIntTyBits)) + SOT.first = APInt(); + if (knownOffset(SOT) && !::CheckedZextOrTrunc(SOT.second, InitialIntTyBits)) + SOT.second = APInt(); + } + // If the computed offset is "unknown" we cannot add the stripped offset. + return {SOT.first, + SOT.second.getBitWidth() > 1 ? SOT.second + Offset : SOT.second}; +} + +SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) { if (Instruction *I = dyn_cast<Instruction>(V)) { // If we have already seen this instruction, bail out. Cycles can happen in // unreachable code after constant propagation. if (!SeenInsts.insert(I).second) return unknown(); - if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) - return visitGEPOperator(*GEP); return visit(*I); } if (Argument *A = dyn_cast<Argument>(V)) @@ -597,12 +627,6 @@ SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { return visitGlobalVariable(*GV); if (UndefValue *UV = dyn_cast<UndefValue>(V)) return visitUndefValue(*UV); - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { - if (CE->getOpcode() == Instruction::IntToPtr) - return unknown(); // clueless - if (CE->getOpcode() == Instruction::GetElementPtr) - return visitGEPOperator(cast<GEPOperator>(*CE)); - } LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V << '\n'); @@ -682,15 +706,6 @@ ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) { return unknown(); } -SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { - SizeOffsetType PtrData = compute(GEP.getPointerOperand()); - APInt Offset(DL.getIndexTypeSizeInBits(GEP.getPointerOperand()->getType()), 0); - if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(DL, Offset)) - return unknown(); - - return std::make_pair(PtrData.first, PtrData.second + Offset); -} - SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { if (GA.isInterposable()) return unknown(); diff --git a/llvm/lib/BinaryFormat/COFF.cpp b/llvm/lib/BinaryFormat/COFF.cpp new file mode 100644 index 000000000000..8fbee0218b79 --- /dev/null +++ b/llvm/lib/BinaryFormat/COFF.cpp @@ -0,0 +1,57 @@ +//===- llvm/BinaryFormat/COFF.cpp - The COFF format -----------------------===// +// +// 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/BinaryFormat/COFF.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" + +// Maximum offsets for different string table entry encodings. +enum : unsigned { Max7DecimalOffset = 9999999U }; +enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0 + +// Encode a string table entry offset in base 64, padded to 6 chars, and +// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ... +// Buffer must be at least 8 bytes large. No terminating null appended. +static void encodeBase64StringEntry(char *Buffer, uint64_t Value) { + assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset && + "Illegal section name encoding for value"); + + static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + Buffer[0] = '/'; + Buffer[1] = '/'; + + char *Ptr = Buffer + 7; + for (unsigned i = 0; i < 6; ++i) { + unsigned Rem = Value % 64; + Value /= 64; + *(Ptr--) = Alphabet[Rem]; + } +} + +bool llvm::COFF::encodeSectionName(char *Out, uint64_t Offset) { + if (Offset <= Max7DecimalOffset) { + // Offsets of 7 digits or less are encoded in ASCII. + SmallVector<char, COFF::NameSize> Buffer; + Twine('/').concat(Twine(Offset)).toVector(Buffer); + assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2); + std::memcpy(Out, Buffer.data(), Buffer.size()); + return true; + } + + if (Offset <= MaxBase64Offset) { + // Starting with 10,000,000, offsets are encoded as base64. + encodeBase64StringEntry(Out, Offset); + return true; + } + + // The offset is too large to be encoded. + return false; +} diff --git a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp index b901a2d2da23..249f02f36bae 100644 --- a/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp @@ -302,7 +302,8 @@ EPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr, return Alloc.takeError(); auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec); - ABI->writeResolverCode(SegInfo.WorkingMem.data(), SegInfo.Addr.getValue(), + ResolverBlockAddr = SegInfo.Addr.getValue(); + ABI->writeResolverCode(SegInfo.WorkingMem.data(), ResolverBlockAddr, ReentryFnAddr, ReentryCtxAddr); auto FA = Alloc->finalize(); @@ -310,7 +311,7 @@ EPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr, return FA.takeError(); ResolverBlock = std::move(*FA); - return SegInfo.Addr.getValue(); + return ResolverBlockAddr; } std::unique_ptr<IndirectStubsManager> diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp index 2399ea27ee9d..b8e3e40e4c1d 100644 --- a/llvm/lib/IR/Mangler.cpp +++ b/llvm/lib/IR/Mangler.cpp @@ -144,7 +144,7 @@ void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, // Mangle functions with Microsoft calling conventions specially. Only do // this mangling for x86_64 vectorcall and 32-bit x86. - const Function *MSFunc = dyn_cast<Function>(GV); + const Function *MSFunc = dyn_cast_or_null<Function>(GV->getAliaseeObject()); // Don't add byte count suffixes when '\01' or '?' are in the first // character. diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 73c687331d30..aba2ad315535 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -452,32 +452,6 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym, Sym->MC = &MCSym; } -// Maximum offsets for different string table entry encodings. -enum : unsigned { Max7DecimalOffset = 9999999U }; -enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0 - -// Encode a string table entry offset in base 64, padded to 6 chars, and -// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ... -// Buffer must be at least 8 bytes large. No terminating null appended. -static void encodeBase64StringEntry(char *Buffer, uint64_t Value) { - assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset && - "Illegal section name encoding for value"); - - static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - Buffer[0] = '/'; - Buffer[1] = '/'; - - char *Ptr = Buffer + 7; - for (unsigned i = 0; i < 6; ++i) { - unsigned Rem = Value % 64; - Value /= 64; - *(Ptr--) = Alphabet[Rem]; - } -} - void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { if (S.Name.size() <= COFF::NameSize) { std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); @@ -485,19 +459,8 @@ void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { } uint64_t StringTableEntry = Strings.getOffset(S.Name); - if (StringTableEntry <= Max7DecimalOffset) { - SmallVector<char, COFF::NameSize> Buffer; - Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer); - assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2); - std::memcpy(S.Header.Name, Buffer.data(), Buffer.size()); - return; - } - if (StringTableEntry <= MaxBase64Offset) { - // Starting with 10,000,000, offsets are encoded as base64. - encodeBase64StringEntry(S.Header.Name, StringTableEntry); - return; - } - report_fatal_error("COFF string table is greater than 64 GB."); + if (!COFF::encodeSectionName(S.Header.Name, StringTableEntry)) + report_fatal_error("COFF string table is greater than 64 GB."); } void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) { diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index c539c8617d99..ac5e51e47ddf 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -8990,12 +8990,13 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue Op, if (V.isUndef()) continue; else if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT || - !isa<ConstantSDNode>(V.getOperand(1))) { + !isa<ConstantSDNode>(V.getOperand(1)) || + V.getOperand(0).getValueType().isScalableVector()) { LLVM_DEBUG( dbgs() << "Reshuffle failed: " "a shuffle can only come from building a vector from " - "various elements of other vectors, provided their " - "indices are constant\n"); + "various elements of other fixed-width vectors, provided " + "their indices are constant\n"); return SDValue(); } @@ -9039,8 +9040,8 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue Op, for (auto &Src : Sources) { EVT SrcVT = Src.ShuffleVec.getValueType(); - uint64_t SrcVTSize = SrcVT.getFixedSizeInBits(); - if (SrcVTSize == VTSize) + TypeSize SrcVTSize = SrcVT.getSizeInBits(); + if (SrcVTSize == TypeSize::Fixed(VTSize)) continue; // This stage of the search produces a source with the same element type as @@ -9049,7 +9050,7 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue Op, unsigned NumSrcElts = VTSize / EltVT.getFixedSizeInBits(); EVT DestVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumSrcElts); - if (SrcVTSize < VTSize) { + if (SrcVTSize.getFixedValue() < VTSize) { assert(2 * SrcVTSize == VTSize); // We can pad out the smaller vector for free, so if it's part of a // shuffle... @@ -9059,7 +9060,7 @@ SDValue AArch64TargetLowering::ReconstructShuffle(SDValue Op, continue; } - if (SrcVTSize != 2 * VTSize) { + if (SrcVTSize.getFixedValue() != 2 * VTSize) { LLVM_DEBUG( dbgs() << "Reshuffle failed: result vector too small to extract\n"); return SDValue(); @@ -9732,6 +9733,10 @@ static SDValue constructDup(SDValue V, int Lane, SDLoc dl, EVT VT, if (ExtIdxInBits % CastedEltBitWidth != 0) return false; + // Can't handle cases where vector size is not 128-bit + if (!Extract.getOperand(0).getValueType().is128BitVector()) + return false; + // Update the lane value by offsetting with the scaled extract index. LaneC += ExtIdxInBits / CastedEltBitWidth; @@ -13676,8 +13681,10 @@ static SDValue performFpToIntCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); SDValue Op = N->getOperand(0); - if (!Op.getValueType().isVector() || !Op.getValueType().isSimple() || - Op.getOpcode() != ISD::FMUL) + if (!Op.getValueType().isSimple() || Op.getOpcode() != ISD::FMUL) + return SDValue(); + + if (!Op.getValueType().is64BitVector() && !Op.getValueType().is128BitVector()) return SDValue(); SDValue ConstVec = Op->getOperand(1); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index a9191924129c..ea9c1b620065 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2270,6 +2270,19 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned Opc) { case AArch64::LD1SW_D_IMM: case AArch64::LD1D_IMM: + case AArch64::LD2B_IMM: + case AArch64::LD2H_IMM: + case AArch64::LD2W_IMM: + case AArch64::LD2D_IMM: + case AArch64::LD3B_IMM: + case AArch64::LD3H_IMM: + case AArch64::LD3W_IMM: + case AArch64::LD3D_IMM: + case AArch64::LD4B_IMM: + case AArch64::LD4H_IMM: + case AArch64::LD4W_IMM: + case AArch64::LD4D_IMM: + case AArch64::ST1B_IMM: case AArch64::ST1B_H_IMM: case AArch64::ST1B_S_IMM: @@ -2281,6 +2294,19 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned Opc) { case AArch64::ST1W_D_IMM: case AArch64::ST1D_IMM: + case AArch64::ST2B_IMM: + case AArch64::ST2H_IMM: + case AArch64::ST2W_IMM: + case AArch64::ST2D_IMM: + case AArch64::ST3B_IMM: + case AArch64::ST3H_IMM: + case AArch64::ST3W_IMM: + case AArch64::ST3D_IMM: + case AArch64::ST4B_IMM: + case AArch64::ST4H_IMM: + case AArch64::ST4W_IMM: + case AArch64::ST4D_IMM: + case AArch64::LD1RB_IMM: case AArch64::LD1RB_H_IMM: case AArch64::LD1RB_S_IMM: @@ -2897,6 +2923,45 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale, MinOffset = -8; MaxOffset = 7; break; + case AArch64::LD2B_IMM: + case AArch64::LD2H_IMM: + case AArch64::LD2W_IMM: + case AArch64::LD2D_IMM: + case AArch64::ST2B_IMM: + case AArch64::ST2H_IMM: + case AArch64::ST2W_IMM: + case AArch64::ST2D_IMM: + Scale = TypeSize::Scalable(32); + Width = SVEMaxBytesPerVector * 2; + MinOffset = -8; + MaxOffset = 7; + break; + case AArch64::LD3B_IMM: + case AArch64::LD3H_IMM: + case AArch64::LD3W_IMM: + case AArch64::LD3D_IMM: + case AArch64::ST3B_IMM: + case AArch64::ST3H_IMM: + case AArch64::ST3W_IMM: + case AArch64::ST3D_IMM: + Scale = TypeSize::Scalable(48); + Width = SVEMaxBytesPerVector * 3; + MinOffset = -8; + MaxOffset = 7; + break; + case AArch64::LD4B_IMM: + case AArch64::LD4H_IMM: + case AArch64::LD4W_IMM: + case AArch64::LD4D_IMM: + case AArch64::ST4B_IMM: + case AArch64::ST4H_IMM: + case AArch64::ST4W_IMM: + case AArch64::ST4D_IMM: + Scale = TypeSize::Scalable(64); + Width = SVEMaxBytesPerVector * 4; + MinOffset = -8; + MaxOffset = 7; + break; case AArch64::LD1B_H_IMM: case AArch64::LD1SB_H_IMM: case AArch64::LD1H_S_IMM: diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 83bf89ff97c5..1316161f05f1 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -143,23 +143,23 @@ def HasSMEF64 : Predicate<"Subtarget->hasSMEF64()">, def HasSMEI64 : Predicate<"Subtarget->hasSMEI64()">, AssemblerPredicate<(all_of FeatureSMEI64), "sme-i64">; def HasStreamingSVE : Predicate<"Subtarget->hasStreamingSVE()">, - AssemblerPredicate<(all_of FeatureStreamingSVE), "streaming-sve">; + AssemblerPredicate<(all_of FeatureStreamingSVE), "sme">; // A subset of SVE(2) instructions are legal in Streaming SVE execution mode, // they should be enabled if either has been specified. def HasSVEorStreamingSVE : Predicate<"Subtarget->hasSVE() || Subtarget->hasStreamingSVE()">, AssemblerPredicate<(any_of FeatureSVE, FeatureStreamingSVE), - "streaming-sve or sve">; + "sve or sme">; def HasSVE2orStreamingSVE : Predicate<"Subtarget->hasSVE2() || Subtarget->hasStreamingSVE()">, AssemblerPredicate<(any_of FeatureSVE2, FeatureStreamingSVE), - "streaming-sve or sve2">; + "sve2 or sme">; // A subset of NEON instructions are legal in Streaming SVE execution mode, // they should be enabled if either has been specified. def HasNEONorStreamingSVE : Predicate<"Subtarget->hasNEON() || Subtarget->hasStreamingSVE()">, AssemblerPredicate<(any_of FeatureNEON, FeatureStreamingSVE), - "streaming-sve or neon">; + "neon or sme">; def HasRCPC : Predicate<"Subtarget->hasRCPC()">, AssemblerPredicate<(all_of FeatureRCPC), "rcpc">; def HasAltNZCV : Predicate<"Subtarget->hasAlternativeNZCV()">, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index eb52e4aa6273..b195b1f2556a 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -765,8 +765,19 @@ namespace llvm { /// then the VPERM for the shuffle. All in all a very slow sequence. TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override { - if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 && - VT.getScalarSizeInBits() % 8 == 0) + // Default handling for scalable and single-element vectors. + if (VT.isScalableVector() || VT.getVectorNumElements() == 1) + return TargetLoweringBase::getPreferredVectorAction(VT); + + // Split and promote vNi1 vectors so we don't produce v256i1/v512i1 + // types as those are only for MMA instructions. + if (VT.getScalarSizeInBits() == 1 && VT.getSizeInBits() > 16) + return TypeSplitVector; + if (VT.getScalarSizeInBits() == 1) + return TypePromoteInteger; + + // Widen vectors that have reasonably sized elements. + if (VT.getScalarSizeInBits() % 8 == 0) return TypeWidenVector; return TargetLoweringBase::getPreferredVectorAction(VT); } diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 95319d1b0b74..9a6ffb20615b 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -1607,9 +1607,11 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { return MatchOperand_Success; case AsmToken::Plus: Opcode = MCBinaryExpr::Add; + getLexer().Lex(); break; case AsmToken::Minus: Opcode = MCBinaryExpr::Sub; + getLexer().Lex(); break; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 97d24c8e9c0b..e7672a7652cd 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -7203,6 +7203,11 @@ static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)); if (!N0C || !N1C) return SDValue(); + // If N0C has multiple uses it's possible one of the cases in + // DAGCombiner::isMulAddWithConstProfitable will be true, which would result + // in an infinite loop. + if (!N0C->hasOneUse()) + return SDValue(); int64_t C0 = N0C->getSExtValue(); int64_t C1 = N1C->getSExtValue(); int64_t CA, CB; @@ -7443,6 +7448,8 @@ static SDValue combineMUL_VLToVWMUL_VL(SDNode *N, SelectionDAG &DAG, unsigned ExtOpc = IsSignExt ? RISCVISD::VSEXT_VL : RISCVISD::VZEXT_VL; if (Op0.getValueType() != NarrowVT) Op0 = DAG.getNode(ExtOpc, DL, NarrowVT, Op0, Mask, VL); + // vwmulsu requires second operand to be zero extended. + ExtOpc = IsVWMULSU ? RISCVISD::VZEXT_VL : ExtOpc; if (Op1.getValueType() != NarrowVT) Op1 = DAG.getNode(ExtOpc, DL, NarrowVT, Op1, Mask, VL); @@ -10459,7 +10466,18 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, } } - return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); + std::pair<Register, const TargetRegisterClass *> Res = + TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); + + // If we picked one of the Zfinx register classes, remap it to the GPR class. + // FIXME: When Zfinx is supported in CodeGen this will need to take the + // Subtarget into account. + if (Res.second == &RISCV::GPRF16RegClass || + Res.second == &RISCV::GPRF32RegClass || + Res.second == &RISCV::GPRF64RegClass) + return std::make_pair(Res.first, &RISCV::GPRRegClass); + + return Res; } unsigned diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a1c387574ebb..77c2e7d16990 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -54599,8 +54599,9 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, // In any sort of PIC mode addresses need to be computed at runtime by // adding in a register or some sort of table lookup. These can't - // be used as immediates. - if (Subtarget.isPICStyleGOT() || Subtarget.isPICStyleStubPIC()) + // be used as immediates. BlockAddresses are fine though. + if ((Subtarget.isPICStyleGOT() || Subtarget.isPICStyleStubPIC()) && + !isa<BlockAddressSDNode>(Op)) return; // If we are in non-pic codegen mode, we allow the address of a global (with diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index d66140a726f6..7bca2084c448 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -320,7 +320,8 @@ bool AA::getPotentialCopiesOfStoredValue( Value &Ptr = *SI.getPointerOperand(); SmallVector<Value *, 8> Objects; - if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, QueryingAA, &SI)) { + if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, QueryingAA, &SI, + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "Underlying objects stored into could not be determined\n";); return false; @@ -514,10 +515,10 @@ isPotentiallyReachable(Attributor &A, const Instruction &FromI, return true; }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; Result = !A.checkForAllCallSites(CheckCallSite, *FromFn, /* RequireAllCallSites */ true, - &QueryingAA, AllCallSitesKnown); + &QueryingAA, UsedAssumedInformation); if (Result) { LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI << " in @" << FromFn->getName() @@ -1277,7 +1278,7 @@ bool Attributor::checkForAllUses( bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, - bool &AllCallSitesKnown) { + bool &UsedAssumedInformation) { // We can try to determine information from // the call sites. However, this is only possible all call sites are known, // hence the function has internal linkage. @@ -1286,31 +1287,26 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, if (!AssociatedFunction) { LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP << "\n"); - AllCallSitesKnown = false; return false; } return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites, - &QueryingAA, AllCallSitesKnown); + &QueryingAA, UsedAssumedInformation); } bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const Function &Fn, bool RequireAllCallSites, const AbstractAttribute *QueryingAA, - bool &AllCallSitesKnown) { + bool &UsedAssumedInformation) { if (RequireAllCallSites && !Fn.hasLocalLinkage()) { LLVM_DEBUG( dbgs() << "[Attributor] Function " << Fn.getName() << " has no internal linkage, hence not all call sites are known\n"); - AllCallSitesKnown = false; return false; } - // If we do not require all call sites we might not see all. - AllCallSitesKnown = RequireAllCallSites; - SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses())); for (unsigned u = 0; u < Uses.size(); ++u) { const Use &U = *Uses[u]; @@ -1322,7 +1318,6 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser() << "\n"; }); - bool UsedAssumedInformation = false; if (isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation, /* CheckBBLivenessOnly */ true)) { LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n"); @@ -1795,7 +1790,7 @@ void Attributor::identifyDeadInternalFunctions() { if (!F) continue; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (checkForAllCallSites( [&](AbstractCallSite ACS) { Function *Callee = ACS.getInstruction()->getFunction(); @@ -1803,7 +1798,7 @@ void Attributor::identifyDeadInternalFunctions() { (Functions.count(Callee) && Callee->hasLocalLinkage() && !LiveInternalFns.count(Callee)); }, - *F, true, nullptr, AllCallSitesKnown)) { + *F, true, nullptr, UsedAssumedInformation)) { continue; } @@ -2290,9 +2285,9 @@ bool Attributor::isValidFunctionSignatureRewrite( } // Avoid callbacks for now. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr, - AllCallSitesKnown)) { + UsedAssumedInformation)) { LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n"); return false; } @@ -2305,7 +2300,6 @@ bool Attributor::isValidFunctionSignatureRewrite( // Forbid must-tail calls for now. // TODO: - bool UsedAssumedInformation = false; auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn); if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr, nullptr, {Instruction::Call}, @@ -2514,9 +2508,9 @@ ChangeStatus Attributor::rewriteFunctionSignatures( }; // Use the CallSiteReplacementCreator to create replacement call sites. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn, - true, nullptr, AllCallSitesKnown); + true, nullptr, UsedAssumedInformation); (void)Success; assert(Success && "Assumed call site replacement to succeed!"); diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 4e4f768ed2cb..61a973f869d4 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -32,6 +32,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Assumptions.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -260,17 +261,23 @@ static bool genericValueTraversal( StateTy &State, function_ref<bool(Value &, const Instruction *, StateTy &, bool)> VisitValueCB, - const Instruction *CtxI, bool UseValueSimplify = true, int MaxValues = 16, + const Instruction *CtxI, bool &UsedAssumedInformation, + bool UseValueSimplify = true, int MaxValues = 16, function_ref<Value *(Value *)> StripCB = nullptr, bool Intraprocedural = false) { - const AAIsDead *LivenessAA = nullptr; - if (IRP.getAnchorScope()) - LivenessAA = &A.getAAFor<AAIsDead>( - QueryingAA, - IRPosition::function(*IRP.getAnchorScope(), IRP.getCallBaseContext()), - DepClassTy::NONE); - bool AnyDead = false; + struct LivenessInfo { + const AAIsDead *LivenessAA = nullptr; + bool AnyDead = false; + }; + DenseMap<const Function *, LivenessInfo> LivenessAAs; + auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & { + LivenessInfo &LI = LivenessAAs[&F]; + if (!LI.LivenessAA) + LI.LivenessAA = &A.getAAFor<AAIsDead>(QueryingAA, IRPosition::function(F), + DepClassTy::NONE); + return LI; + }; Value *InitialV = &IRP.getAssociatedValue(); using Item = std::pair<Value *, const Instruction *>; @@ -320,7 +327,6 @@ static bool genericValueTraversal( // Look through select instructions, visit assumed potential values. if (auto *SI = dyn_cast<SelectInst>(V)) { - bool UsedAssumedInformation = false; Optional<Constant *> C = A.getAssumedConstant( *SI->getCondition(), QueryingAA, UsedAssumedInformation); bool NoValueYet = !C.hasValue(); @@ -341,12 +347,12 @@ static bool genericValueTraversal( // Look through phi nodes, visit all live operands. if (auto *PHI = dyn_cast<PHINode>(V)) { - assert(LivenessAA && - "Expected liveness in the presence of instructions!"); + LivenessInfo &LI = GetLivenessInfo(*PHI->getFunction()); for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) { BasicBlock *IncomingBB = PHI->getIncomingBlock(u); - if (LivenessAA->isEdgeDead(IncomingBB, PHI->getParent())) { - AnyDead = true; + if (LI.LivenessAA->isEdgeDead(IncomingBB, PHI->getParent())) { + LI.AnyDead = true; + UsedAssumedInformation |= !LI.LivenessAA->isAtFixpoint(); continue; } Worklist.push_back( @@ -358,7 +364,7 @@ static bool genericValueTraversal( if (auto *Arg = dyn_cast<Argument>(V)) { if (!Intraprocedural && !Arg->hasPassPointeeByValueCopyAttr()) { SmallVector<Item> CallSiteValues; - bool AllCallSitesKnown = true; + bool UsedAssumedInformation = false; if (A.checkForAllCallSites( [&](AbstractCallSite ACS) { // Callbacks might not have a corresponding call site operand, @@ -369,7 +375,7 @@ static bool genericValueTraversal( CallSiteValues.push_back({CSOp, ACS.getInstruction()}); return true; }, - *Arg->getParent(), true, &QueryingAA, AllCallSitesKnown)) { + *Arg->getParent(), true, &QueryingAA, UsedAssumedInformation)) { Worklist.append(CallSiteValues); continue; } @@ -377,7 +383,6 @@ static bool genericValueTraversal( } if (UseValueSimplify && !isa<Constant>(V)) { - bool UsedAssumedInformation = false; Optional<Value *> SimpleV = A.getAssumedSimplified(*V, QueryingAA, UsedAssumedInformation); if (!SimpleV.hasValue()) @@ -401,8 +406,10 @@ static bool genericValueTraversal( } while (!Worklist.empty()); // If we actually used liveness information so we have to record a dependence. - if (AnyDead) - A.recordDependence(*LivenessAA, QueryingAA, DepClassTy::OPTIONAL); + for (auto &It : LivenessAAs) + if (It.second.AnyDead) + A.recordDependence(*It.second.LivenessAA, QueryingAA, + DepClassTy::OPTIONAL); // All values have been visited. return true; @@ -412,6 +419,7 @@ bool AA::getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, SmallVectorImpl<Value *> &Objects, const AbstractAttribute &QueryingAA, const Instruction *CtxI, + bool &UsedAssumedInformation, bool Intraprocedural) { auto StripCB = [&](Value *V) { return getUnderlyingObject(V); }; SmallPtrSet<Value *, 8> SeenObjects; @@ -424,7 +432,7 @@ bool AA::getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, }; if (!genericValueTraversal<decltype(Objects)>( A, IRPosition::value(Ptr), QueryingAA, Objects, VisitValueCB, CtxI, - true, 32, StripCB, Intraprocedural)) + UsedAssumedInformation, true, 32, StripCB, Intraprocedural)) return false; return true; } @@ -570,9 +578,9 @@ static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA, return T->isValidState(); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true, - AllCallSitesKnown)) + UsedAssumedInformation)) S.indicatePessimisticFixpoint(); else if (T.hasValue()) S ^= *T; @@ -1246,11 +1254,13 @@ struct AAPointerInfoImpl // Run the user callback on all writes we cannot skip and return if that // succeeded for all or not. unsigned NumInterferingWrites = InterferingWrites.size(); - for (auto &It : InterferingWrites) + for (auto &It : InterferingWrites) { if (!DT || NumInterferingWrites > MaxInterferingWrites || - !CanSkipAccess(*It.first, It.second)) + !CanSkipAccess(*It.first, It.second)) { if (!UserCB(*It.first, It.second)) return false; + } + } return true; } @@ -1894,17 +1904,18 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) { return true; }; + bool UsedAssumedInformation = false; auto ReturnInstCB = [&](Instruction &I) { ReturnInst &Ret = cast<ReturnInst>(I); return genericValueTraversal<ReturnInst>( A, IRPosition::value(*Ret.getReturnValue()), *this, Ret, ReturnValueCB, - &I, /* UseValueSimplify */ true, /* MaxValues */ 16, + &I, UsedAssumedInformation, /* UseValueSimplify */ true, + /* MaxValues */ 16, /* StripCB */ nullptr, /* Intraprocedural */ true); }; // Discover returned values from all live returned instructions in the // associated function. - bool UsedAssumedInformation = false; if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret}, UsedAssumedInformation)) return indicatePessimisticFixpoint(); @@ -2420,8 +2431,10 @@ struct AANonNullFloating : public AANonNullImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -2499,14 +2512,15 @@ struct AANoRecurseFunction final : AANoRecurseImpl { DepClassTy::NONE); return NoRecurseAA.isKnownNoRecurse(); }; - bool AllCallSitesKnown; - if (A.checkForAllCallSites(CallSitePred, *this, true, AllCallSitesKnown)) { + bool UsedAssumedInformation = false; + if (A.checkForAllCallSites(CallSitePred, *this, true, + UsedAssumedInformation)) { // If we know all call sites and all are known no-recurse, we are done. // If all known call sites, which might not be all that exist, are known // to be no-recurse, we are not done but we can continue to assume // no-recurse. If one of the call sites we have not visited will become // live, another update is triggered. - if (AllCallSitesKnown) + if (!UsedAssumedInformation) indicateOptimisticFixpoint(); return ChangeStatus::UNCHANGED; } @@ -3146,10 +3160,10 @@ struct AANoAliasArgument final // If the argument is never passed through callbacks, no-alias cannot break // synchronization. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (A.checkForAllCallSites( [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this, - true, AllCallSitesKnown)) + true, UsedAssumedInformation)) return Base::updateImpl(A); // TODO: add no-alias but make sure it doesn't break synchronization by @@ -3727,9 +3741,8 @@ struct AAIsDeadReturned : public AAIsDeadValueImpl { return areAllUsesAssumedDead(A, *ACS.getInstruction()); }; - bool AllCallSitesKnown; if (!A.checkForAllCallSites(PredForCallSite, *this, true, - AllCallSitesKnown)) + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return ChangeStatus::UNCHANGED; @@ -3834,6 +3847,9 @@ struct AAIsDeadFunction : public AAIsDead { ChangeStatus updateImpl(Attributor &A) override; bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override { + assert(From->getParent() == getAnchorScope() && + To->getParent() == getAnchorScope() && + "Used AAIsDead of the wrong function"); return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To)); } @@ -4312,8 +4328,10 @@ struct AADereferenceableFloating : AADereferenceableImpl { }; DerefState T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<DerefState>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -4578,8 +4596,10 @@ struct AAAlignFloating : AAAlignImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); // TODO: If we know we visited all incoming values, thus no are assumed @@ -5359,7 +5379,9 @@ struct AAValueSimplifyImpl : AAValueSimplify { Value &Ptr = *L.getPointerOperand(); SmallVector<Value *, 8> Objects; - if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, AA, &L)) + bool UsedAssumedInformation = false; + if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, AA, &L, + UsedAssumedInformation)) return false; const auto *TLI = @@ -5371,7 +5393,6 @@ struct AAValueSimplifyImpl : AAValueSimplify { if (isa<ConstantPointerNull>(Obj)) { // A null pointer access can be undefined but any offset from null may // be OK. We do not try to optimize the latter. - bool UsedAssumedInformation = false; if (!NullPointerIsDefined(L.getFunction(), Ptr.getType()->getPointerAddressSpace()) && A.getAssumedSimplified(Ptr, AA, UsedAssumedInformation) == Obj) @@ -5477,14 +5498,14 @@ struct AAValueSimplifyArgument final : AAValueSimplifyImpl { // Generate a answer specific to a call site context. bool Success; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (hasCallBaseContext() && getCallBaseContext()->getCalledFunction() == Arg->getParent()) Success = PredForCallSite( AbstractCallSite(&getCallBaseContext()->getCalledOperandUse())); else Success = A.checkForAllCallSites(PredForCallSite, *this, true, - AllCallSitesKnown); + UsedAssumedInformation); if (!Success) if (!askSimplifiedValueForOtherAAs(A)) @@ -5754,8 +5775,10 @@ struct AAValueSimplifyFloating : AAValueSimplifyImpl { }; bool Dummy = false; + bool UsedAssumedInformation = false; if (!genericValueTraversal<bool>(A, getIRPosition(), *this, Dummy, VisitValueCB, getCtxI(), + UsedAssumedInformation, /* UseValueSimplify */ false)) if (!askSimplifiedValueForOtherAAs(A)) return indicatePessimisticFixpoint(); @@ -6026,13 +6049,13 @@ struct AAHeapToStackFunction final : public AAHeapToStack { else A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark); + const DataLayout &DL = A.getInfoCache().getDL(); Value *Size; Optional<APInt> SizeAPI = getSize(A, *this, AI); if (SizeAPI.hasValue()) { Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI); } else { LLVMContext &Ctx = AI.CB->getContext(); - auto &DL = A.getInfoCache().getDL(); ObjectSizeOpts Opts; ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts); SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB); @@ -6052,14 +6075,14 @@ struct AAHeapToStackFunction final : public AAHeapToStack { max(Alignment, MaybeAlign(AlignmentAPI.getValue().getZExtValue())); } - unsigned AS = cast<PointerType>(AI.CB->getType())->getAddressSpace(); - Instruction *Alloca = - new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment, - "", AI.CB->getNextNode()); + // TODO: Hoist the alloca towards the function entry. + unsigned AS = DL.getAllocaAddrSpace(); + Instruction *Alloca = new AllocaInst(Type::getInt8Ty(F->getContext()), AS, + Size, Alignment, "", AI.CB); if (Alloca->getType() != AI.CB->getType()) - Alloca = new BitCastInst(Alloca, AI.CB->getType(), "malloc_bc", - Alloca->getNextNode()); + Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast( + Alloca, AI.CB->getType(), "malloc_cast", AI.CB); auto *I8Ty = Type::getInt8Ty(F->getContext()); auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty); @@ -6167,7 +6190,8 @@ ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) { // branches etc. SmallVector<Value *, 8> Objects; if (!AA::getAssumedUnderlyingObjects(A, *DI.CB->getArgOperand(0), Objects, - *this, DI.CB)) { + *this, DI.CB, + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "[H2S] Unexpected failure in getAssumedUnderlyingObjects!\n"); @@ -6445,10 +6469,10 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { Optional<Type *> identifyPrivatizableType(Attributor &A) override { // If this is a byval argument and we know all the call sites (so we can // rewrite them), there is no need to check them explicitly. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (getIRPosition().hasAttr(Attribute::ByVal) && A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this, - true, AllCallSitesKnown)) + true, UsedAssumedInformation)) return getAssociatedValue().getType()->getPointerElementType(); Optional<Type *> Ty; @@ -6498,7 +6522,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { return !Ty.hasValue() || Ty.getValue(); }; - if (!A.checkForAllCallSites(CallSiteCheck, *this, true, AllCallSitesKnown)) + if (!A.checkForAllCallSites(CallSiteCheck, *this, true, + UsedAssumedInformation)) return nullptr; return Ty; } @@ -6545,9 +6570,9 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { return TTI->areTypesABICompatible( CB->getCaller(), CB->getCalledFunction(), ReplacementTypes); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!A.checkForAllCallSites(CallSiteCheck, *this, true, - AllCallSitesKnown)) { + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for " << Fn.getName() << "\n"); @@ -6674,7 +6699,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { }; if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true, - AllCallSitesKnown)) + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return ChangeStatus::UNCHANGED; @@ -7774,7 +7799,9 @@ void AAMemoryLocationImpl::categorizePtrValue( << getMemoryLocationsAsStr(State.getAssumed()) << "]\n"); SmallVector<Value *, 8> Objects; + bool UsedAssumedInformation = false; if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, *this, &I, + UsedAssumedInformation, /* Intraprocedural */ true)) { LLVM_DEBUG( dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"); @@ -8590,8 +8617,10 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { IntegerRangeState T(getBitWidth()); + bool UsedAssumedInformation = false; if (!genericValueTraversal<IntegerRangeState>(A, getIRPosition(), *this, T, VisitValueCB, getCtxI(), + UsedAssumedInformation, /* UseValueSimplify */ false)) return indicatePessimisticFixpoint(); @@ -9402,8 +9431,10 @@ struct AANoUndefFloating : public AANoUndefImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -9520,9 +9551,10 @@ struct AACallEdgesCallSite : public AACallEdgesImpl { // Process any value that we might call. auto ProcessCalledOperand = [&](Value *V) { bool DummyValue = false; + bool UsedAssumedInformation = false; if (!genericValueTraversal<bool>(A, IRPosition::value(*V), *this, DummyValue, VisitValue, nullptr, - false)) { + UsedAssumedInformation, false)) { // If we haven't gone through all values, assume that there are unknown // callees. setHasUnknownCallee(true, Change); @@ -9586,7 +9618,8 @@ struct AACallEdgesFunction : public AACallEdgesImpl { // Visit all callable instructions. bool UsedAssumedInformation = false; if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this, - UsedAssumedInformation)) { + UsedAssumedInformation, + /* CheckBBLivenessOnly */ true)) { // If we haven't looked at all call like instructions, assume that there // are unknown callees. setHasUnknownCallee(true, Change); @@ -9940,12 +9973,13 @@ struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl { return !getAssumed().empty() || !getKnown().empty(); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; // Get the intersection of all assumptions held by this node's predecessors. // If we don't know all the call sites then this is either an entry into the // call graph or an empty node. This node is known to only contain its own // assumptions and can be propagated to its successors. - if (!A.checkForAllCallSites(CallSitePred, *this, true, AllCallSitesKnown)) + if (!A.checkForAllCallSites(CallSitePred, *this, true, + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 213a998d5bba..e2f1944cee63 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1614,6 +1614,26 @@ static bool basicBlockCanReturn(BasicBlock &BB) { return none_of(BB, instructionDoesNotReturn); } +// FIXME: this doesn't handle recursion. +static bool canReturn(Function &F) { + SmallVector<BasicBlock *, 16> Worklist; + SmallPtrSet<BasicBlock *, 16> Visited; + + Visited.insert(&F.front()); + Worklist.push_back(&F.front()); + + do { + BasicBlock *BB = Worklist.pop_back_val(); + if (basicBlockCanReturn(*BB)) + return true; + for (BasicBlock *Succ : successors(BB)) + if (Visited.insert(Succ).second) + Worklist.push_back(Succ); + } while (!Worklist.empty()); + + return false; +} + // Set the noreturn function attribute if possible. static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallSet<Function *, 8> &Changed) { @@ -1622,9 +1642,7 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, F->doesNotReturn()) continue; - // The function can return if any basic blocks can return. - // FIXME: this doesn't handle recursion or unreachable blocks. - if (none_of(*F, basicBlockCanReturn)) { + if (!canReturn(*F)) { F->setDoesNotReturn(); Changed.insert(F); } diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index 520b6ebf9e74..5113c0c67acc 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -2119,6 +2119,8 @@ private: OMPRTL___kmpc_barrier_simple_generic); ExternalizationRAII ThreadId(OMPInfoCache, OMPRTL___kmpc_get_hardware_thread_id_in_block); + ExternalizationRAII NumThreads( + OMPInfoCache, OMPRTL___kmpc_get_hardware_num_threads_in_block); ExternalizationRAII WarpSize(OMPInfoCache, OMPRTL___kmpc_get_warp_size); registerAAs(IsModulePass); diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index ae636e7b61f7..c5c8e880eb3d 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -770,6 +770,10 @@ struct DSEState { /// Keep track of instructions (partly) overlapping with killing MemoryDefs per /// basic block. MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs; + // Check if there are root nodes that are terminated by UnreachableInst. + // Those roots pessimize post-dominance queries. If there are such roots, + // fall back to CFG scan starting from all non-unreachable roots. + bool AnyUnreachableExit; // Class contains self-reference, make sure it's not copied/moved. DSEState(const DSEState &) = delete; @@ -805,6 +809,10 @@ struct DSEState { // Collect whether there is any irreducible control flow in the function. ContainsIrreducibleLoops = mayContainIrreducibleControl(F, &LI); + + AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) { + return isa<UnreachableInst>(E->getTerminator()); + }); } /// Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p @@ -1508,54 +1516,56 @@ struct DSEState { CommonPred = PDT.findNearestCommonDominator(CommonPred, BB); } - // If CommonPred is in the set of killing blocks, just check if it - // post-dominates MaybeDeadAccess. - if (KillingBlocks.count(CommonPred)) { - if (PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) - return {MaybeDeadAccess}; - return None; - } - // If the common post-dominator does not post-dominate MaybeDeadAccess, // there is a path from MaybeDeadAccess to an exit not going through a // killing block. - if (PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) { - SetVector<BasicBlock *> WorkList; - - // If CommonPred is null, there are multiple exits from the function. - // They all have to be added to the worklist. - if (CommonPred) - WorkList.insert(CommonPred); - else - for (BasicBlock *R : PDT.roots()) + if (!PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) { + if (!AnyUnreachableExit) + return None; + + // Fall back to CFG scan starting at all non-unreachable roots if not + // all paths to the exit go through CommonPred. + CommonPred = nullptr; + } + + // If CommonPred itself is in the set of killing blocks, we're done. + if (KillingBlocks.count(CommonPred)) + return {MaybeDeadAccess}; + + SetVector<BasicBlock *> WorkList; + // If CommonPred is null, there are multiple exits from the function. + // They all have to be added to the worklist. + if (CommonPred) + WorkList.insert(CommonPred); + else + for (BasicBlock *R : PDT.roots()) { + if (!isa<UnreachableInst>(R->getTerminator())) WorkList.insert(R); + } - NumCFGTries++; - // Check if all paths starting from an exit node go through one of the - // killing blocks before reaching MaybeDeadAccess. - for (unsigned I = 0; I < WorkList.size(); I++) { - NumCFGChecks++; - BasicBlock *Current = WorkList[I]; - if (KillingBlocks.count(Current)) - continue; - if (Current == MaybeDeadAccess->getBlock()) - return None; + NumCFGTries++; + // Check if all paths starting from an exit node go through one of the + // killing blocks before reaching MaybeDeadAccess. + for (unsigned I = 0; I < WorkList.size(); I++) { + NumCFGChecks++; + BasicBlock *Current = WorkList[I]; + if (KillingBlocks.count(Current)) + continue; + if (Current == MaybeDeadAccess->getBlock()) + return None; - // MaybeDeadAccess is reachable from the entry, so we don't have to - // explore unreachable blocks further. - if (!DT.isReachableFromEntry(Current)) - continue; + // MaybeDeadAccess is reachable from the entry, so we don't have to + // explore unreachable blocks further. + if (!DT.isReachableFromEntry(Current)) + continue; - for (BasicBlock *Pred : predecessors(Current)) - WorkList.insert(Pred); + for (BasicBlock *Pred : predecessors(Current)) + WorkList.insert(Pred); - if (WorkList.size() >= MemorySSAPathCheckLimit) - return None; - } - NumCFGSuccess++; - return {MaybeDeadAccess}; + if (WorkList.size() >= MemorySSAPathCheckLimit) + return None; } - return None; + NumCFGSuccess++; } // No aliasing MemoryUses of MaybeDeadAccess found, MaybeDeadAccess is diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 25bf69729c70..644372483edd 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -666,19 +666,18 @@ static void inversePermutation(ArrayRef<unsigned> Indices, /// \returns inserting index of InsertElement or InsertValue instruction, /// using Offset as base offset for index. -static Optional<int> getInsertIndex(Value *InsertInst, unsigned Offset) { +static Optional<unsigned> getInsertIndex(Value *InsertInst, + unsigned Offset = 0) { int Index = Offset; if (auto *IE = dyn_cast<InsertElementInst>(InsertInst)) { if (auto *CI = dyn_cast<ConstantInt>(IE->getOperand(2))) { auto *VT = cast<FixedVectorType>(IE->getType()); if (CI->getValue().uge(VT->getNumElements())) - return UndefMaskElem; + return None; Index *= VT->getNumElements(); Index += CI->getZExtValue(); return Index; } - if (isa<UndefValue>(IE->getOperand(2))) - return UndefMaskElem; return None; } @@ -3848,13 +3847,9 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, // Check that we have a buildvector and not a shuffle of 2 or more // different vectors. ValueSet SourceVectors; - int MinIdx = std::numeric_limits<int>::max(); for (Value *V : VL) { SourceVectors.insert(cast<Instruction>(V)->getOperand(0)); - Optional<int> Idx = *getInsertIndex(V, 0); - if (!Idx || *Idx == UndefMaskElem) - continue; - MinIdx = std::min(MinIdx, *Idx); + assert(getInsertIndex(V) != None && "Non-constant or undef index?"); } if (count_if(VL, [&SourceVectors](Value *V) { @@ -3876,10 +3871,8 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, decltype(OrdCompare)> Indices(OrdCompare); for (int I = 0, E = VL.size(); I < E; ++I) { - Optional<int> Idx = *getInsertIndex(VL[I], 0); - if (!Idx || *Idx == UndefMaskElem) - continue; - Indices.emplace(*Idx, I); + unsigned Idx = *getInsertIndex(VL[I]); + Indices.emplace(Idx, I); } OrdersType CurrentOrder(VL.size(), VL.size()); bool IsIdentity = true; @@ -5006,12 +4999,10 @@ InstructionCost BoUpSLP::getEntryCost(const TreeEntry *E, SmallVector<int> PrevMask(NumElts, UndefMaskElem); Mask.swap(PrevMask); for (unsigned I = 0; I < NumScalars; ++I) { - Optional<int> InsertIdx = getInsertIndex(VL[PrevMask[I]], 0); - if (!InsertIdx || *InsertIdx == UndefMaskElem) - continue; - DemandedElts.setBit(*InsertIdx); - IsIdentity &= *InsertIdx - Offset == I; - Mask[*InsertIdx - Offset] = I; + unsigned InsertIdx = *getInsertIndex(VL[PrevMask[I]]); + DemandedElts.setBit(InsertIdx); + IsIdentity &= InsertIdx - Offset == I; + Mask[InsertIdx - Offset] = I; } assert(Offset < NumElts && "Failed to find vector index offset"); @@ -5685,42 +5676,41 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) { // to detect it as a final shuffled/identity match. if (auto *VU = dyn_cast_or_null<InsertElementInst>(EU.User)) { if (auto *FTy = dyn_cast<FixedVectorType>(VU->getType())) { - Optional<int> InsertIdx = getInsertIndex(VU, 0); - if (!InsertIdx || *InsertIdx == UndefMaskElem) - continue; - auto *It = find_if(FirstUsers, [VU](Value *V) { - return areTwoInsertFromSameBuildVector(VU, - cast<InsertElementInst>(V)); - }); - int VecId = -1; - if (It == FirstUsers.end()) { - VF.push_back(FTy->getNumElements()); - ShuffleMask.emplace_back(VF.back(), UndefMaskElem); - // Find the insertvector, vectorized in tree, if any. - Value *Base = VU; - while (isa<InsertElementInst>(Base)) { - // Build the mask for the vectorized insertelement instructions. - if (const TreeEntry *E = getTreeEntry(Base)) { - VU = cast<InsertElementInst>(Base); - do { - int Idx = E->findLaneForValue(Base); - ShuffleMask.back()[Idx] = Idx; - Base = cast<InsertElementInst>(Base)->getOperand(0); - } while (E == getTreeEntry(Base)); - break; + Optional<unsigned> InsertIdx = getInsertIndex(VU); + if (InsertIdx) { + auto *It = find_if(FirstUsers, [VU](Value *V) { + return areTwoInsertFromSameBuildVector(VU, + cast<InsertElementInst>(V)); + }); + int VecId = -1; + if (It == FirstUsers.end()) { + VF.push_back(FTy->getNumElements()); + ShuffleMask.emplace_back(VF.back(), UndefMaskElem); + // Find the insertvector, vectorized in tree, if any. + Value *Base = VU; + while (isa<InsertElementInst>(Base)) { + // Build the mask for the vectorized insertelement instructions. + if (const TreeEntry *E = getTreeEntry(Base)) { + VU = cast<InsertElementInst>(Base); + do { + int Idx = E->findLaneForValue(Base); + ShuffleMask.back()[Idx] = Idx; + Base = cast<InsertElementInst>(Base)->getOperand(0); + } while (E == getTreeEntry(Base)); + break; + } + Base = cast<InsertElementInst>(Base)->getOperand(0); } - Base = cast<InsertElementInst>(Base)->getOperand(0); + FirstUsers.push_back(VU); + DemandedElts.push_back(APInt::getZero(VF.back())); + VecId = FirstUsers.size() - 1; + } else { + VecId = std::distance(FirstUsers.begin(), It); } - FirstUsers.push_back(VU); - DemandedElts.push_back(APInt::getZero(VF.back())); - VecId = FirstUsers.size() - 1; - } else { - VecId = std::distance(FirstUsers.begin(), It); + ShuffleMask[VecId][*InsertIdx] = EU.Lane; + DemandedElts[VecId].setBit(*InsertIdx); + continue; } - int Idx = *InsertIdx; - ShuffleMask[VecId][Idx] = EU.Lane; - DemandedElts[VecId].setBit(Idx); - continue; } } @@ -6477,11 +6467,9 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) { Mask.swap(PrevMask); for (unsigned I = 0; I < NumScalars; ++I) { Value *Scalar = E->Scalars[PrevMask[I]]; - Optional<int> InsertIdx = getInsertIndex(Scalar, 0); - if (!InsertIdx || *InsertIdx == UndefMaskElem) - continue; - IsIdentity &= *InsertIdx - Offset == I; - Mask[*InsertIdx - Offset] = I; + unsigned InsertIdx = *getInsertIndex(Scalar); + IsIdentity &= InsertIdx - Offset == I; + Mask[InsertIdx - Offset] = I; } if (!IsIdentity || NumElts != NumScalars) { V = Builder.CreateShuffleVector(V, Mask); @@ -8349,6 +8337,8 @@ void SLPVectorizerPass::collectSeedInstructions(BasicBlock *BB) { bool SLPVectorizerPass::tryToVectorizePair(Value *A, Value *B, BoUpSLP &R) { if (!A || !B) return false; + if (isa<InsertElementInst>(A) || isa<InsertElementInst>(B)) + return false; Value *VL[] = {A, B}; return tryToVectorizeList(VL, R); } @@ -9323,21 +9313,22 @@ static Optional<unsigned> getAggregateSize(Instruction *InsertInst) { } while (true); } -static bool findBuildAggregate_rec(Instruction *LastInsertInst, +static void findBuildAggregate_rec(Instruction *LastInsertInst, TargetTransformInfo *TTI, SmallVectorImpl<Value *> &BuildVectorOpds, SmallVectorImpl<Value *> &InsertElts, unsigned OperandOffset) { do { Value *InsertedOperand = LastInsertInst->getOperand(1); - Optional<int> OperandIndex = getInsertIndex(LastInsertInst, OperandOffset); + Optional<unsigned> OperandIndex = + getInsertIndex(LastInsertInst, OperandOffset); if (!OperandIndex) - return false; + return; if (isa<InsertElementInst>(InsertedOperand) || isa<InsertValueInst>(InsertedOperand)) { - if (!findBuildAggregate_rec(cast<Instruction>(InsertedOperand), TTI, - BuildVectorOpds, InsertElts, *OperandIndex)) - return false; + findBuildAggregate_rec(cast<Instruction>(InsertedOperand), TTI, + BuildVectorOpds, InsertElts, *OperandIndex); + } else { BuildVectorOpds[*OperandIndex] = InsertedOperand; InsertElts[*OperandIndex] = LastInsertInst; @@ -9347,7 +9338,6 @@ static bool findBuildAggregate_rec(Instruction *LastInsertInst, (isa<InsertValueInst>(LastInsertInst) || isa<InsertElementInst>(LastInsertInst)) && LastInsertInst->hasOneUse()); - return true; } /// Recognize construction of vectors like @@ -9382,13 +9372,11 @@ static bool findBuildAggregate(Instruction *LastInsertInst, BuildVectorOpds.resize(*AggregateSize); InsertElts.resize(*AggregateSize); - if (findBuildAggregate_rec(LastInsertInst, TTI, BuildVectorOpds, InsertElts, - 0)) { - llvm::erase_value(BuildVectorOpds, nullptr); - llvm::erase_value(InsertElts, nullptr); - if (BuildVectorOpds.size() >= 2) - return true; - } + findBuildAggregate_rec(LastInsertInst, TTI, BuildVectorOpds, InsertElts, 0); + llvm::erase_value(BuildVectorOpds, nullptr); + llvm::erase_value(InsertElts, nullptr); + if (BuildVectorOpds.size() >= 2) + return true; return false; } diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp index cbd0e4261238..fcbfef96d860 100644 --- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp @@ -116,7 +116,7 @@ void COFFWriter::layoutSections() { } } -size_t COFFWriter::finalizeStringTable() { +Expected<size_t> COFFWriter::finalizeStringTable() { for (const auto &S : Obj.getSections()) if (S.Name.size() > COFF::NameSize) StrTabBuilder.add(S.Name); @@ -129,11 +129,16 @@ size_t COFFWriter::finalizeStringTable() { for (auto &S : Obj.getMutableSections()) { memset(S.Header.Name, 0, sizeof(S.Header.Name)); - if (S.Name.size() > COFF::NameSize) { - snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d", - (int)StrTabBuilder.getOffset(S.Name)); - } else { + if (S.Name.size() <= COFF::NameSize) { + // Short names can go in the field directly. memcpy(S.Header.Name, S.Name.data(), S.Name.size()); + } else { + // Offset of the section name in the string table. + size_t Offset = StrTabBuilder.getOffset(S.Name); + if (!COFF::encodeSectionName(S.Header.Name, Offset)) + return createStringError(object_error::invalid_section_index, + "COFF string table is greater than 64GB, " + "unable to encode section name offset"); } } for (auto &S : Obj.getMutableSymbols()) { @@ -219,7 +224,11 @@ Error COFFWriter::finalize(bool IsBigObj) { Obj.PeHeader.CheckSum = 0; } - size_t StrTabSize = finalizeStringTable(); + Expected<size_t> StrTabSizeOrErr = finalizeStringTable(); + if (!StrTabSizeOrErr) + return StrTabSizeOrErr.takeError(); + + size_t StrTabSize = *StrTabSizeOrErr; size_t PointerToSymbolTable = FileSize; // StrTabSize <= 4 is the size of an empty string table, only consisting diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h index eed43b3e5814..5758aadb5439 100644 --- a/llvm/tools/llvm-objcopy/COFF/Writer.h +++ b/llvm/tools/llvm-objcopy/COFF/Writer.h @@ -35,7 +35,7 @@ class COFFWriter { Error finalizeRelocTargets(); Error finalizeSymbolContents(); void layoutSections(); - size_t finalizeStringTable(); + Expected<size_t> finalizeStringTable(); Error finalize(bool IsBigObj); diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 04a67225401f..3d43d1a72e7e 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -2265,6 +2265,7 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type, case DT_MIPS_PLTGOT: case DT_MIPS_RWPLT: case DT_MIPS_RLD_MAP_REL: + case DT_MIPS_XHASH: return FormatHexValue(Value); case DT_MIPS_FLAGS: return FormatFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags)); diff --git a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp index 21339a3f8f3d..893d8a55c895 100644 --- a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -286,7 +286,7 @@ private: uintptr_t SlabSize = 0; uintptr_t CurrentSlabOffset = 0; SectionIDMap *SecIDMap = nullptr; -#if defined(__x86_64__) && defined(__ELF__) +#if defined(__x86_64__) && defined(__ELF__) && defined(__linux__) unsigned UsedTLSStorage = 0; #endif }; @@ -350,7 +350,7 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, // In case the execution needs TLS storage, we define a very small TLS memory // area here that will be used in allocateTLSSection(). -#if defined(__x86_64__) && defined(__ELF__) +#if defined(__x86_64__) && defined(__ELF__) && defined(__linux__) extern "C" { alignas(16) __attribute__((visibility("hidden"), tls_model("initial-exec"), used)) thread_local char LLVMRTDyldTLSSpace[16]; @@ -361,7 +361,7 @@ TrivialMemoryManager::TLSSection TrivialMemoryManager::allocateTLSSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) { -#if defined(__x86_64__) && defined(__ELF__) +#if defined(__x86_64__) && defined(__ELF__) && defined(__linux__) if (Size + UsedTLSStorage > sizeof(LLVMRTDyldTLSSpace)) { return {}; } |