Merge llvm-project release/14.x llvmorg-14.0.0-rc2-12-g09546e1b5103
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-14.0.0-rc2-12-g09546e1b5103. PR: 261742 MFC after: 2 weeks
This commit is contained in:
commit
d781ede639
@ -9,6 +9,7 @@
|
||||
CONTRIBUTING.md
|
||||
README.md
|
||||
SECURITY.md
|
||||
bolt/
|
||||
clang/.clang-format
|
||||
clang/.clang-tidy
|
||||
clang/.gitignore
|
||||
@ -106,6 +107,7 @@ clang/tools/clang-format/git-clang-format
|
||||
clang/tools/clang-format-vs/
|
||||
clang/tools/clang-fuzzer/
|
||||
clang/tools/clang-import-test/
|
||||
clang/tools/clang-linker-wrapper/
|
||||
clang/tools/clang-nvlink-wrapper/
|
||||
clang/tools/clang-offload-bundler/
|
||||
clang/tools/clang-offload-wrapper/
|
||||
@ -218,6 +220,8 @@ compiler-rt/lib/tsan/check_cmake.sh
|
||||
compiler-rt/lib/tsan/dd/CMakeLists.txt
|
||||
compiler-rt/lib/tsan/go/build.bat
|
||||
compiler-rt/lib/tsan/go/buildgo.sh
|
||||
compiler-rt/lib/tsan/rtl/CMakeLists.txt
|
||||
compiler-rt/lib/tsan/rtl-old/CMakeLists.txt
|
||||
compiler-rt/lib/tsan/tests/
|
||||
compiler-rt/lib/ubsan/CMakeLists.txt
|
||||
compiler-rt/lib/ubsan_minimal/CMakeLists.txt
|
||||
@ -256,6 +260,7 @@ libunwind/.clang-format
|
||||
libunwind/CMakeLists.txt
|
||||
libunwind/cmake/
|
||||
libunwind/docs/
|
||||
libunwind/include/CMakeLists.txt
|
||||
libunwind/src/CMakeLists.txt
|
||||
libunwind/test/
|
||||
lld/CMakeLists.txt
|
||||
@ -266,15 +271,8 @@ lld/MachO/CMakeLists.txt
|
||||
lld/MinGW/
|
||||
lld/cmake/
|
||||
lld/docs/CMakeLists.txt
|
||||
lld/lib/CMakeLists.txt
|
||||
lld/lib/Core/CMakeLists.txt
|
||||
lld/lib/Driver/CMakeLists.txt
|
||||
lld/lib/ReaderWriter/CMakeLists.txt
|
||||
lld/lib/ReaderWriter/MachO/CMakeLists.txt
|
||||
lld/lib/ReaderWriter/YAML/CMakeLists.txt
|
||||
lld/test/
|
||||
lld/tools/lld/CMakeLists.txt
|
||||
lld/unittests/
|
||||
lld/utils/
|
||||
lld/wasm/
|
||||
lldb/.clang-format
|
||||
@ -404,6 +402,7 @@ lldb/source/Plugins/Platform/Windows/
|
||||
lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/Linux/
|
||||
lldb/source/Plugins/Process/MacOSX-Kernel/
|
||||
lldb/source/Plugins/Process/NetBSD/CMakeLists.txt
|
||||
@ -448,6 +447,7 @@ lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt
|
||||
lldb/source/Symbol/CMakeLists.txt
|
||||
lldb/source/Target/CMakeLists.txt
|
||||
lldb/source/Utility/CMakeLists.txt
|
||||
lldb/source/Version/CMakeLists.txt
|
||||
lldb/test/
|
||||
lldb/third_party/
|
||||
lldb/tools/CMakeLists.txt
|
||||
@ -519,6 +519,7 @@ llvm/lib/DebugInfo/GSYM/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/MSF/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/PDB/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
|
||||
llvm/lib/Debuginfod/CMakeLists.txt
|
||||
llvm/lib/Demangle/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt
|
||||
@ -665,6 +666,7 @@ llvm/lib/Target/WebAssembly/Utils/CMakeLists.txt
|
||||
llvm/lib/Target/X86/AsmParser/CMakeLists.txt
|
||||
llvm/lib/Target/X86/CMakeLists.txt
|
||||
llvm/lib/Target/X86/Disassembler/CMakeLists.txt
|
||||
llvm/lib/Target/X86/MCA/CMakeLists.txt
|
||||
llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/X86/README-FPStack.txt
|
||||
llvm/lib/Target/X86/README-SSE.txt
|
||||
@ -722,6 +724,7 @@ llvm/tools/llvm-cvtres/
|
||||
llvm/tools/llvm-cxxdump/CMakeLists.txt
|
||||
llvm/tools/llvm-cxxfilt/CMakeLists.txt
|
||||
llvm/tools/llvm-cxxmap/CMakeLists.txt
|
||||
llvm/tools/llvm-debuginfod-find/
|
||||
llvm/tools/llvm-diff/CMakeLists.txt
|
||||
llvm/tools/llvm-diff/lib/CMakeLists.txt
|
||||
llvm/tools/llvm-dis/CMakeLists.txt
|
||||
@ -810,7 +813,6 @@ llvm/utils/UpdateCMakeLists.pl
|
||||
llvm/utils/UpdateTestChecks/
|
||||
llvm/utils/abtest.py
|
||||
llvm/utils/add_argument_names.py
|
||||
llvm/utils/benchmark/
|
||||
llvm/utils/bisect
|
||||
llvm/utils/bisect-skip-count
|
||||
llvm/utils/bugpoint/
|
||||
@ -850,6 +852,7 @@ llvm/utils/llvm-compilers-check
|
||||
llvm/utils/llvm-gisel-cov.py
|
||||
llvm/utils/llvm-lit/
|
||||
llvm/utils/llvm-locstats/
|
||||
llvm/utils/llvm-mca-compare.py
|
||||
llvm/utils/llvm-native-gxx
|
||||
llvm/utils/llvm-original-di-preservation.py
|
||||
llvm/utils/llvm.grm
|
||||
@ -910,4 +913,5 @@ openmp/tools/
|
||||
polly/
|
||||
pstl/
|
||||
runtimes/
|
||||
third-party/
|
||||
utils/
|
||||
|
@ -2461,10 +2461,10 @@ class FriendTemplateDecl : public Decl {
|
||||
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) {}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.");
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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")));
|
||||
|
@ -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")));
|
||||
|
@ -82,6 +82,10 @@ class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
|
||||
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;
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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 &) {}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -210,7 +210,6 @@ class ObjectSizeOffsetVisitor
|
||||
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 @@ class ObjectSizeOffsetVisitor
|
||||
SizeOffsetType visitInstruction(Instruction &I);
|
||||
|
||||
private:
|
||||
SizeOffsetType computeImpl(Value *V);
|
||||
bool CheckedZextOrTrunc(APInt &I);
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -148,7 +148,7 @@ class EPCIndirectionUtils {
|
||||
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;
|
||||
|
@ -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 @@ struct Attributor {
|
||||
/// 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.
|
||||
///
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
57
contrib/llvm-project/llvm/lib/BinaryFormat/COFF.cpp
Normal file
57
contrib/llvm-project/llvm/lib/BinaryFormat/COFF.cpp
Normal file
@ -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;
|
||||
}
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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()">,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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!");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -2119,6 +2119,8 @@ struct OpenMPOpt {
|
||||
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);
|
||||
|
@ -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 (!PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) {
|
||||
if (!AnyUnreachableExit)
|
||||
return None;
|
||||
|
||||
// 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())
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
if (WorkList.size() >= MemorySSAPathCheckLimit)
|
||||
return None;
|
||||
}
|
||||
NumCFGSuccess++;
|
||||
return {MaybeDeadAccess};
|
||||
// Fall back to CFG scan starting at all non-unreachable roots if not
|
||||
// all paths to the exit go through CommonPred.
|
||||
CommonPred = nullptr;
|
||||
}
|
||||
return None;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
|
||||
if (WorkList.size() >= MemorySSAPathCheckLimit)
|
||||
return None;
|
||||
}
|
||||
NumCFGSuccess++;
|
||||
}
|
||||
|
||||
// No aliasing MemoryUses of MaybeDeadAccess found, MaybeDeadAccess is
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -35,7 +35,7 @@ class COFFWriter {
|
||||
Error finalizeRelocTargets();
|
||||
Error finalizeSymbolContents();
|
||||
void layoutSections();
|
||||
size_t finalizeStringTable();
|
||||
Expected<size_t> finalizeStringTable();
|
||||
|
||||
Error finalize(bool IsBigObj);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -286,7 +286,7 @@ class TrivialMemoryManager : public RTDyldMemoryManager {
|
||||
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 {};
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// $FreeBSD$
|
||||
|
||||
#define LLVM_REVISION "llvmorg-14.0.0-rc1-74-g4dc3cb8e3255"
|
||||
#define LLVM_REVISION "llvmorg-14.0.0-rc2-12-g09546e1b5103"
|
||||
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||
|
||||
#define CLANG_REVISION "llvmorg-14.0.0-rc1-74-g4dc3cb8e3255"
|
||||
#define CLANG_REVISION "llvmorg-14.0.0-rc2-12-g09546e1b5103"
|
||||
#define CLANG_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||
|
||||
#define LLDB_REVISION "llvmorg-14.0.0-rc1-74-g4dc3cb8e3255"
|
||||
#define LLDB_REVISION "llvmorg-14.0.0-rc2-12-g09546e1b5103"
|
||||
#define LLDB_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Local identifier in __FreeBSD_version style
|
||||
#define LLD_FREEBSD_VERSION 1400003
|
||||
|
||||
#define LLD_VERSION_STRING "14.0.0 (FreeBSD llvmorg-14.0.0-rc1-74-g4dc3cb8e3255-" __XSTRING(LLD_FREEBSD_VERSION) ")"
|
||||
#define LLD_VERSION_STRING "14.0.0 (FreeBSD llvmorg-14.0.0-rc2-12-g09546e1b5103-" __XSTRING(LLD_FREEBSD_VERSION) ")"
|
||||
|
@ -1,3 +1,3 @@
|
||||
/* $FreeBSD$ */
|
||||
#define LLVM_REVISION "llvmorg-14.0.0-rc1-74-g4dc3cb8e3255"
|
||||
#define LLVM_REVISION "llvmorg-14.0.0-rc2-12-g09546e1b5103"
|
||||
#define LLVM_REPOSITORY "https://github.com/llvm/llvm-project.git"
|
||||
|
@ -151,6 +151,7 @@ SRCS_MIN+= AsmParser/LLLexer.cpp
|
||||
SRCS_MIN+= AsmParser/LLParser.cpp
|
||||
SRCS_MIN+= AsmParser/Parser.cpp
|
||||
SRCS_MIN+= BinaryFormat/AMDGPUMetadataVerifier.cpp
|
||||
SRCS_MIN+= BinaryFormat/COFF.cpp
|
||||
SRCS_MIN+= BinaryFormat/Dwarf.cpp
|
||||
SRCS_MIN+= BinaryFormat/Magic.cpp
|
||||
SRCS_MIN+= BinaryFormat/MachO.cpp
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
.include <bsd.init.mk>
|
||||
|
||||
LIB= clang_rt.asan-static-${CRTARCH}
|
||||
LIB= clang_rt.asan_static-${CRTARCH}
|
||||
|
||||
SRCS+= asan/asan_rtl_static.cpp
|
||||
SRCS+= asan/asan_rtl_x86_64.S
|
||||
|
Loading…
Reference in New Issue
Block a user