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:
Dimitry Andric 2022-03-05 15:16:17 +01:00
commit d781ede639
50 changed files with 582 additions and 339 deletions

View file

@ -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/

View file

@ -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) {}

View file

@ -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,

View file

@ -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.");

View file

@ -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);

View file

@ -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")));

View file

@ -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")));

View file

@ -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;

View file

@ -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)) {

View file

@ -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

View file

@ -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 &) {}
};

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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.

View file

@ -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.

View file

@ -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;

View file

@ -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.
///

View file

@ -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};

View file

@ -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;

View file

@ -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

View file

@ -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();

View 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;
}

View file

@ -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>

View file

@ -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.

View file

@ -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) {

View file

@ -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);

View file

@ -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:

View file

@ -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()">,

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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!");

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -35,7 +35,7 @@ class COFFWriter {
Error finalizeRelocTargets();
Error finalizeSymbolContents();
void layoutSections();
size_t finalizeStringTable();
Expected<size_t> finalizeStringTable();
Error finalize(bool IsBigObj);

View file

@ -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));

View file

@ -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 {};
}

View file

@ -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"

View file

@ -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) ")"

View file

@ -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"

View file

@ -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

View file

@ -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